Kommunikation mellan PICar
Kommunikation mellan PICar
Går det att få två stycken PICar att kommunicera med varrandra?
Det jag vill göra är att jag har en PIC krets som har tre stycken switchar kopplade till sig.
Sedan har jag en annan PIC med 3 st lysdioder kopplade till sig.
Nu vill jag göra så att när jag trycker på sw1 så ska första PICen berätta för den andra PICen att knappen är nedtryckt, och då ska led1 lysa.
PICarna ska vara ihopkopplade med en kabel, möjligtvis två (1-wire/2-wire interface).
PICarna i fråga ska vara PIC16F84A (eller mindre).
Någon som kan hjälpa mig en bit på vägen med hur jag ska få PICarna att prata med varrandra?
Det jag vill göra är att jag har en PIC krets som har tre stycken switchar kopplade till sig.
Sedan har jag en annan PIC med 3 st lysdioder kopplade till sig.
Nu vill jag göra så att när jag trycker på sw1 så ska första PICen berätta för den andra PICen att knappen är nedtryckt, och då ska led1 lysa.
PICarna ska vara ihopkopplade med en kabel, möjligtvis två (1-wire/2-wire interface).
PICarna i fråga ska vara PIC16F84A (eller mindre).
Någon som kan hjälpa mig en bit på vägen med hur jag ska få PICarna att prata med varrandra?
Klocksignalen är oberoende av hur fort du kör PIC:arna(inte riktigt oberoende men ända...).
Mastern (den som har kontroll över klocksignalen) talar om för slaven att en ny bit finns på datalinan, då kan du ha olika hastigheter på PIC:arna så länge slaven hinner upptäcka förändringarna på klocksignalen.
Ungefär så här:
Mastern (den som har kontroll över klocksignalen) talar om för slaven att en ny bit finns på datalinan, då kan du ha olika hastigheter på PIC:arna så länge slaven hinner upptäcka förändringarna på klocksignalen.
Ungefär så här:
Kod: Markera allt
___ _______
data: ___| |___| |_
_ _ _ _ _
clock: | |_| |_| |_| |_| |_|
resultat: 0 1 0 1 1 0
Sända '00000001' ex:
sätt data till noll
skicka ut 7 pulser på klock-utgången
sätt data till ett
skicka ut en puls på klock-utgången
Ta emot:
loop(8ggr)
{
vänta på positiv flank på klocka
läs data
}
sätt ihop de olika data-bitarna till en byte (om det nu är nödvändigt)
använd byten på valfritt sätt
HAr inte de PICar du tänkt använd a(vilka är det föressten) hårdvaru UART (serie-interface) - eller I2C kanske lättare att använda ngn av dem
Kan inte gå in mycket mer i detalj i koden utan att veta vilket språk du vill använda
sätt data till noll
skicka ut 7 pulser på klock-utgången
sätt data till ett
skicka ut en puls på klock-utgången
Ta emot:
loop(8ggr)
{
vänta på positiv flank på klocka
läs data
}
sätt ihop de olika data-bitarna till en byte (om det nu är nödvändigt)
använd byten på valfritt sätt
HAr inte de PICar du tänkt använd a(vilka är det föressten) hårdvaru UART (serie-interface) - eller I2C kanske lättare att använda ngn av dem

Kan inte gå in mycket mer i detalj i koden utan att veta vilket språk du vill använda
Lite otestad asm-kod...
Sändare: Datan skickas på PORTB1 och klockan på PORTB0.
En byte skickas med minst värda biten först.
På mottagaren kan man t.ex. aktivera interrupt på stigande flank på PORTB0 (det finns väl på F84, eller yrar jag?). Då kan man göra vad man vill på mottagar-picen och så när den första stigande flanken på klockan kommer så hoppar den till interrupt-rutinen som tar emot en byte och gör något med den...
Interrupt-rutinen (exklusive save/restore och så som alltid ska finnas med).
Om nu mottagar-picen inte gör något annat så kan man loopa den här koden hela tiden...
Sändare: Datan skickas på PORTB1 och klockan på PORTB0.
En byte skickas med minst värda biten först.
Kod: Markera allt
; loopa 8 ggr (8 bitar)
movlw 8
movwf counter
sendloop:
; "kopiera" en bit från databyte till pinnen
bcf PORTB,1
btfsc databyte,0
bsf PORTB,1
; shifta databyte ett steg
rrf databyte,f
; dra klockpinnen hög
bsf PORTB,0
; vänta lite så mottagaren hinner med
call delay
; dra klockpinnen låg
bcf PORTB,0
call delay
; loopa...
decfsz counter
goto sendloop
Interrupt-rutinen (exklusive save/restore och så som alltid ska finnas med).
Om nu mottagar-picen inte gör något annat så kan man loopa den här koden hela tiden...
Kod: Markera allt
; loopa 8 ggr...
movlw 8
movwf counter
recvloop:
; vänta tills klockan är hög
btfss PORTB,0
goto recvloop
; shifta databyte ett steg
rrf databyte,f
; "kopiera" en bit från pinnen till databyte
bcf databyte,7
btfsc PORTB,1
bsf databyte,7
; vänta tills klockan går låg igen
wait:
btfsc PORTB,0
goto wait
; loopa...
decfsz counter
goto recvloop
; anropa en funktion som gör nåt med datan vi fått...
call do_something
Jag har tänkt använda PIC16F84A, eller iaf någon PIC som JDM programmeraren klarar av, eftersom att det är en sån jag har.Xyzzy skrev:Sända '00000001' ex:
sätt data till noll
skicka ut 7 pulser på klock-utgången
sätt data till ett
skicka ut en puls på klock-utgången
Ta emot:
loop(8ggr)
{
vänta på positiv flank på klocka
läs data
}
sätt ihop de olika data-bitarna till en byte (om det nu är nödvändigt)
använd byten på valfritt sätt
HAr inte de PICar du tänkt använd a(vilka är det föressten) hårdvaru UART (serie-interface) - eller I2C kanske lättare att använda ngn av dem
Kan inte gå in mycket mer i detalj i koden utan att veta vilket språk du vill använda
Har försökt hitta något intressant om I2C på piclist, men har ej funnit något av instresse.
Nope, inga hårdvaru UART i de kretsar som stödjs av JDM vad jag vet.
JAL, Pic Basic eller Asm går bra, eftersom att jag förstår dessa relativt bra, och har kompilatorer till dem.
Tack så mycket, otroligt snällt av dig!cyr skrev:Lite otestad asm-kod...
Sändare: Datan skickas på PORTB1 och klockan på PORTB0.
En byte skickas med minst värda biten först.På mottagaren kan man t.ex. aktivera interrupt på stigande flank på PORTB0 (det finns väl på F84, eller yrar jag?). Då kan man göra vad man vill på mottagar-picen och så när den första stigande flanken på klockan kommer så hoppar den till interrupt-rutinen som tar emot en byte och gör något med den...Kod: Markera allt
; loopa 8 ggr (8 bitar) movlw 8 movwf counter sendloop: ; "kopiera" en bit från databyte till pinnen bcf PORTB,1 btfsc databyte,0 bsf PORTB,1 ; shifta databyte ett steg rrf databyte,f ; dra klockpinnen hög bsf PORTB,0 ; vänta lite så mottagaren hinner med call delay ; dra klockpinnen låg bcf PORTB,0 call delay ; loopa... decfsz counter goto sendloop
Interrupt-rutinen (exklusive save/restore och så som alltid ska finnas med).
Om nu mottagar-picen inte gör något annat så kan man loopa den här koden hela tiden...
Kod: Markera allt
; loopa 8 ggr... movlw 8 movwf counter recvloop: ; vänta tills klockan är hög btfss PORTB,0 goto recvloop ; shifta databyte ett steg rrf databyte,f ; "kopiera" en bit från pinnen till databyte bcf databyte,7 btfsc PORTB,1 bsf databyte,7 ; vänta tills klockan går låg igen wait: btfsc PORTB,0 goto wait ; loopa... decfsz counter goto recvloop ; anropa en funktion som gör nåt med datan vi fått... call do_something
Har några frågor om koden.
Vart definierar man innehållet i databyte?
Vart får man delay'en ifrån i sändarkoden (det finns ingen rutin som heter delay i sändarkoden)?
Och, hur gör jag sedan för att jämföra innehållet i databyte med säg 00000001?
Ser att cmp inte finns med som instruktion i 16F84A, och troligen inte i någon annan PIC krets heller.
Förslagsvis så gör man sändarkoden ovan till en subrutin "sendserial" och gör såhär när man vill skicka:
delay kan t.ex. vara en liten loop:
Kod: Markera allt
movlw b'00000001'
movwf databyte
call sendserial
Kod: Markera allt
delay:
movlw 10
movwf delaycounter
dlywait:
decfsz delaycounter
goto dlywait
return
Åh, det börjar arta sig 
Som du kanske förstår så har jag inte den största kunskapen om asm, så hoppas inte att jag verkar tjatig.
Har inte databladet till hands nu, så jag är inte hundra på vad delay'en gör, men är det ungefär såhär (pseudo kod)?
Hur gör man sen när mottagaren fått innehållet i databyte?
Hur ska man kunna jämföra innehållet i databyte med någonting, exempelvis b'00000001'?

Som du kanske förstår så har jag inte den största kunskapen om asm, så hoppas inte att jag verkar tjatig.
Har inte databladet till hands nu, så jag är inte hundra på vad delay'en gör, men är det ungefär såhär (pseudo kod)?
Kod: Markera allt
delay:
Set w = 10
Set delaycounter = w
dlywait:
If delaycounter != 0 Then
Goto dlywait
Else
Return
Hur ska man kunna jämföra innehållet i databyte med någonting, exempelvis b'00000001'?
jämför w med databyte, hoppa om samma:bz k(branch on zero) gör ungefär så här:
sen finns bnz:
Kod: Markera allt
subwf databyte
bz databyte_och_w_är_sammalika ;om databyte-w = 0 hoppa till...
Kod: Markera allt
btfsc STATUS,Z
goto k
Kod: Markera allt
btfss STATUS,Z
goto k