Programació en mpasm del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Sensor de temperatura i humitat

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

Sensor de temperatura i humitat

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:

Sensor de temperatura i humitat

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:

Sensor de temperatura i humitat

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

 

 

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