Kommunikation mellan PICar

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Kommunikation mellan PICar

Inlägg av Pinkevin »

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?
gvs
EF Sponsor
Inlägg: 1688
Blev medlem: 18 oktober 2003, 14:20:34
Ort: Göteborg
Kontakt:

Inlägg av gvs »

Bygg ett vanligt serieprotokoll. Titta på piclist.com där finns massa kodexempel.
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Inlägg av Pinkevin »

Har kollat där, men hittar inget, tycker där är för rörigt.
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Enklast att få rätt är nog synkront med två sladdar (klock, data).

Om PICarna båda har en stabil klocka (kristall) så går det hyffsat enkelt att få ihop asynkront också (en sladd räcker för data åt ena hållet).
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Inlägg av Pinkevin »

Om man har en klocksignal också, vad ska den skicka isåfall, och hur ska den kunna stabilisera det hela?
PICarna jobbar ju fortfarande med samma hastighet som förr, även om man har en klocksignal som berättar hur snabbt den andra arbetar, eller?
Användarvisningsbild
mrmike
Inlägg: 301
Blev medlem: 29 oktober 2003, 20:40:12

Inlägg av mrmike »

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:

Kod: Markera allt

              ___     _______
data:     ___|   |___|       |_
           _   _   _   _   _
clock:    | |_| |_| |_| |_| |_|

resultat: 0   1   0   1   1   0
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Inlägg av Pinkevin »

Jaha, så klocksignalen berättar för slaven med vilken hastighet datan kommer?
Användarvisningsbild
Xyzzy
Inlägg: 1260
Blev medlem: 30 januari 2004, 22:31:07
Ort: Uppsala, Sweden

Inlägg av Xyzzy »

Njaee...
man skulle kunna säga så här:
När mottagaren får en positiv flank (sign. går från noll till ett) på klockingången så ska den läsa av datasignalen, sen vänta tills nästa positiva flank på klockingången kommer.
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Inlägg av Pinkevin »

Ah, såg inte att det var två ettor på raken.
Förstår nu.

Men hur gör jag för att "skicka" t ex 00000001 från portb.1 på ena PICen till porta.1 på andra PICen?

Och hur får man den andra PICen att lyssna efter inkommande data på en pinne?
Användarvisningsbild
Xyzzy
Inlägg: 1260
Blev medlem: 30 januari 2004, 22:31:07
Ort: Uppsala, Sweden

Inlägg av Xyzzy »

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
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Lite otestad asm-kod...

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
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...

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
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Inlägg av Pinkevin »

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
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.
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.
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.

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
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...

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
Tack så mycket, otroligt snällt av dig!
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.
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Inlägg av cyr »

Förslagsvis så gör man sändarkoden ovan till en subrutin "sendserial" och gör såhär när man vill skicka:

Kod: Markera allt

  movlw b'00000001'
  movwf databyte
  call sendserial
delay kan t.ex. vara en liten loop:

Kod: Markera allt

delay:
  movlw 10
  movwf delaycounter
dlywait:
  decfsz delaycounter
  goto dlywait
  return
Pinkevin
Inlägg: 285
Blev medlem: 1 januari 2004, 12:44:10
Ort: Norrtälje

Inlägg av Pinkevin »

Å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)?

Kod: Markera allt

delay: 
  Set w = 10
  Set delaycounter = w
dlywait: 
  If delaycounter != 0 Then
  Goto dlywait
  Else
  Return
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'?
Användarvisningsbild
mrmike
Inlägg: 301
Blev medlem: 29 oktober 2003, 20:40:12

Inlägg av mrmike »

jämför w med databyte, hoppa om samma:

Kod: Markera allt

subwf	databyte
bz		databyte_och_w_är_sammalika	;om databyte-w = 0 hoppa till...
bz k(branch on zero) gör ungefär så här:

Kod: Markera allt

btfsc	STATUS,Z
goto	k
sen finns bnz:

Kod: Markera allt

btfss	STATUS,Z
goto	k
Skriv svar