Hem triat el sensor de temperatura i humitat RHT03 de l'empresa Maxdetect.

El connexionat del sensor és molt senzill. Té quatre potes, dues són per a l'alimentació, una és la que es connecta amb el microcontrolador i la restant no es connecta enlloc. L'esquema és el següent:

Com la mateixa pota serveix d'entrada i de sortida, hi ha moments que és el sensor qui envia senyal i en altres moments és el microcontrolador qui ho fa. Però en algun moment la pota queda sense connexió efectiva i, per això, cal posar-hi una resistència que manté la pota a 5 V si no està treballant.
El sensor pot llegir correctament valors de temperatura entre -40 °C i +80 °C així com humitats relatives entre 0 i 100 % amb una xifra decimal en tots dos casos. El sensor envia una cadena de 40 bits com la següent:
0000 0010 1000 1100 0000 0001 0101 1111 1110 1110
Els valors s'envien en l'ordre següent:
| Ordre | Número de bits | Contingut | Exemple | ||
| Bits | Decimal | Lectura | |||
| 1 | 16 | Humitat | 0000 0010 1000 1100 | 652 | 65,2 % |
| 2 | 16 | Temperatura | 0000 0001 0101 1111 | 351 | 35,1 °C |
| 1000 0000 0110 0101 | 101 | -10,1 °C | |||
| 3 | 8 | Suma de comprovació | 1110 1110 | ||
El primer bit de la temperatura no forma part del valor sinó que indica el signe. Quan la temperatura és positiva aquest bit és zero i si és negativa el bit és 1. El valor es calcula amb els altres 15 bits.
La suma de comprovació es calcula sumant els quatre bytes de la temperatura i la humitat. El resultat d'aquesta suma (prescindim de si hi ha un novè bit) és el valor que s'envia. Per exemple en el cas següent
0000 0010 1000 1100 0000 0001 0101 1111 1110 1110
seria:
| 0000 0010 | ||
| 1000 1100 | ||
| 0000 0001 | ||
| 0101 1111 | ||
| 1110 1110 |
La seqüència d'un enviament seria la de la figura seüent:

Abans i després de l'enviament, el microcontrolador i el sensor estan funcionant com a entrades i és la resistència qui manté l'estat a 5 V (tram en color blau).
Quan el microcontrolador vol llegir el sensor (color taronja) ha de posar-se en mode sortida i enviar un zero durant 1 ms o més. Tot seguit es posa a 1 i torna a passar a mode entrada per esperar que el sensor respongui.
El sensor envia primer un senyal de que inicia la transmissió de dades (color rosa) consistent en un 0 i un 1 de 80 μs cada un. Tots els temps que aquí s'indiquen són aproximats.
Després el sensor envia els 40 bits (color verd). Un bit a 0 està format per un valor 0 d'uns 50 μs seguit d'un valor 1 d'uns 26 a 28 μs. En canvi, un bit a 1 està format per un valor 0 d'uns 50 μs seguit d'un valor 1 d'uns 70 μs.
Un cop ha acabat la transmissió, el sensor es posa a 0 un moment i després torna a passar a mode recepció.
A continuació hi ha un programa de prova del sensor. El programa llegeix el valor del sensor (connectat a RA5) i mostra a una pantalla sèrie els tres valors enviats (humitat, temperatura i suma) tal com els rep; és a dir els números de 16 o 8 bits tal com arriben.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Compta ; Comptador d'iteracions Temp ; Variable temporal Valor:2 ; Valor d'entrada (16 bits) Resul:5 ; Valor de sortida Port ; Valor a escriure al port A Temps ; Variable per a guardar-hi el temps Bits ; Compta els bits que es van rebent Control ; Bits de control (port B) Caracter ; Caràcter o codi a enviar (port C) Retard1 ; Variables per als cicles de retard Retard2 Humit:2 ; Valor de la humitat relativa (en %) multiplicat per 10 Temper:2 ; Valor de la temperatura (en °C) multiplicat per 10 Check ; Suma de comprovació de la lectura del sensor 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 bcf TRISA,5 ; De moment, RA5 és sortida clrf TRISB ; Tot el port B és de sortida clrf TRISC ; Tot el port C és de sortida ; Configuració de la comunicació sèrie bsf TXSTA,BRGH ; Configuració de velocitat bcf BAUDCTL,BRG16 ; Paràmetre de velocitat de 8 bits movlw .25 ; Velocitat de 9600 baud movwf SPBRG ; Paràmetre de velocitat bcf TXSTA,SYNC ; Comunicació asíncrona bcf TXSTA,TX9 ; Comunicació de 8 bits bcf STATUS,RP0 bcf STATUS,RP1 ; Tria el banc 0 bsf RCSTA,SPEN ; Activa comunicació sèrie bsf STATUS,RP0 ; Tria el banc 1 bsf TXSTA,TXEN ; Activa comunicació bcf STATUS,RP0 ; Tria el banc 0 movlw b'00100000' ; PORTA,5 és on hi ha el sensor movwf Port ; Ho guardem a la variable Port movwf PORTA ; I ho copiem al port A movlw b'00010001' ; Configuració de Timer1 ; Com a temporitzador basat en rellotge ; 01 - Factor d'escala de 2 ; TMR1L s'incrementarà cada 2 us movwf T1CON ; Ho guarda al registre de configuració del Timer1 Bucle call Llegir ; Llegeix els valors del sensor andlw 0xFF ; Anem a veure si W és zero btfss STATUS,Z ; Si és zero, and donarà zero goto Bucle ; No és zero, tornem a llegir ; És zero, lectura correcta movlw .254 ; Caràcter de control movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movlw .1 ; Esborra la pantalla i posa el cursor a l'inici movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Humit+1,w ; Llegeix el byte més significatiu de la humitat movwf Valor+1 ; Ho prepara per convertir-ho a BCD movf Humit,w ; Llegeix el byte menys significatiu de la humitat movwf Valor ; Ho prepara per convertir-ho a BCD call BCD5 ; Ho converteix en BCD en 3 bytes call Separa ; Ho separem en 5 bytes call EscPant5 ; Ho enviem a la pantalla movlw ' ' ; Espai en blanc movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Temper+1,w ; Llegeix el byte més significatiu de la temperatura movwf Valor+1 ; Ho prepara per convertir-ho a BCD movf Temper,w ; Llegeix el byte menys significatiu de la temperatura movwf Valor ; Ho prepara per convertir-ho a BCD call BCD5 ; Ho converteix en BCD en 3 bytes call Separa ; Ho separem en 5 bytes call EscPant5 ; Ho enviem a la pantalla movlw ' ' ; Espai en blanc movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia clrf Valor+1 ; El CheckSum només té un byte movf Check,w ; Llegeix el CheckSum movwf Valor ; Ho prepara per convertir-ho a BCD call BCD5 ; Ho converteix en BCD en 3 bytes call Separa ; Ho separem en 5 bytes call EscPant3 ; Enviem els tres dígits a la pantalla movlw 0 ; Comença un cicle de durada fixa (0,2 s) call Retard ; Crida a la funció Retard, el paràmetre està a W goto Bucle
; ; Llegeix els valors al sensor ; Llegir ; Primer activem el funcionament del sensor bsf STATUS,RP0 ; Tria el banc 1 bcf TRISA,5 ; Posem el pin com a sortida bcf STATUS,RP0 ; Tria el banc 0 clrf Humit+1 ; Posa a zero les variables on ha d'anar la lectura clrf Humit clrf Temper+1 ; Els primers bits de Humit+1 seran 0; així clrf Temper ; si el bit de més a la dreta de Check el posem a 1 movlw 0x01 ; podrem veure on ha quedat aquest 1 movwf Check ; en cas que hi hagi una errada de lectura bcf Port,5 ; Posa la sortida a 0 movf Port,w ; Ho copia a W movwf PORTA ; I ho envia al port movlw .2 ; Retard d'1,54 ms call Retard ; Espera el temps bsf Port,5 ; Posa la sortida a 1 movf Port,w ; Ho copia a W movwf PORTA ; I ho envia al port movlw .5 ; El retard serà de 3*5 = 15 us call Retus ; Un cop activat, esperem la resposta bsf STATUS,RP0 ; Tria el banc 1 bsf TRISA,5 ; Posem el pin com a entrada bcf STATUS,RP0 ; Tria el banc 0 ; Esperem a rebre el pols d'inici ; Primer un L d'uns 80 us ; Per començar, s'ha de desactivar l'entrada ; i s'ha de reactivar al cap d'entre 70 i 90 us Esp0 btfsc PORTA,5 ; S'ha desactivat l'entrada? goto Esp0 ; No, doncs esperem clrf TMR1L clrf TMR1H ; Comencem a comptar el temps Esp1I ; Esperem que s'activi l'entrada btfsc PORTA,5 ; S'ha activat l'entrada? goto ZeroIni ; Sí, doncs el zero inicial ja està movf TMR1L,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .45 ; Mirem que no passem de 90 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 45 goto Esp1I ; És més petit, seguim esperant retlw .1 ; És més gran: Error 1 - Zero inicial massa llarg ZeroIni ; El zero inicial ja està ; Comprovem la durada movf TMR1L,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR1L ; Comencem a comptar el temps per al següent clrf TMR1H movlw .35 ; Mirem que no sigui menor que 70 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 35 retlw .2 ; És més petit: Error 2 - Zero inicial massa curt ; Ja tenim el zero inicial ; Ara l'entrada està a u i esperem que es posi a zero Esp0I ; Esperem a que es desactivi l'entrada btfss PORTA,5 ; S'ha desactivat l'entrada? goto UIni ; Sí, doncs l'u inicial ja està movf TMR1L,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .45 ; Mirem que no passem de 90 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 45 goto Esp0I ; És més petit, seguim esperant retlw .3 ; És més gran: Error 3 - U inicial massa llarg UIni ; L'u inicial ja està movf TMR1L,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR1L ; Comencem a comptar el temps per al següent clrf TMR1H movlw .35 ; Mirem que no sigui menor que 70 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 35 retlw .4 ; És més petit: Error 4 - U inicial massa curt ; Ja tenim l'u inicial ; Ara hem de rebre els bits movlw .40 ; Hem de rebre 40 bits movwf Bits ; Aquesta variable els comptarà BucBits ; Esperem a rebre un bit ; Primer un L d'uns 80 us ; Ara l'entrada està a zero ; S'ha d'activar al cap d'entre 10 i 90 us Esp1B ; Esperem que s'activi l'entrada btfsc PORTA,5 ; S'ha activat l'entrada? goto ZeroB ; Sí, doncs el valor 0 del bit ja està movf TMR1L,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .45 ; Mirem que no passem de 90 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 45 goto Esp1B ; És més petit, seguim esperant retlw .5 ; És més gran: Error 5 - Valor 0 del bit massa llarg ZeroB ; El valor 0 del bit ja està movf TMR1L,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR1L ; Comencem a comptar el temps per al següent movlw .5 ; Mirem que no sigui menor que 10 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 5 retlw .6 ; És més petit: Error 6 - Valor 0 del bit massa curt ; Ja tenim el valor 0 del bit. Ara esperem un 1 Esp0B ; Esperem a que es desactivi l'entrada btfss PORTA,5 ; S'ha desactivat l'entrada? goto UB ; Sí, doncs el valor 1 del bit ja està movf TMR1L,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .40 ; Mirem que no passem de 80 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 40 goto Esp0B ; És més petit, seguim esperant retlw .7 ; És més gran: Error 7 - Valor 1 del bit massa llarg UB ; El valor 1 del bit ja està movf TMR1L,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR1H clrf TMR1L ; Comencem a comptar el temps per al següent ; Ja hem comprovat que no passi de 80 us ; Si és més petit que 12 us és massa curt movlw .6 ; Mirem si és menor que 12 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 8 retlw .8 ; És més petit: Error 8 - Valor 1 del bit massa curt ; Ja hem comprovat que no sigui massa curt ; Si és més petit que 38 us és un pols curt, o sigui un 0 movlw .19 ; Mirem si és menor que 38 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 19 goto EsUn0 ; Si està entre 16 i 38 us és un 0 ; No era un pols curt ; Si és més gran que 60 us és un pols llarg, o sigui un 1 movlw .30 ; Mirem si és menor que 60 us subwf Temps,w ; W = Temps - W btfsc STATUS,C ; C = 1 si Temps >= 30 goto EsUn1 ; Si està entre 60 i 80 us és un 1 retlw .9 ; No és ni llarg ni curt: Error 9 - Valor 1 del bit incorrecte EsUn0 bcf STATUS,C ; Si és un 0 entrem un 0 goto EntraBit EsUn1 bsf STATUS,C ; Si és un 1 entrem un 1 EntraBit ; Guardem el bit rebut rlf Check,f ; Entrem per Check i anem rodant fins a Humit+1 rlf Temper,f rlf Temper+1,f rlf Humit,f rlf Humit+1,f decfsz Bits,f ; Un altre bit rebut goto BucBits ; Si no hem acabat, esperem el següent retlw .0 ; Lectura correcta ; ; Anem a enviar la lectura ; EscPant3 ; Anem a enviar la lectura de 3 caràcters movlw .3 ; Cal fer-ho 3 cops movwf Compta ; Ho posem al comptador movlw Resul+2 ; Adreça de la darrera xifra goto EscPant EscPant5 ; Anem a enviar la lectura de 5 caràcters movlw .5 ; Cal fer-ho 5 cops movwf Compta ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra EscPant movwf FSR ; Adreçament indirecte BuclePant movf INDF,w ; Llegeix el caràcter movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia decf FSR,f ; Decrementa FSR decfsz Compta,f ; Decrementa el comptador goto BuclePant ; Si no és zero, repetim return ; Fi de l'enviament a la pantalla ; ; Enviem caràcters a visualitzar ; EnviaL movf Caracter,f ; Agafa el caràcter movwf TXREG ; L'envia nop nop ; Espera 2 us btfss PIR1,TXIF ; El registre TXREG ha quedat lliure? goto $-1 ; No, doncs esperem return ; Tornem al lloc des d'on hem vingut ; ; Funció de retard; W conté el nombre de cicles de 3 us que cal fer ; Retus movwf Retard1 Bucleus decfsz Retard1,f goto Bucleus return ; ; Funció Retard, W conté el nombre de cicles de 771 us que cal fer ; Retard movwf Retard2 ; Ho copia a la variable Retard2 BucRet decfsz Retard1,f ; Decrementa la variable 1 ; si dona zero, no es fa la instrucció següent goto BucRet ; Salta, excepte si el resultat ha estat zero decfsz Retard2,f ; Decrementa la variable 2 goto BucRet ; Salta, excepte si el resultat ha estat zero return ; Tornem al lloc des d'on hem vingut ; ; Converteix a BCD ; BCD5 bcf STATUS,C ; Posa a zero C per entrar zeros a les rotacions movlw .16 ; Nombre d'iteracions movwf Compta ; Comptador d'iteracions clrf Resul+2 ; Desenes de miler clrf Resul+1 ; Unitats de miler i centenes clrf Resul ; Desenes i unitats BucleBCD rlf Valor,f ; Girem bits a l'esquerra a valor rlf Valor+1,f ; Cap a valor+1 rlf Resul,f ; I cap als resultats rlf Resul+1,f rlf Resul+2,f decfsz Compta,f ; Decrementa Compta goto ajust ; Si no és zero, ajustem el resultat retlw 0 ; Si és zero ja estem; tornem un 0 a W ajust movlw Resul ; Agafem l'adreça del byte de menys pes movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte de més a la dreta movlw Resul+1 ; Agafem l'adreça del byte del mig movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte del mig movlw Resul+2 ; Agafem l'adreça del byte de més pes movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte de més a l'esquerra goto BucleBCD ; Torna a repetir el bucle (fins a 16 cops) ; ; funció d'ajust d'un byte, primer el nibble de la dreta, després l'altre ; ajustBCD movlw 0x03 ; Agafa el valor 03h addwf INDF,w ; El suma al byte que ajustem movwf Temp ; Ho guarda a Temp btfsc Temp,3 ; És més gran que 07h (s'ha activat el bit 3)? movwf INDF ; Si és cert, sobreposa el resultat movlw 0x30 ; Agafa el valor 30h addwf INDF,w ; El suma al byte que ajustem movwf Temp ; Ho guarda a Temp btfsc Temp,7 ; És més gran que 70h (s'ha activat el bit 7)? movwf INDF ; Si és cert, sobreposa el resultat retlw 0 ; Retorna amb un zero a W ; ; Separa els digits i els converteix a ASCII ; Separa movf Resul+2,w ; Agafa les desenes de miler movwf Resul+4 ; Les posa al seu lloc swapf Resul+1,w ; Llegeix les unitats de miler i les centenes i les guarda, permutades, a w andlw 0x0F ; Es queda amb les unitats de miler movwf Resul+3 ; Les posa al seu lloc movf Resul+1,w ; Llegeix les unitats de miler i les centenes i les guarda a w andlw 0x0F ; Es queda amb les centenes movwf Resul+2 ; Les posa al seu lloc swapf Resul,w ; Llegeix les desenes i les unitats i les guarda, permutades, a w andlw 0x0F ; Es queda amb les desenes movwf Resul+1 ; Les posa al seu lloc movf Resul,w ; Llegeix les desenes i les unitats i les guarda a w andlw 0x0F ; Es queda amb les unitats movwf Resul ; Les posa al seu lloc movlw .5 ; Cal fer-ho 5 cops movwf Compta ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra movwf FSR ; Adreçament indirecte movlw '0' ; Carrega el codi ASCII del número 0 ; Sumant-li la xifra tindrem el codi ASCII Bucle1 addwf INDF,f ; Ho afegeix al dígit decf FSR,f ; Decrementa FSR decfsz Compta,f ; Decrementa el comptador goto Bucle1 ; Si no és zero, repetim movlw .4 ; Cal fer-ho 4 cops movwf Compta ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra movwf FSR ; Adreçament indirecte Bucle2 movf INDF,w ; Llegeix el dígit xorlw '0' ; Compara amb 0 btfss STATUS,Z ; Si Z està activat eren iguals goto Final ; Si no eren iguals, ja estem movlw ' ' ; Carrega un espai en blanc movwf INDF ; Substitueix el 0 per l'espai decf FSR,f ; Decrementa FSR decfsz Compta,f ; Decrementa el comptador goto Bucle2 ; Si no és zero, repetim Final retlw 0 ; Retorna amb un 0 a W end
A continuació hi ha un altre programa de prova del sensor. El programa llegeix el valor del sensor (connectat a RA2) i mostra a una pantalla paral·lel els tres valors enviats (humitat, temperatura i suma) tal com els rep; és a dir els números de 16 o 8 bits tal com arriben.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Compta ; Comptador d'iteracions Temp ; Variable temporal Valor:2 ; Valor d'entrada (16 bits) Resul:5 ; Valor de sortida Port ; Valor a escriure al port A Temps ; Variable per a guardar-hi el temps Bits ; Compta els bits que es van rebent Control ; Bits de control (port B) Caracter ; Caràcter o codi a enviar (port C) Retard1 ; Variables per als cicles de retard Retard2 Humit:2 ; Valor de la humitat relativa (en %) multiplicat per 10 Temper:2 ; Valor de la temperatura (en °C) multiplicat per 10 Check ; Suma de comprovació de la lectura del sensor 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 bcf TRISA,2 ; De moment, RA2 és sortida clrf TRISB ; Tot el port B és de sortida clrf TRISC ; Tot el port C és de sortida movlw b'10000000' ; Configuració de Timer0 ; Com a temporitzador basat en rellotge ; 000 - Factor d'escala de 2 ; TMR0 s'incrementarà cada 2 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 bsf STATUS,RP1 ; Tria el banc 2 movlw b'11111011' movwf ANSEL ; Posa AN2 (RA2) com entrada binària bcf STATUS,RP0 bcf STATUS,RP1 ; Tria el banc 0 movlw b'00000100' ; PORTA,2 és on hi ha el sensor movwf Port ; Ho guardem a la variable Port movwf PORTA ; I ho copiem al port A Bucle call IniPant ; Inicialització del mode de funcionament de la pantalla call ConfPant ; Configuració de la pantalla call Llegir ; Llegeix els valors del sensor andlw 0xFF ; Anem a veure si W és zero btfss STATUS,Z ; Si és zero, and donarà zero goto Bucle ; No és zero, tornem a llegir ; És zero, lectura correcta movlw 0x00 ; Adreça DDRAM (Filera 1 - Posició 1) iorlw b'10000000' ; Posa el bit de DDRAM a 1 movwf Caracter ; Ho guarda a la variable call EnviaC ; Ho envia movf Humit+1,w ; Llegeix el byte més significatiu de la humitat movwf Valor+1 ; Ho prepara per convertir-ho a BCD movf Humit,w ; Llegeix el byte menys significatiu de la humitat movwf Valor ; Ho prepara per convertir-ho a BCD call BCD5 ; Ho converteix en BCD en 3 bytes call Separa ; Ho separem en 5 bytes call EscPant5 ; Ho enviem a la pantalla movlw ' ' ; Espai en blanc movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia movf Temper+1,w ; Llegeix el byte més significatiu de la temperatura movwf Valor+1 ; Ho prepara per convertir-ho a BCD movf Temper,w ; Llegeix el byte menys significatiu de la temperatura movwf Valor ; Ho prepara per convertir-ho a BCD call BCD5 ; Ho converteix en BCD en 3 bytes call Separa ; Ho separem en 5 bytes call EscPant5 ; Ho enviem a la pantalla movlw ' ' ; Espai en blanc movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia clrf Valor+1 ; El CheckSum només té un byte movf Check,w ; Llegeix el CheckSum movwf Valor ; Ho prepara per convertir-ho a BCD call BCD5 ; Ho converteix en BCD en 3 bytes call Separa ; Ho separem en 5 bytes call EscPant3 ; Enviem els tres dígits a la pantalla movlw 0 ; Comença un cicle de durada fixa (0,2 s) call Retard ; Crida a la funció Retard, el paràmetre està a W goto Bucle
; ; Llegeix els valors al sensor ; Llegir ; Primer activem el funcionament del sensor bsf STATUS,RP0 ; Tria el banc 1 bcf TRISA,2 ; Posem el pin com a sortida bcf STATUS,RP0 ; Tria el banc 0 clrf Humit+1 ; Posa a zero les variables on ha d'anar la lectura clrf Humit clrf Temper+1 ; Els primers bits de Humit+1 seran 0; així clrf Temper ; si el bit de més a la dreta de Check el posem a 1 movlw 0x01 ; podrem veure on ha quedat aquest 1 movwf Check ; en cas que hi hagi una errada de lectura bcf Port,2 ; Posa la sortida a 0 movf Port,w ; Ho copia a W movwf PORTA ; I ho envia al port movlw .2 ; Retard d'1,54 ms call Retard ; Espera el temps bsf Port,2 ; Posa la sortida a 1 movf Port,w ; Ho copia a W movwf PORTA ; I ho envia al port movlw .5 ; El retard serà de 3*5 = 15 us call Retus ; Un cop activat, esperem la resposta bsf STATUS,RP0 ; Tria el banc 1 bsf TRISA,2 ; Posem el pin com a entrada bcf STATUS,RP0 ; Tria el banc 0 ; Esperem a rebre el pols d'inici ; Primer un L d'uns 80 us ; Per començar, s'ha de desactivar l'entrada ; i s'ha de reactivar al cap d'entre 70 i 90 us Esp0 btfsc PORTA,2 ; S'ha desactivat l'entrada? goto Esp0 ; No, doncs esperem clrf TMR0 ; Comencem a comptar el temps Esp1I ; Esperem que s'activi l'entrada btfsc PORTA,2 ; S'ha activat l'entrada? goto ZeroIni ; Sí, doncs el zero inicial ja està movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .45 ; Mirem que no passem de 90 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 45 goto Esp1I ; És més petit, seguim esperant retlw .1 ; És més gran: Error 1 - Zero inicial massa llarg ZeroIni ; El zero inicial ja està ; Comprovem la durada movf TMR0,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR0 ; Comencem a comptar el temps per al següent movlw .35 ; Mirem que no sigui menor que 70 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 35 retlw .2 ; És més petit: Error 2 - Zero inicial massa curt ; Ja tenim el zero inicial ; Ara l'entrada està a u i esperem que es posi a zero Esp0I ; Esperem a que es desactivi l'entrada btfss PORTA,2 ; S'ha desactivat l'entrada? goto UIni ; Sí, doncs l'u inicial ja està movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .45 ; Mirem que no passem de 90 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 45 goto Esp0I ; És més petit, seguim esperant retlw .3 ; És més gran: Error 3 - U inicial massa llarg UIni ; L'u inicial ja està movf TMR0,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR0 ; Comencem a comptar el temps per al següent movlw .35 ; Mirem que no sigui menor que 70 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 35 retlw .4 ; És més petit: Error 4 - U inicial massa curt ; Ja tenim l'u inicial ; Ara hem de rebre els bits movlw .40 ; Hem de rebre 40 bits movwf Bits ; Aquesta variable els comptarà BucBits ; Esperem a rebre un bit ; Primer un L d'uns 80 us ; Ara l'entrada està a zero ; S'ha d'activar al cap d'entre 10 i 90 us clrf TMR0 ; Comencem a comptar el temps Esp1B ; Esperem que s'activi l'entrada btfsc PORTA,2 ; S'ha activat l'entrada? goto ZeroB ; Sí, doncs el valor 0 del bit ja està movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .45 ; Mirem que no passem de 90 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 45 goto Esp1B ; És més petit, seguim esperant retlw .5 ; És més gran: Error 5 - Valor 0 del bit massa llarg ZeroB ; El valor 0 del bit ja està movf TMR0,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR0 ; Comencem a comptar el temps per al següent movlw .5 ; Mirem que no sigui menor que 10 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 5 retlw .6 ; És més petit: Error 6 - Valor 0 del bit massa curt ; Ja tenim el valor 0 del bit. Ara esperem un 1 Esp0B ; Esperem a que es desactivi l'entrada btfss PORTA,2 ; S'ha desactivat l'entrada? goto UB ; Sí, doncs el valor 1 del bit ja està movf TMR0,w ; No, agafa el valor actual del temps movwf Temps ; i el guarda movlw .40 ; Mirem que no passem de 80 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 40 goto Esp0B ; És més petit, seguim esperant retlw .7 ; És més gran: Error 7 - Valor 1 del bit massa llarg UB ; El valor 1 del bit ja està movf TMR0,w ; Agafa el valor actual del temps movwf Temps ; i el guarda clrf TMR0 ; Comencem a comptar el temps per al següent ; Ja hem comprovat que no passi de 80 us ; Si és més petit que 12 us és massa curt movlw .6 ; Mirem si és menor que 12 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 8 retlw .8 ; És més petit: Error 8 - Valor 1 del bit massa curt ; Ja hem comprovat que no sigui massa curt ; Si és més petit que 38 us és un pols curt, o sigui un 0 movlw .19 ; Mirem si és menor que 38 us subwf Temps,w ; W = Temps - W btfss STATUS,C ; C = 1 si Temps >= 19 goto EsUn0 ; Si està entre 16 i 38 us és un 0 ; No era un pols curt ; Si és més gran que 60 us és un pols llarg, o sigui un 1 movlw .30 ; Mirem si és menor que 60 us subwf Temps,w ; W = Temps - W btfsc STATUS,C ; C = 1 si Temps >= 30 goto EsUn1 ; Si està entre 60 i 80 us és un 1 retlw .9 ; No és ni llarg ni curt: Error 9 - Valor 1 del bit incorrecte EsUn0 bcf STATUS,C ; Si és un 0 entrem un 0 goto EntraBit EsUn1 bsf STATUS,C ; Si és un 1 entrem un 1 EntraBit ; Guardem el bit rebut rlf Check,f ; Entrem per Check i anem rodant fins a Humit+1 rlf Temper,f rlf Temper+1,f rlf Humit,f rlf Humit+1,f decfsz Bits,f ; Un altre bit rebut goto BucBits ; Si no hem acabat, esperem el següent retlw .0 ; Lectura correcta ; ; Anem a enviar la lectura ; EscPant3 ; Anem a enviar la lectura de 3 caràcters movlw .3 ; Cal fer-ho 3 cops movwf Compta ; Ho posem al comptador movlw Resul+2 ; Adreça de la darrera xifra goto EscPant EscPant5 ; Anem a enviar la lectura de 5 caràcters movlw .5 ; Cal fer-ho 5 cops movwf Compta ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra EscPant movwf FSR ; Adreçament indirecte BuclePant movf INDF,w ; Llegeix el caràcter movwf Caracter ; Ho guarda a la variable call EnviaL ; Ho envia decf FSR,f ; Decrementa FSR decfsz Compta,f ; Decrementa el comptador goto BuclePant ; Si no és zero, repetim return ; Fi de l'enviament a la pantalla ; ; Inicialització del mode de funcionament de la pantalla ; IniPant movlw 0 ; Els cicles de retard són de 0,2 s call Retard ; Crida a la funció Retard call Retard ; Crida a la funció Retard call Retard ; Crida a la funció Retard movlw b'00100000' ; Function set - Configuració inicial 0010 al nibble de l'esquerra movwf Caracter ; Ho guarda a la variable call EnviaI ; Envia els 4 bits superiors ; Ara enviem la configuració 2 línea, 5x8 píxels 0010 1000 call EnviaI ; Enviem la part esquerra (ja ho teníem a Caracter) movlw b'10000000' ; I ara la part dreta (però posada a l'esquerra) movwf Caracter ; Ho guarda a la variable call EnviaI ; Envia els 4 bits superiors return ; Fi de la inicialització del mode de funcionament ; ; Configuració de la pantalla ; ConfPant movlw b'00001111' ; Display ON/OFF control - Activa la pantalla amb cursor intermitent movwf Caracter ; Ho guarda a la variable call EnviaC ; Ho envia movlw b'00000001' ; Clear display - Buida la pantalla i inicialitza movwf Caracter ; Ho guarda a la variable call EnviaC ; Ho envia movlw .5 ; El punt indica que es un valor decimal ; Comença un cicle de durada fixa (3,9 ms) call Retard ; Crida a la funció Retard, el paràmetre està a W movlw b'00000110' ; Entry mode - Buida la pantalla, sentit dreta i despl. automàtic movwf Caracter ; Ho guarda a la variable call EnviaC ; Ho envia return ; Fi de la configuració de la pantalla ; ; Enviem caràcters ; EnviaC ; Enviem caràcters de control bcf Control,7 ; Desactiva E bcf Control,5 ; Desactiva RS goto Envia EnviaL ; Enviem caràcters a visualitzar bcf Control,7 ; Desactiva E bsf Control,5 ; Activa RS Envia call EnviaN ; Envia els 4 bits més alts swapf Caracter,f ; Permuta els nibbles call EnviaN ; Envia els 4 bits més alts swapf Caracter,f ; Torna a deixar els nibbles com estaven return ; Tornem al lloc des d'on hem vingut EnviaI ; Enviem nibbles de caràcters de control bcf Control,7 ; Desactiva E bcf Control,5 ; Desactiva RS EnviaN ; Enviem nibbles decfsz Retard1,f ; Funció de retard de 0,8 ms goto EnviaN movf Control,w ; Copia Control a l'acumulador movwf PORTB ; I ho posa al PORTB nop ; Espera 1 us nop ; Espera 1 us nop ; Espera 1 us movf Caracter,w ; Llegeix el caràcter andlw 0xF0 ; Agafa els 4 bits més alts movwf PORTC ; Envia el byte bsf Control,7 ; Activa E movf Control,w ; Copia Control a l'acumulador movwf PORTB ; I ho posa al PORTB nop ; Espera 1 us nop ; Espera 1 us nop ; Espera 1 us nop ; Espera 1 us nop ; Espera 1 us bcf Control,7 ; Desactiva E movf Control,w ; Copia Control a l'acumulador movwf PORTB ; I ho posa al PORTB return ; Tornem al lloc des d'on hem vingut ; ; Funció de retard; W conté el nombre de cicles de 3 us que cal fer ; Retus movwf Retard1 Bucleus decfsz Retard1,f goto Bucleus return ; ; Funció Retard, W conté el nombre de cicles de 771 us que cal fer ; Retard movwf Retard2 ; Ho copia a la variable Retard2 BucRet decfsz Retard1,f ; Decrementa la variable 1 ; si dona zero, no es fa la instrucció següent goto BucRet ; Salta, excepte si el resultat ha estat zero decfsz Retard2,f ; Decrementa la variable 2 goto BucRet ; Salta, excepte si el resultat ha estat zero return ; Tornem al lloc des d'on hem vingut ; ; Converteix a BCD ; BCD5 bcf STATUS,C ; Posa a zero C per entrar zeros a les rotacions movlw .16 ; Nombre d'iteracions movwf Compta ; Comptador d'iteracions clrf Resul+2 ; Desenes de miler clrf Resul+1 ; Unitats de miler i centenes clrf Resul ; Desenes i unitats BucleBCD rlf Valor,f ; Girem bits a l'esquerra a valor rlf Valor+1,f ; Cap a valor+1 rlf Resul,f ; I cap als resultats rlf Resul+1,f rlf Resul+2,f decfsz Compta,f ; Decrementa Compta goto ajust ; Si no és zero, ajustem el resultat retlw 0 ; Si és zero ja estem; tornem un 0 a W ajust movlw Resul ; Agafem l'adreça del byte de menys pes movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte de més a la dreta movlw Resul+1 ; Agafem l'adreça del byte del mig movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte del mig movlw Resul+2 ; Agafem l'adreça del byte de més pes movwf FSR ; La posa a l'adreçament indirecte call ajustBCD ; Ajusta el byte de més a l'esquerra goto BucleBCD ; Torna a repetir el bucle (fins a 16 cops) ; ; funció d'ajust d'un byte, primer el nibble de la dreta, després l'altre ; ajustBCD movlw 0x03 ; Agafa el valor 03h addwf INDF,w ; El suma al byte que ajustem movwf Temp ; Ho guarda a Temp btfsc Temp,3 ; És més gran que 07h (s'ha activat el bit 3)? movwf INDF ; Si és cert, sobreposa el resultat movlw 0x30 ; Agafa el valor 30h addwf INDF,w ; El suma al byte que ajustem movwf Temp ; Ho guarda a Temp btfsc Temp,7 ; És més gran que 70h (s'ha activat el bit 7)? movwf INDF ; Si és cert, sobreposa el resultat retlw 0 ; Retorna amb un zero a W ; ; Separa els digits i els converteix a ASCII ; Separa movf Resul+2,w ; Agafa les desenes de miler movwf Resul+4 ; Les posa al seu lloc swapf Resul+1,w ; Llegeix les unitats de miler i les centenes i les guarda, permutades, a w andlw 0x0F ; Es queda amb les unitats de miler movwf Resul+3 ; Les posa al seu lloc movf Resul+1,w ; Llegeix les unitats de miler i les centenes i les guarda a w andlw 0x0F ; Es queda amb les centenes movwf Resul+2 ; Les posa al seu lloc swapf Resul,w ; Llegeix les desenes i les unitats i les guarda, permutades, a w andlw 0x0F ; Es queda amb les desenes movwf Resul+1 ; Les posa al seu lloc movf Resul,w ; Llegeix les desenes i les unitats i les guarda a w andlw 0x0F ; Es queda amb les unitats movwf Resul ; Les posa al seu lloc movlw .5 ; Cal fer-ho 5 cops movwf Compta ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra movwf FSR ; Adreçament indirecte movlw '0' ; Carrega el codi ASCII del número 0 ; Sumant-li la xifra tindrem el codi ASCII Bucle1 addwf INDF,f ; Ho afegeix al dígit decf FSR,f ; Decrementa FSR decfsz Compta,f ; Decrementa el comptador goto Bucle1 ; Si no és zero, repetim movlw .4 ; Cal fer-ho 4 cops movwf Compta ; Ho posem al comptador movlw Resul+4 ; Adreça de la darrera xifra movwf FSR ; Adreçament indirecte Bucle2 movf INDF,w ; Llegeix el dígit xorlw '0' ; Compara amb 0 btfss STATUS,Z ; Si Z està activat eren iguals goto Final ; Si no eren iguals, ja estem movlw ' ' ; Carrega un espai en blanc movwf INDF ; Substitueix el 0 per l'espai decf FSR,f ; Decrementa FSR decfsz Compta,f ; Decrementa el comptador goto Bucle2 ; Si no és zero, repetim Final retlw 0 ; Retorna amb un 0 a W end

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.