Programació en pic-as 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ó.

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

Compta EQU 0x20  ; Comptador d'iteracions
Temp EQU 0x21  ; Variable Temporal
Valor EQU 0x22  ; Valor d'entrada (2 bytes, 16 bits)
Resul EQU 0x24  ; Valor de sortida (5 nibbles en tres bytes)
;
; Funció que converteix un número de 16 bits a BCD (5 dígits)
;
BCD5:
  bcf CARRY  ; 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 EQU 0x24  ; Valor de sortida (cinc bytes, 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.