Programació en mpasm del PIC 16F690

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

Conversió d'un número de 16 bits a BCD

La funció següent agafa un valor de 16 bits (guardat en dos bytes) i el converteix en cinc dígits BCD, guardats en tres bytes. L'acumulador retorna amb un zero.

El següent diagrama descriu les variables:

Codificacio variables

Aquest programa parteix de la idea de fer rodar els bits cap a l'esquerra (suposant que inicialment C i Resul estan a zero) des de Valor cap a Resul:

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

Si repetíssim això 16 vegades, les variables Valor ens quedarien a zero i tots els bits que hi havia en elles haurien passat a Resul i Resul+1 (Resul+2 seguiria a zero). Així hauríem canviat de lloc però el resultat seguiria en binari i no en BCD.

Cal detectar els canvi de dígit i corregir-lo. Imaginem que hem fet ja tres rotacions i observem, mirant alguns exemples, què succeeix a la quarta:

Abans de rodar Bit que entra Després de rodar
3 0011 0 0110 6
1 0111 7
4 0100 0 1000 8
1 1001 9
5 0101 0 1010 A
1 1011 B
6 0110 0 1100 C
1 1101 D
7 0111 0 1110 E
1 1111 F

Veiem que després de rodar el resultat és el doble si ha entrat un 0 o el doble més 1 si ha entrat un 1.

Per a valors fins a 4 no hi ha cap problema però amb valors superiors a 4 el resultat ja és més gran que 10 i, per tant, caldria separar les xifres.

Provem de sumar 3 (0011), abans de rodar, als valors de la taula anterior:

Valor inicial Després de sumar 3 Bit que entra Després de rodar
3 0011 6 0110 0 1100 C
1 1101 D
4 0100 7 0111 0 1110 E
1 1111 F
5 0101 8 1000 0 1 0000 1 0
1 1 0001 1 1
6 0110 9 1001 0 1 0010 1 2
1 1 0011 1 3
7 0111 10 1010 0 1 0100 1 4
1 1 0101 1 5

Veiem que els valors superiors a 4 han quedat amb el resultat correcte, és a dir amb el número que correspon expressat en BCD. Per exemple el 5 abans es convertia en Ah i ara es converteix en 10h. Cal, però, no fer-ho si el valor original és inferior a 5.

Si ens tornem a mirar la taula, veiem que després de sumar 3 els valors que eren superiors a 4 (els que cal canviar) tenen activat el bit 3 mentre que els que són inferiors a 5 (els que no s'han de tocar), el tenen desactivat. Així doncs el programa serà fàcil: sumarem 3 i mirarem el resultat. Si el resultat té el bit 3 desactivat caldrà deixar-lo com estava; si, en canvi, el té activat, caldrà conservar el valor obtingut a la suma.

A mida que els bits vagin rodant, els resultats s'aniran desplaçant i a la setzena iteració ja haurem buidat Valor. A cada rotació el que estem fent equival a multiplicar per dos i, a més, sumar 1 si el que entra per la dreta és un 1. A cada iteració hem de comprovar tots els nibbles per fer la correcció que hem comentat en cas que es vegi que a la rotació següent passarem de 10. En cada byte, doncs, cal provar-ho en els dos nibbles. Als de la dreta ho farem sumant 03h i mirant el bit 3 i als de l'esquerra ho farem sumant 30h i mirant el bit 7. Un cop fetes les 16 iteracions ja no s'ha de fer l'ajust ja que no hi haurà posterior rotació.

A l'exemple PP podem veure una mostra de com emprar aquesta funció.

Això és el que fa la funció següent:

Compta				; Comptador d'iteracions
Temp				; Variable Temporal
Valor:2				; Valor d'entrada (16 bits)
Resul:3				; Valor de sortida (5 nibbles en tres bytes)
					;
					; Funció que converteix un número de 16 bits a BCD (5 dígits)
					;
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					; funció d'ajust dels resultats
	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)
ajustBCD				; funció d'ajust d'un byte, primer el nibble de la dreta, després l'altre
	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

Si volem el resultat amb un dígit a cada byte, després haurem d'executar el següent tros de programa en el que els cinc dígits entren en els bytes Resul, Resul+1 i Resul+2 i surten ocupant dos bytes més Resul+3 i Resul+4.

Resul:5				; Valor de sortida (els tres primers són l'entrada)
...
	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
...

 

 

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