En aquest cas també convertirem el valor d'un comptador a codi Gray (com a l'exemple AI) però ho farem d'una manera diferent. La nostra funció de conversió a codi Gray tindrà 16 diferents adreces de retorn del tipus retlw (retorn amb un valor a W) i anirem a la instrucció que correspon al valor actual a base de modificar el comptador de programa.
El programa següent és una versió simplificada en la que ja sabem que no cal tocar PCH:
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Polsador ; Una variable amb l'estat del polsador (1 = premut) Previ ; I una amb l'estat previ del polsador Visualit ; Una variable on guardem el que mostraran els LED Compta ; Una variable per comptar iteracions Retard1 ; Variable per al bucle de retard temp ; Variable temporal 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 TRISC ; Posa tots els bits del port C com a sortida bcf STATUS,RP0 clrf Compta ; Posa el comptador d'iteracions a valor zero clrf Visualit ; Posa el comptador dels LED a valor zero clrf Previ ; L'estat previ del polsador és no premut clrf PORTC ; Comencem amb els LED apagats Bucle movlw b'00000001' movwf Polsador ; Activem polsador abans de comprovar btfsc PORTA,3 ; Mira si està desactivada l'entrada A3 ; Si desactivat (premut), no fa la instrucció següent clrf Polsador ; Si no està premut, desactiva polsador movf Previ,w ; Copia Previ a l'acumulador xorwf Polsador,w ; Compara Previ amb Polsador, si són iguals s'activa Z btfsc STATUS,Z ; Si són iguals va a Final goto Esborra incf Compta,f ; Si són iguals, incrementa el valor de Compta movf Compta,w ; Copia Compta a l'acumulador xorlw .4 ; Comprova si val 4, si ho val s'activa Z btfss STATUS,Z ; Si val 4 no fa la instrucció següent goto Final ; Si no era 4 va a Final movf Polsador,w ; Copia Polsador a W, si val 0 s'activa Z btfsc STATUS,Z ; Si Polsador valia 1 (Z=0) no fa la instrucció següent goto Invert ; Si no està premut, ja estem incf Visualit,f ; Si ho està, incrementa el valor de Visualit btfsc Visualit,4 ; Mira si hem arribat a 16 clrf Visualit ; Si hem arribat a 16, torna a posar el comptador a zero movf Visualit,w ; El valor actual el guardem a W call Conversio ; funció de conversió a codi Gray movwf PORTC ; Posa el valor de W als LED Invert movf Previ,w ; Copia Previ a l'acumulador xorlw b'00000001' ; Inverteix el valor movwf Previ ; I ho guarda a Previ Esborra clrf Compta ; Posa el comptador d'iteracions a valor zero Final ; Funció de retard 1 ms nop decfsz Retard1,f goto Final goto Bucle ; Repetim-ho...
; ; funció de conversió a codi Gray ; Conversio andlw 0x0F ; Preventivament, posa a zero els quatre bits superiors movwf temp ; Ho guardem a la variable temporal per tenir lliure l'acumulador ; Aquest és el número que buscarem a la taula movlw Taula ; Carrega l'adreça de la taula addwf temp,w ; Hi afegeix el número que busquem (entre 0 i 15) i ho guarda a l'acumulador movwf PCL ; Modifica el valor de PCL Taula retlw b'00000000' ; Si el punter és zero retornem amb el codi Gray de 0 a l'acumulador retlw b'00000001' ; Torna amb 1 retlw b'00000011' ; Torna amb 2 retlw b'00000010' ; Torna amb 3 retlw b'00000110' ; Torna amb 4 retlw b'00000111' ; Torna amb 5 retlw b'00000101' ; Torna amb 6 retlw b'00000100' ; Torna amb 7 retlw b'00001100' ; Torna amb 8 retlw b'00001101' ; Torna amb 9 retlw b'00001111' ; Torna amb 10 retlw b'00001110' ; Torna amb 11 retlw b'00001010' ; Torna amb 12 retlw b'00001011' ; Torna amb 13 retlw b'00001001' ; Torna amb 14 retlw b'00001000' ; Torna amb 15 end
La directiva dt ens permet entrar les dades de manera compacta. Si, per exemple, escrivim aquest tros de programa:
Taula dt b'00001111', 0xFA, "PICkit", .15
obtindrem a la memòria de programa les instruccions retlw corresponents a cada un dels valors incloent-hi una línia per a cada lletra del text que està entre cometes:
Taula retlw 0xF ; Equival a b'00001111' retlw 0xFA ; 0xFA retlw 0x50 ; Equival a 'P' retlw 0x49 ; Equival a 'I' retlw 0x43 ; Equival a 'C' retlw 0x6B ; Equival a 'k' retlw 0x69 ; Equival a 'i' retlw 0x74 ; Equival a 't' retlw 0xF ; Equival a .15
La següent versió del programa fa el mateix que el primer que hem vist però emprant la directiva dt.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Polsador ; Una variable amb l'estat del polsador (1 = premut) Previ ; I una amb l'estat previ del polsador Visualit ; Una variable on guardem el que mostraran els LED Compta ; Una variable per comptar iteracions Retard1 ; Variable per al bucle de retard temp ; Variable temporal 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 TRISC ; Posa tots els bits del port C com a sortida bcf STATUS,RP0 clrf Compta ; Posa el comptador d'iteracions a valor zero clrf Visualit ; Posa el comptador dels LED a valor zero clrf Previ ; L'estat previ del polsador és no premut clrf PORTC ; Comencem amb els LED apagats Bucle movlw b'00000001' movwf Polsador ; Activem polsador abans de comprovar btfsc PORTA,3 ; Mira si està desactivada l'entrada A3 ; Si desactivat (premut), no fa la instrucció següent clrf Polsador ; Si no està premut, desactiva polsador movf Previ,w ; Copia Previ a l'acumulador xorwf Polsador,w ; Compara Previ amb Polsador, si són iguals s'activa Z btfsc STATUS,Z ; Si són iguals va a Final goto Esborra incf Compta,f ; Si són iguals, incrementa el valor de Compta movf Compta,w ; Copia Compta a l'acumulador xorlw .4 ; Comprova si val 4, si ho val s'activa Z btfss STATUS,Z ; Si val 4 no fa la instrucció següent goto Final ; Si no era 4 va a Final movf Polsador,w ; Copia Polsador a W, si val 0 s'activa Z btfsc STATUS,Z ; Si Polsador valia 1 (Z=0) no fa la instrucció següent goto Invert ; Si no està premut, ja estem incf Visualit,f ; Si ho està, incrementa el valor de Visualit btfsc Visualit,4 ; Mira si hem arribat a 16 clrf Visualit ; Si hem arribat a 16, torna a posar el comptador a zero movf Visualit,w ; El valor actual el guardem a W call Conversio ; funció de conversió a codi Gray movwf PORTC ; Posa el valor de W als LED Invert movf Previ,w ; Copia Previ a l'acumulador xorlw b'00000001' ; Inverteix el valor movwf Previ ; I ho guarda a Previ Esborra clrf Compta ; Posa el comptador d'iteracions a valor zero Final ; Funció de retard 1 ms nop decfsz Retard1,f goto Final goto Bucle ; Repetim-ho...
; ; funció de conversió a codi Gray ; Conversio andlw 0x0F ; Preventivament, posa a zero els quatre bits superiors movwf temp ; Ho guardem a la variable temporal per tenir lliure l'acumulador ; Aquest és el número que buscarem a la taula movlw Taula ; Carrega l'adreça de la taula addwf temp,w ; Hi afegeix el número que busquem (entre 0 i 15) i ho guarda a l'acumulador movwf PCL ; Modifica el valor de PCL Taula dt b'00000000', b'00000001', b'00000011', b'00000010' dt b'00000110', b'00000111', b'00000101', b'00000100' dt b'00001100', b'00001101', b'00001111', b'00001110' dt b'00001010', b'00001011', b'00001001', b'00001000' end
A continuació tenim una nova versió en la que la funció està posada de tal manera que una part de la taula està a PCH 00h i una altra a 01h; així ens veiem obligats a controlar PCH:
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Polsador ; Una variable amb l'estat del polsador (1 = premut) Previ ; I una amb l'estat previ del polsador Visualit ; Una variable on guardem el que mostraran els LED Compta ; Una variable per comptar iteracions Retard1 ; Variable per al bucle de retard temp ; Variable temporal 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 TRISC ; Posa tots els bits del port C com a sortida bcf STATUS,RP0 clrf Compta ; Posa el comptador d'iteracions a valor zero clrf Visualit ; Posa el comptador dels LED a valor zero clrf Previ ; L'estat previ del polsador és no premut clrf PORTC ; Comencem amb els LED apagats Bucle movlw b'00000001' movwf Polsador ; Activem polsador abans de comprovar btfsc PORTA,3 ; Mira si està desactivada l'entrada A3 ; Si desactivat (premut), no fa la instrucció següent clrf Polsador ; Si no està premut, desactiva polsador movf Previ,w ; Copia Previ a l'acumulador xorwf Polsador,w ; Compara Previ amb Polsador, si són iguals s'activa Z btfsc STATUS,Z ; Si són iguals va a Final goto Esborra incf Compta,f ; Si són iguals, incrementa el valor de Compta movf Compta,w ; Copia Compta a l'acumulador xorlw .4 ; Comprova si val 4, si ho val s'activa Z btfss STATUS,Z ; Si val 4 no fa la instrucció següent goto Final ; Si no era 4 va a Final movf Polsador,w ; Copia Polsador a W, si val 0 s'activa Z btfsc STATUS,Z ; Si Polsador valia 1 (Z=0) no fa la instrucció següent goto Invert ; Si no està premut, ja estem incf Visualit,f ; Si ho està, incrementa el valor de Visualit btfsc Visualit,4 ; Mira si hem arribat a 16 clrf Visualit ; Si hem arribat a 16, torna a posar el comptador a zero movf Visualit,w ; El valor actual el guardem a W call Conversio ; funció de conversió a codi Gray movwf PORTC ; Posa el valor de W als LED Invert movf Previ,w ; Copia Previ a l'acumulador xorlw b'00000001' ; Inverteix el valor movwf Previ ; I ho guarda a Previ Esborra clrf Compta ; Posa el comptador d'iteracions a valor zero Final ; Funció de retard 1 ms nop decfsz Retard1,f goto Final goto Bucle ; Repetim-ho...
org 0xf0 ; Adreça triada perquè segur canviï PCH ; ; funció de conversió a codi Gray ; Conversio ; funció de conversió a codi Gray andlw 0x0F ; Preventivament, posa a zero els quatre bits superiors movwf temp ; Ho guardem a la variable temporal per tenir lliure l'acumulador ; Aquest és el número que buscarem a la taula movlw high Taula ; Carrega la part alta de l'adreça de la taula movwf PCLATH ; Ho posa a la part alta de PC movlw low Taula ; Carrega la part baixa de l'adreça de la taula addwf temp,w ; Hi afegeix el número que busquem (entre 0 i 15) ; i ho guarda a l'acumulador btfsc STATUS,C ; S'ha activat C? incf PCLATH,f ; Si s'ha activat, incrementem PCLATH movwf PCL ; Modifica el valor de PCL (i, per tant, també el de PCH) Taula retlw b'00000000' ; Si el punter és zero retornem amb el codi Gray de 0 a l'acumulador retlw b'00000001' ; Torna amb 1 retlw b'00000011' ; Torna amb 2 retlw b'00000010' ; Torna amb 3 retlw b'00000110' ; Torna amb 4 retlw b'00000111' ; Torna amb 5 retlw b'00000101' ; Torna amb 6 (aquesta instrucció està a 0FFh) retlw b'00000100' ; Torna amb 7 (aquesta instrucció està a 100h) retlw b'00001100' ; Torna amb 8 retlw b'00001101' ; Torna amb 9 retlw b'00001111' ; Torna amb 10 retlw b'00001110' ; Torna amb 11 retlw b'00001010' ; Torna amb 12 retlw b'00001011' ; Torna amb 13 retlw b'00001001' ; Torna amb 14 retlw b'00001000' ; Torna amb 15 end

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