Referència | Trucs | Perifèrics | Recursos CITCEA | |
Tutorial | Exemples | Projectes | Inici |
En aquest exemple volem comunicar dos microcontroladors per radiofreqüència.
Ens basarem en l'exemple EA. A l'emissor hi tindrem el programa d'aquest exemple però, addicionalment, enviarem per radiofreqüència el mateix valor que enviem als LED. En el receptor, rebrem el valor i el mostrarem als LED. Així doncs, els LED de les dues plaques tindran la mateixa combinació que podrem variar amb el potenciòmetre de la targeta emissora.
Per evitar saturar el canal de ràdio, esperarem 0,6 s entre una lectura i la següent.
L'emissor estarà connectat a RB4 i el receptor a RB6. Fem servir potes diferents perquè en cas de voler implementar un enllaç bidireccional tindríem emissor i receptor en el mateix microcontrolador.
Els programes es podrien fer servir també per a comunicació per cable. Si comuniquem per cable, podem emprar un filtre més acurat, com hem comentat a radiofreqüència.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Port ; Variable per al contingut del port B ; que permet modificar els bits individualment Comp_bits ; Variable per comptar bits Comp_bytes ; Variable per comptar bytes Control ; Variable per calcular el byte de control Retard ; Comptador per al retard Byte ; Variable de treball per enviar un byte Bytes ; Número de bytes que voldrem enviar ; Un paquet tindrà aquests i el byte de control Ret:3 ; Tres variables per a bucles de retard Vector ; Lloc on es guardaran els bytes a enviar ; Després d'aquesta ja no es poden declarar més variables ; ja que el vector tindrà tantes posicions com hi digui a Bytes ; més una per al byte de control endc
org 0 Inici bsf STATUS,RP0 ; Tria el banc 1 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf TRISA ; Posa tots els bits del port A com a entrada clrf TRISB ; Posa tots els bits del port B com a sortida clrf TRISC ; Posa tots els bits del port C com a sortida movlw b'00010000' ; Posa el conversor a 1/8 de la freqüència movwf ADCON1 ; Copia W a la configuració del conversor A/D bcf STATUS,RP0 bsf STATUS,RP1 ; Tria el banc 2 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf ANSEL ; Configura AN0-AN7 com entrades analògiques bcf STATUS,RP0 bcf STATUS,RP1 ; Tria el banc 0 movlw 0 ; Inicialment totes les sortides desactivades movwf Port ; Ho guardem a Port movwf PORTB ; I ho copiem al port B movlw .2 ; Número de bytes que volem enviar movwf Bytes ; Ho guardem a Bytes movlw 0x93 ; Codi d'identificació movwf Vector ; El guarda sobre el primer byte de dades que enviarem movlw b'00000001' ; activa el conversor A/D connectat a AN0 movwf ADCON0 ; amb el resultat justificat per l'esquerra Bucle nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon, en total 5 bsf ADCON0,GO ; Inicia la conversió btfsc ADCON0,GO ; Quan el bit sigui 0 la conversió haurà acabat goto $-1 ; repetim la línia fins que deixi de ser 1 swapf ADRESH,w ; Permuta els nibbles dels bits superiors movwf PORTC ; Copia el resultat sobre els LED movwf Vector+1 ; i sobre el segon byte de dades que enviarem call Envia ; Envia la dada movlw .3 ; Bucle de retard de 3 * 0,2 = 0,6 s movwf Ret+2 Bucles decfsz Ret,f goto Bucles decfsz Ret+1,f goto Bucles decfsz Ret+2,f goto Bucles goto Bucle
; ; Funció per enviar un paquet ; Envia ; Comencem calculant el byte de control ; Hem de sumar (sense portar-ne) tots els bytes clrf Control ; El posem a zero movf Bytes,w ; Llegim el número de bytes que volem enviar movwf Comp_bytes ; Ho guardem al comptador de bytes movlw Vector ; Llegim l'adreça de Vector movwf FSR ; Ho posem al punter d'adreçament indirecte movlw 0 ; L'acumulador contindrà la suma, comencem a 0 addwf INDF,w ; Hi sumem un dels bytes incf FSR,f ; Desplaça el punter decfsz Comp_bytes,f ; Byte següent goto $-3 ; Si no és el darrer, seguim ; Ja tenim la suma, ara ho restem (sense portar-ne) de Control (= 0) subwf Control,w ; W = Control - suma movwf INDF ; Ho guarda al final del Vector ; Comencem a enviar ; Primer cal enviar la capçalera movlw .15 ; Primer 15 bits a 1 movwf Comp_bits ; Ho guarda al comptador de bits call Envia_1 ; Envia un 1 decfsz Comp_bits,f ; Decrementa els bits pendents goto $-2 ; Repeteix fins que s'acabi call Envia_0 ; Finalment un bit a 0 ; Després cal enviar els bytes movf Bytes,w ; Llegim el número de bytes que volem enviar movwf Comp_bytes ; Ho guardem al comptador de bytes incf Comp_bytes,f ; Incrementa el comptador de bytes per afegir el byte de control movlw Vector ; Llegim l'adreça de Vector movwf FSR ; Ho posem al punter d'adreçament indirecte TI movf INDF,w ; Agafa un dels bytes movwf Byte ; Ho guarda a la variable de treball movlw .8 ; Un byte són 8 bits movwf Comp_bits ; Ho guarda al comptador de bits TR rlf Byte,f ; El bit de més a l'esquerra passa a C btfss STATUS,C ; Mira sí és 0 goto T0 ; Sí, envia un 0 call Envia_1 ; No, envia un 1 goto TF T0 call Envia_0 ; Envia un 0 TF decfsz Comp_bits,f ; Següent bit goto TR ; Al final de cada byte s'envia un 1 i un 0 call Envia_1 ; Envia un 1 call Envia_0 ; Envia un 0 incf FSR,f ; Desplaça el punter decfsz Comp_bytes,f ; Byte següent goto TI bcf Port,4 ; Desactiva l'emissor movf Port,w ; Ho canviem a Port movwf PORTB ; I ho copiem al port B return Envia_0 ; Funció per enviar un 0 bsf Port,4 ; Un bit 0 comença amb 1 movf Port,w ; Ho canviem a Port movwf PORTB ; I ho copiem al port B movlw .166 ; Cada dec són 1 us i cada goto són 2 us movwf Retard ; 165 * 3 (a la darrera no hi ha goto) dona 495 decfsz Retard,f ; que amb els 4 dels mov i 1 del dec goto $-1 ; fem 500 us bcf Port,4 ; I canvia a 0 a mig bit movf Port,w ; Ho canviem a Port movwf PORTB ; I ho copiem al port B movlw .166 ; Cada dec són 1 us i cada goto són 2 us movwf Retard ; 165 * 3 (a la darrera no hi ha goto) dona 495 decfsz Retard,f ; que amb els 4 dels mov i 1 del dec goto $-1 ; fem 500 us return ; 0 enviat Envia_1 ; Funció per enviar un 1 bcf Port,4 ; Un bit 1 comença amb 0 movf Port,w ; Ho canviem a Port movwf PORTB ; I ho copiem al port B movlw .166 ; Cada dec són 1 us i cada goto són 2 us movwf Retard ; 165 * 3 (a la darrera no hi ha goto) dona 495 decfsz Retard,f ; que amb els 4 dels mov i 1 del dec goto $-1 ; fem 500 us bsf Port,4 ; I canvia a 1 a mig bit movf Port,w ; Ho canviem a Port movwf PORTB ; I ho copiem al port B movlw .166 ; Cada dec són 1 us i cada goto són 2 us movwf Retard ; 165 * 3 (a la darrera no hi ha goto) dona 495 decfsz Retard,f ; que amb els 4 dels mov i 1 del dec goto $-1 ; fem 500 us return ; 1 enviat end
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Estat ; Variable per memoritzar estats Comp_bits ; Variable per comptar bits Comp_bytes ; Variable per comptar bytes Byte ; Variable temporal per construir un byte Bytes ; Número de bytes que rebrem Temps ; Variable per comptar el temps minS ; Valor mínim per a la durada d'un semiperíode maxS ; Valor màxim per a la durada d'un semiperíode minP ; Valor mínim per a la durada d'un període maxP ; Valor màxim per a la durada d'un període Vector ; Lloc on es guardaran els bytes rebuts ; Després d'aquesta ja no es poden declarar més variables ; ja que el vector tindrà tantes posicions com hi digui a Bytes ; més una per al byte de control endc
org 0 Inici ; Comencem amb la inicialització bsf STATUS,RP0 ; Tria el banc 1 movlw b'01000000' ; RB6 és entrada, la resta del port B és sortida movwf TRISB clrf TRISC ; Posa tots els bits del port C com a sortida movlw b'10000010' ; Configuració de Timer0 ; Com a temporitzador basat en rellotge ; 010 - Factor d'escala de 8 ; TMR0 s'incrementarà cada 8 us ; I resistències de pull-up desactivades (valor per defecte) movwf OPTION_REG ; Ho guarda al registre de configuració del Timer0 bcf STATUS,RP0 ; Tria el banc 0 ; Inicialització de variables clrf Estat ; De moment, desactiva tots els bits d'estat movlw .3 ; Número de bytes que rebrem movwf Bytes ; Ho guardem a Bytes ; Semiperíode de 500 us ; Marge d'error: 30 % 500 * 0,3 = 150 movlw .43 ; (500 - 150)/8 movwf minS ; Valor mínim per a la durada d'un semiperíode movlw .82 ; (500 + 150)/8 movwf maxS ; Valor màxim per a la durada d'un semiperíode movlw .87 ; 2 * (500 - 150)/8 movwf minP ; Valor mínim per a la durada d'un període movlw .163 ; 2 * (500 + 150)/8 movwf maxP ; Valor màxim per a la durada d'un període clrf PORTC ; Comencem amb els LED apagats Bucle call Rebre ; Espera que arribi un paquet andlw 0xFF ; Anem a veure si W és zero btfss STATUS,Z ; Si és zero, and donarà zero goto Bucle ; No és zero, esperem un altre paquet movlw 0x93 ; Sí és zero, anem a veure el Codi d'identificació xorwf Vector,w ; Compara amb el codi d'identificació btfss STATUS,Z ; Si Z = 1 es que són iguals goto Bucle ; Z = 0, esperem un altre paquet movf Vector+1,w ; Agafem el byte de dades movwf PORTC ; i el copia sobre els LED goto Bucle ; Acabat, esperem un altre paquet
; ; Funció per rebre un paquet ; Rebre ; Comencem inicialitzant variables movlw Vector ; Carreguem l'adreça del lloc on es guardaran els bytes rebuts movwf FSR ; Punter per a l'adreçament indirecte clrf Comp_bits ; Posem a zero la variable que compta els bits rebuts movf Bytes,w ; Número de bytes que rebrem movwf Comp_bytes ; Variable de comptatge bsf Estat,5 ; Cap = 1 ; Ara esperem la primera activació (primer 1) btfss PORTB,6 ; S'ha activat l'entrada? goto $-1 ; No, doncs esperem clrf TMR0 ; Sí, comencem a comptar el temps Espera ; Esperem a que es desactivi l'entrada btfss PORTB,6 ; S'ha desactivat l'entrada? goto PrimerBit ; Sí, doncs el primer bit ja està movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movf maxS,w ; Mirem que no passem de maxS subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= maxS goto Espera ; És més petit, seguim esperant retlw .129 ; És més gran: Error 129 - Bit d'inici massa llarg PrimerBit ; El primer bit ja està movf TMR0,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR0 ; Comencem a comptar el temps movf minS,w ; Mirem que no sigui menor que minS subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= minS retlw .130 ; És més petit: Error 130 - Bit d'inici massa curt incf Comp_bits,f ; Ja tenim un bit bsf Estat,6 ; Pre = 1 bcf Estat,7 ; Rebut = 0 SegTran ; Esperem al següent canvi a l'entrada btfsc Estat,7 ; Quin és el darrer valor de l'entrada? goto Espera0 ; 1, doncs hem de rebre un 0 goto Espera1 ; 0, doncs hem de rebre un 1 Espera0 ; Esperem que es desactivi l'entrada btfss PORTB,6 ; S'ha desactivat l'entrada? goto Canvi ; Sí movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movf maxP,w ; Mirem que no passem de maxP subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= maxP goto Espera0 ; És més petit, seguim esperant retlw .17 ; És més gran: Error 17 - Període massa llarg Espera1 ; Esperem que s'activi l'entrada btfsc PORTB,6 ; S'ha activat l'entrada? goto Canvi ; Sí movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movf maxP,w ; Mirem que no passem de maxP subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= maxP goto Espera1 ; És més petit, seguim esperant retlw .17 ; És més gran: Error 17 - Període massa llarg Canvi ; L'entrada ja ha canviat movf TMR0,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR0 ; Comencem a comptar el temps movf minS,w ; Mirem que no sigui menor que minS subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= minS retlw .18 ; És més petit: Error 18 - Semiperíode massa curt movlw b'10000000' ; Invertim bit 7 xorwf Estat,f ; o sigui, invertim Rebut movf maxS,w ; Mirem si és més gran que maxS subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= maxS goto Curt ; És més petit, és un pols curt movf minP,w ; També mirem si és més gran que minP subwf Temps,w ; W = Temps - W btfsc STATUS,C ; C = 1 si Temps >= minP goto Llarg ; És més gran, és un pols llarg retlw .19 ; Ni curt ni llarg ; Error 19 - Semiperíode massa llarg o període massa curt Llarg ; És un pols llarg btfsc Estat,6 ; Pre = 1? retlw .9 ; Sí: Error 9 - No hi ha canvi a mig període goto CanviFinal ; No, esperem canvi al final de període Curt ; És un pols curt movlw b'01000000' ; Invertim Pre ara xorwf Estat,f ; per no haver-ho de fer dos cops btfsc Estat,6 ; Pre = 1? goto SegTran ; No, esperem canvi a mig període CanviFinal ; Sí, esperem canvi al final de període btfss Estat,5 ; Cap = 1? goto NoCap ; No, ja no estem rebent capçalera btfss Estat,7 ; Rebut = 1? goto Cap0 ; No, hem rebut un zero a la capçalera incf Comp_bits,f ; Tenim un altre 1 de capçalera movlw .16 ; Hem arribat al final de la capçalera? xorwf Comp_bits,w ; Comp_bits = 16? btfsc STATUS,Z ; Z = 1 si Comp_bits = 16 retlw .66 ; Sí: Error 66 - Massa 1 a la capçalera goto SegTran ; No, esperem el següent Cap0 ; Hem rebut un zero a la capçalera movlw .15 ; Hem arribat al final de la capçalera? xorwf Comp_bits,w ; Comp_bits = 15? btfss STATUS,Z ; Z = 1 si Comp_bits = 15 retlw .65 ; Sí: Error 65 - Pocs 1 a la capçalera bcf Estat,5 ; Cap = 0 - Capçalera ja acabada, ara rebrem el missatge movlw .10 ; Cada byte són 10 bits movwf Comp_bits ; 8 de dades i dos d'aturada clrf Byte ; De moment, no hem rebut cap bit de Byte goto SegTran ; Anem a esperar el primer bit NoCap ; Ja no estem rebent capçalera decfsz Comp_bits,f ; Decrementem, és 0? goto NoEs0 ; No, cal saber si és 1 o més gran btfsc Estat,7 ; Sí, darrer bit d'aturada - Rebut = 1? retlw .34 ; Sí: Error 34 - No hi ha 0 als bits d'aturada movf Byte,w ; Agafa el byte rebut movwf INDF ; I el guarda a Vector incf FSR,f ; Incrementa el punter decfsz Comp_bytes,f ; Decrementem, és 0? goto NoFi ; No, cal rebre un altre byte ; Ja hem acabat, anem a fer la suma de control movlw Vector ; Carreguem l'adreça del lloc on es guardaran els bytes rebuts movwf FSR ; Punter per a l'adreçament indirecte movf Bytes,w ; Número de bytes que hem rebut movwf Comp_bytes ; Variable de comptatge movlw 0 ; Comencem amb zero per anar sumant SumaControl ; i anem a fer el bucle de suma addwf INDF,w ; Suma el valor de Vector incf FSR,f ; Incrementa el punter decfsz Comp_bytes,f ; Decrementa, és 0? goto SumaControl ; No, sumem un altre andlw 0xFF ; Sí, anem a veure si surt zero btfss STATUS,Z ; Si és zero, and donarà zero retlw .5 ; No és zero: Error 5 - La suma de control no dona 0 retlw 0 ; Sí és zero: Error 0 - Recepció correcta NoFi ; Cal rebre un altre byte movlw .10 ; Cada byte són 10 bits movwf Comp_bits ; 8 de dades i dos d'aturada clrf Byte ; De moment, no hem rebut cap bit de Byte goto SegTran ; Anem a esperar el primer bit NoEs0 ; Cal saber si és 1 o més gran decfsz Comp_bits,w ; Decrementem provisionalment, és 0? goto Dades ; No, doncs encara és un bit de dades btfss Estat,7 ; Sí, és un bit d'aturada - Rebut = 1? retlw .33 ; No: Error 33 - No hi ha 1 als bits d'aturada goto SegTran ; Sí, esperem el següent bit d'aturada Dades ; És un bit de dades rlf Estat,w ; Passa Rebut a C rlf Byte,f ; I el col·loca a la dreta de Byte desplaçant els que ja hi són goto SegTran ; Esperem el següent bit end
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.