En aquest exemple farem servir els polsadors per anar movent un cursor (groc) per la matriu de LED i encendre de color blau els punts seleccionats. D'aquesta manera, aconseguirem fer un dibuix. Les funcions assignades a cada polsador són les següents:
| Polsador | Funció |
| 0 | Lliure |
| 1 | Desplaçament horitzontal |
| 2 | Desplaçament vertical |
| 3 | Encendre o apagar LED |
| 4 | Lliure |
| 5 | Esborrar dibuix |
Encara que en aquest programa gastem poca memòria de dades (30 bytes) hem optat per guardar el vector figura, que és el que conté els punts del dibuix, al banc 1 de la memòria; així al banc 0 hi ha més espai disponible per si fem servir aquest programa com a base per a futurs projectes. Amb una idea semblant, hem implementat la consulta del polsador 4, encara que en aquest programa no té cap funció.
Fixem-nos que tots els accessos al vector que guarda el dibuix es fan emprant adreçament indirecte. Atès que l'adreçament indirecte treballa amb adreces de vuit bits, es pot accedir directament a les dades del banc 1 sense necessitat de canviar de banc.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20 Port ; Bits a enviar al port B Sortida:6 ; Valors a enviar al MAX7221 (48 bits) Compta ; Variable per comptar els bits a Envia_max Compt ; Variable per comptar els bytes Comp ; Variable per comptar els bits Filera ; Variable per comptar fileres Actiu ; Variable que diu quin color està actiu ; Actiu = 0 Apagat ; Actiu = 1 Vermell ; Actiu = 2 Verd ; Actiu = 3 Blau Polsador ; Variable que conté un bit per a cada polsador per saber si està premut x ; Coordenada X del cursor (0 a 7) ; X = 0 és la columna de la dreta y ; Coordenada Y del cursor (0 a 7) caux ; Comptador auxiliar mirar ; Espera que es deixi anar el polsador mascara ; Màscara per a les operacions amb bits Retard1 ; Variables per als cicles de retard Retard2 endc cblock 0x70 ; Zona de memòria de dades que no depèn del banc triat W_Copia ; Guardarà el contingut de W durant la interrupció ST_Copia ; Guardarà STATUS durant la interrupció endc cblock 0xA0 ; Zona de memòria de dades del banc 1 figura:8 ; Aquí guardarem el dibuix (8 fileres) endc
org 0 goto Inici ; Saltem al lloc on hi ha el programa principal nop ; Zona de memòria de programa que no utilitzem nop nop
Interrup movwf W_Copia ; Copiem l'acumulador a W_Copia swapf STATUS,w ; Copiem STATUS a l'acumulador permutant els nibbles clrf STATUS ; Posa a 0 i així segur que el banc és el 0 movwf ST_Copia ; Guarda STATUS permutat a ST_Copia btfss INTCON,T0IF ; Mira si Timer0 ha arribat a zero ; Si hi ha arribat, no fa la instrucció següent goto FiInt ; Si la interrupció no és del Timer0 no fem res Timer0 ; Programa corresponent a Timer0 bcf INTCON,T0IF ; Si ha arribat, desactivem el bit movlw .100 ; Nova preselecció movwf TMR0 ; Ho posem a TMR0 ; Anem a gestionar el canvi de color movlw b'00000011' ; Descarta els bits que no serveixen andwf Actiu,f btfsc STATUS,Z goto NoZero ; Si Actiu val 0 no ho canvia decf Actiu,f ; Passem a activar un altre color btfss STATUS,Z ; Si s'activa Z és que hem arribat a zero goto NoZero ; Si és zero, tornem a 3 movlw .3 movwf Actiu NoZero ; Gestiona l'activació de tres MAX7221 ; Segons Actiu, activa un color o un altre movlw b'00000011' ; Descarta els bits que no serveixen andwf Actiu,f btfsc STATUS,Z ; Salta si el resultat no és zero goto Apagat ; Si està apagat ho desactiva tot movlw .1 xorwf Actiu,w btfsc STATUS,Z goto Vermell ; Si val 1, activem el vermell movlw .2 xorwf Actiu,w btfsc STATUS,Z goto Verd ; Si val 2, activem el verd ; Si no és cap d'ells, activem el blau movlw 0x01 ; Activat movwf Sortida+4 ; Blau movlw 0x00 ; Desactivat movwf Sortida ; Vermell movwf Sortida+2 ; Verd movlw .1 goto Activa Vermell movlw 0x01 ; Activat movwf Sortida ; Vermell movlw 0x00 ; Desactivat movwf Sortida+2 ; Verd movwf Sortida+4 ; Blau nop ; Temps a afegir nop nop nop goto Activa Verd movlw 0x01 ; Activat movwf Sortida+2 ; Verd movlw 0x00 ; Desactivat movwf Sortida ; Vermell movwf Sortida+4 ; Blau goto Activa Apagat movlw 0x00 ; Desactivat movwf Sortida ; Vermell movwf Sortida+2 ; Verd movwf Sortida+4 ; Blau Activa movlw 0x0C ; Shutdown mode movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho call Envia_max ; Ho envia als MAX7221 FiInt swapf ST_Copia,w ; Copia permutant ST_Copia a l'acumulador movwf STATUS ; I ho passa a STATUS recuperant el valor d'abans ; de la interrupció swapf W_Copia,f ; Permuta els bits de W_Copia swapf W_Copia,w ; Torna a permutar els bits de W_Copia ; i els guarda a l'acumulador sense variar STATUS retfie ; Torna al programa principal, on s'havia quedat
Inici bsf STATUS,RP0 ; Tria el banc 1 movlw b'10000101' ; Configuració de Timer0 ; Com a temporitzador basat en rellotge ; 101 - Factor d'escala de 64 ; I resistències de pull-up desactivades (valor per defecte) movwf OPTION_REG ; Ho guarda al registre de configuració del Timer0 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf TRISA ; Posa tots els bits del port A com a entrada clrf TRISB ; Posa tots els bits del port B com a sortida clrf TRISC ; Posa tots els bits del port C com a sortida movlw b'00010000' movwf ADCON1 ; Posa el conversor a 1/8 de la freqüència bcf STATUS,RP0 bsf STATUS,RP1 ; Tria el banc 2 movlw b'00000101' movwf ANSEL ; Configura AN0 i AN2 com entrada analògica bcf STATUS,RP0 bcf STATUS,RP1 ; Tria el banc 0 clrf PORTC clrf Port ; Posa a zero tots els bits de la variable Port movf Port,w movwf PORTB ; I ho envia al port B movlw b'00001001' movwf ADCON0 ; Activa el conversor A/D connectat a AN2 ; amb el resultat justificat per l'esquerra call Ini3max ; Inicialitza la matriu ; Configura Timer 0 i activa la matriu i les interrupcions ; Una interrupció cada, aproximadament, 10 ms movlw .1 movwf Actiu ; Posa en marxa el vermell movlw .100 ; Presselecció de 100, que són 156 iteracions movwf TMR0 ; Ho posa com a preselecció del temporitzador movlw b'10100000' ; Activem GIE i T0IE movwf INTCON ; Activa les interrupcions globals i la de Timer0 call Apaga ; Apaga els LED clrf x ; Posa x a zero clrf y ; Posa y a zero movlw 1 movwf mirar ; Posa mirar a 1 call PosaZero ; Posa a zero els bytes del vector figura Bucle ; Mirem els polsadors ; Un cop s'ha fet l'acció del polsador, no es tornarà a fer fins ; que es detecti que s'han deixat anar call Llegir ; Llegeix els polsadors movf mirar,f ; S'han de mirar els polsadors? btfsc STATUS,Z ; Si és zero no s'han de mirar goto NoMirar ; Anem a veure si ja s'ha deixat anar movf Polsador,w xorlw b'00000001' ; Mirem si s'ha premut el polsador 1 btfss STATUS,Z ; Si és l'1, salta goto NoPol1 ; No és l'1 ; S'ha premut el polsador 1 incf x,f ; Incrementem x del cursor movlw b'00000111' ; Valor 7 andwf x,f ; Limitem x entre 0 i 7 goto Zmirar ; Ja estem del polsador 1 NoPol1 movf Polsador,w xorlw b'00000010' ; Mirem si s'ha premut el polsador 2 btfss STATUS,Z ; Si és el 2, salta goto NoPol2 ; No és el 2 ; S'ha premut el polsador 2 incf y,f ; Incrementem y del cursor movlw b'00000111' ; Valor 7 andwf y,f ; Limitem x entre 0 i 7 goto Zmirar ; Ja estem del polsador 2 NoPol2 movf Polsador,w xorlw b'00000100' ; Mirem si s'ha premut el polsador 3 btfss STATUS,Z ; Si és el 3, salta goto NoPol3 ; No és el 3 ; S'ha premut el polsador 3 movlw b'00000001' ; Posem un 1 a la columna 0 movwf mascara ; Ho guardem com a màscara movf x,w ; Agafem la x del cursor btfsc STATUS,Z ; Mirem si és zero goto xZero ; Si és zero no cal fer res movwf Comp ; Hem de rodar els bits x posicions rodaX bcf STATUS,C ; Volem entrar zeros rlf mascara,f ; Rodem a l'esquerra i entrem el zero decfsz Comp,f ; Decrementa Comp goto rodaX ; Si Comp no és zero, repeteix el bucle xZero ; Ja tenim l'1 posat a la columna movlw figura ; Agafem l'adreça de la primera posició del vector movwf FSR ; La posem com a punter d'adreçament indirecte movf y,w ; Agafem la y del cursor addwf FSR,f ; Ho afegim al punter movf mascara,w ; Agafa la màscara xorwf INDF,f ; L'aplica a la filera corresponent goto Zmirar ; Ja estem del polsador 3 NoPol3 movf Polsador,w xorlw b'00001000' ; Mirem si s'ha premut el polsador 4 btfss STATUS,Z ; Si és el 4, salta goto NoPol4 ; No és el 4 ; S'ha premut el polsador 4 ; El polsador 4 no fa res goto Zmirar ; Ja estem del polsador 4 NoPol4 movf Polsador,w xorlw b'00010000' ; Mirem si s'ha premut el polsador 5 btfss STATUS,Z ; Si és el 5, salta goto NoPol5 ; No és el 5 ; S'ha premut el polsador 5 call PosaZero ; Posa a zero els bytes del vector figura Zmirar ; Ja estem del polsador 5 clrf mirar ; Posa mirar a zero fins que es deixi el polsador NoPol5 goto Matriu ; Envia la figura actual a la matriu NoMirar movf Polsador,w ; Agafem la lectura dels polsadors btfss STATUS,Z ; Mira si és zero goto Matriu ; Si no és zero cal seguir esperant movlw 1 ; Si és zero, s'ha deixat el polsador movwf mirar ; Posa mirar a 1 Matriu ; Anem a mostrar la figura actual a la matriu de LED clrf caux ; Primer enviem la filera 0 movlw .8 ; Número de bytes que cal enviar movwf Compt ; Variable per comptar els bytes movlw figura ; Agafem l'adreça de la primera posició del vector movwf FSR ; La posem com a punter d'adreçament indirecte BucleMatriu clrf Sortida ; Vermell, en principi, a zero clrf Sortida+2 ; Verd, en principi, a zero movf INDF,w ; Agafa la filera actual movwf Sortida+4 ; La posa en el blau ; Anem a veure si estem a la filera del cursor movf caux,w ; Mirem la filera que estem enviant xorwf y,w ; I comparem amb la del cursor btfss STATUS,Z ; Si és zero, són iguals goto noCur ; No és la filera del cursor movlw b'00000001' ; Posem un 1 a la columna 0 movwf mascara ; Ho guardem com a màscara movf x,w ; Agafem la x del cursor btfsc STATUS,Z ; Mirem si és zero goto xnul ; Si és zero no cal fer res movwf Comp ; Hem de rodar els bits x posicions giraX bcf STATUS,C ; Volem entrar zeros rlf mascara,f ; Rodem a l'esquerra i entrem el zero decfsz Comp,f ; Decrementa Comp goto giraX ; Si Comp no és zero, repeteix el bucle xnul ; Ja tenim l'1 posat a la columna movf mascara,w ; Agafem la màscara que hem preparat (set 0 i un 1) iorwf Sortida,f ; L'apliquem al vermell iorwf Sortida+2,f ; i al verd, per fer el cursor groc comf mascara,w ; Agafem l'invers de la màscara (set 1 i un 0) andwf Sortida+4,f ; L'apliquem al blau per apagar el LED ; Fi del tractament del cursor noCur ; A la matriu s'hi envien valors entre 1 i 8 (no de 0 a 7) incf caux,w ; Incrementa l'índex i el guarda a w movwf Sortida+1 ; El posa per indicar la filera que escrivim movwf Sortida+3 ; El posa per indicar la filera que escrivim movwf Sortida+5 ; El posa per indicar la filera que escrivim call Envia3max ; Ho envia al MAX7221 incf FSR,f ; Incrementa el punter incf caux,f ; Incrementa l'índex decfsz Compt,f ; Decrementa Compt goto BucleMatriu ; Si Compt no és zero, repeteix el bucle movlw 1 ; Retard de 0,771 ms call Retms goto Bucle ; Torna a repetir
; ; Posa a zero els bytes del vector figura ; PosaZero movlw .8 ; Número de bytes que cal posar a zero movwf Compt ; Variable per comptar els bytes movlw figura ; Agafem l'adreça de la primera posició del vector movwf FSR ; La posem com a punter d'adreçament indirecte BucleZero clrf INDF ; Posa a zero la posició actual incf FSR,f ; Incrementa el punter decfsz Compt,f ; Decrementa Compt goto BucleZero ; Si Compt no és zero, repeteix el bucle return ; ; Funció que llegeix els polsadors ; Llegir clrf Polsador ; Si aquest valor no es canvia és que no hi ha cap polsador premut nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon, en total 5 bsf ADCON0,GO ; Inicia la conversió btfsc ADCON0,GO ; Quan el bit sigui 0 la conversió haurà acabat goto $-1 ; repetim la línia fins que deixi de ser 0 ; Comparació P1 movlw .220 ; Límit superior de P1 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP1 ; ADRESH >= W movlw .200 ; Límit inferior de P1 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP1 ; ADRESH < W movlw b'00000001' ; Polsador P1 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP1 ; Comparació P2 movlw .194 ; Límit superior de P2 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP2 ; ADRESH >= W movlw .174 ; Límit inferior de P2 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP2 ; ADRESH < W movlw b'00000010' ; Polsador P2 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP2 ; Comparació P3 movlw .163 ; Límit superior de P3 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP3 ; ADRESH >= W movlw .143 ; Límit inferior de P3 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP3 ; ADRESH < W movlw b'00000100' ; Polsador P3 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP3 ; Comparació P4 movlw .90 ; Límit superior de P4 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP4 ; ADRESH >= W movlw .70 ; Límit inferior de P4 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP4 ; ADRESH < W movlw b'00001000' ; Polsador P4 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP4 ; Comparació P5 movlw .55 ; Límit superior de P5 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP5 ; ADRESH >= W movlw .35 ; Límit inferior de P5 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP5 ; ADRESH < W movlw b'00010000' ; Polsador P5 movwf Polsador ; Ho copia a Polsador NoP5 return ; ; Apaga tots els LED ; Apaga movlw .8 ; Hem d'apagar vuit fileres movwf Filera ; Ho guarda al comptador Repetir movf Filera,w ; Filera actual movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw b'00000000' ; Apagat movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia3max ; Ho envia al MAX7221 decfsz Filera,f ; Passem a una altra filera goto Repetir return ; ; Inicialització de tres MAX7221 ; Ini3max movlw 0x0C ; Shutdown mode movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw 0x00 ; Desactivat movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia_max ; Ho envia al MAX7221 movlw 0x09 ; Decode mode movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw 0x00 ; No decode movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia_max ; Ho envia al MAX7221 movlw 0x0B ; Scan limit movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw 0x07 ; Vuit fileres movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia_max ; Ho envia al MAX7221 return ; ; Envia dades (48 bits) a tres MAX7221 ; desactivant les interrupcions ; Envia3max bcf INTCON,T0IE ; Desactiva les interrupcions momentàniament call Envia_max bsf INTCON,T0IE ; Reactiva les interrupcions a l'acabar return ; ; Envia dades (48 bits) a tres MAX7221 ; ; Els bits estan a les variables: ; Sortida Valor vermells ; Sortida+1 Adreça vermells ; Sortida+2 Valor verds ; Sortida+3 Adreça verds ; Sortida+4 Valor blaus ; Sortida+5 Adreça blaus ; Al final de la funció, el valor de Sortida queda corromput ; Si es vol conservar, cal copiar-lo a una altra variable ; ; Aquesta funció dura, aproximadament, 1 ms Envia_max bcf Port,5 ; S'assegura que Clock està desactivat bcf Port,6 ; S'assegura que Latch està desactivat movf Port,w ; Agafa el valor de Port movwf PORTB ; I el posa al port B movlw .48 ; Número de bits a enviar movwf Compta ; Variable per comptar els bits Bucle3max bcf Port,4 ; Desactiva Data. Si toca activar-ho, ja ho farem rlf Sortida,f ; Fa sortir el bit de més a l'esquerra cap a C rlf Sortida+1,f ; i roda els altres a l'esquerra rlf Sortida+2,f rlf Sortida+3,f rlf Sortida+4,f rlf Sortida+5,f btfsc STATUS,C ; Mira si el bit de l'esquerra era un 1 bsf Port,4 ; Si era 1, activa Data movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Data movwf PORTB ; I el posa al port B bsf Port,5 ; Activa Clock, forçant a llegir el bit movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Clock movwf PORTB ; I el posa al port B bcf Port,5 ; Desactiva Clock movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Clock movwf PORTB ; I el posa al port B decfsz Compta,f ; Decrementa Compta goto Bucle3max ; Si Compta no és zero, repeteix el bucle bsf Port,6 ; Torna a activar Latch ; Els valors es copiaran a la sortida del registre movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Latch movwf PORTB ; I el posa al port B return ; ; Funció de retard de 0,771 W ms ; Retms movwf Retard2 Buclems decfsz Retard1,f goto Buclems decfsz Retard2,f goto Buclems return end
La següent versió del programa és molt similar però mostra el cursor intermitent. Per fer-ho, decrementa el comptador a cada cicle i quan s'assoleix el nombre de cicles canvia la variable que controla si el cursor està encès o apagat.
#include <p16F690.inc> __config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF) #define cic_int .35 ; Nombre de cicles per a la intermitència
cblock 0x20 Port ; Bits a enviar al port B Sortida:6 ; Valors a enviar al MAX7221 (48 bits) Compta ; Variable per comptar els bits a Envia_max Compt ; Variable per comptar els bytes Comp ; Variable per comptar els bits Filera ; Variable per comptar fileres Actiu ; Variable que diu quin color està actiu ; Actiu = 0 Apagat ; Actiu = 1 Vermell ; Actiu = 2 Verd ; Actiu = 3 Blau Polsador ; Variable que conté un bit per a cada polsador per saber si està premut x ; Coordenada X del cursor (0 a 7) ; X = 0 és la columna de la dreta y ; Coordenada Y del cursor (0 a 7) caux ; Comptador auxiliar mirar ; Espera que es deixi anar el polsador mascara ; Màscara per a les operacions amb bits compt_int ; Comptador de cicles per a la intermitència cur_on ; Controla l'estat del cursor Retard1 ; Variables per als cicles de retard Retard2 endc cblock 0x70 ; Zona de memòria de dades que no depèn del banc triat W_Copia ; Guardarà el contingut de W durant la interrupció ST_Copia ; Guardarà STATUS durant la interrupció endc cblock 0xA0 ; Zona de memòria de dades del banc 1 figura:8 ; Aquí guardarem el dibuix (8 fileres) endc
org 0 goto Inici ; Saltem al lloc on hi ha el programa principal nop ; Zona de memòria de programa que no utilitzem nop nop
Interrup movwf W_Copia ; Copiem l'acumulador a W_Copia swapf STATUS,w ; Copiem STATUS a l'acumulador permutant els nibbles clrf STATUS ; Posa a 0 i així segur que el banc és el 0 movwf ST_Copia ; Guarda STATUS permutat a ST_Copia btfss INTCON,T0IF ; Mira si Timer0 ha arribat a zero ; Si hi ha arribat, no fa la instrucció següent goto FiInt ; Si la interrupció no és del Timer0 no fem res Timer0 ; Programa corresponent a Timer0 bcf INTCON,T0IF ; Si ha arribat, desactivem el bit movlw .100 ; Nova preselecció movwf TMR0 ; Ho posem a TMR0 ; Anem a gestionar el canvi de color movlw b'00000011' ; Descarta els bits que no serveixen andwf Actiu,f btfsc STATUS,Z goto NoZero ; Si Actiu val 0 no ho canvia decf Actiu,f ; Passem a activar un altre color btfss STATUS,Z ; Si s'activa Z és que hem arribat a zero goto NoZero ; Si és zero, tornem a 3 movlw .3 movwf Actiu NoZero ; Gestiona l'activació de tres MAX7221 ; Segons Actiu, activa un color o un altre movlw b'00000011' ; Descarta els bits que no serveixen andwf Actiu,f btfsc STATUS,Z ; Salta si el resultat no és zero goto Apagat ; Si està apagat ho desactiva tot movlw .1 xorwf Actiu,w btfsc STATUS,Z goto Vermell ; Si val 1, activem el vermell movlw .2 xorwf Actiu,w btfsc STATUS,Z goto Verd ; Si val 2, activem el verd ; Si no és cap d'ells, activem el blau movlw 0x01 ; Activat movwf Sortida+4 ; Blau movlw 0x00 ; Desactivat movwf Sortida ; Vermell movwf Sortida+2 ; Verd movlw .1 goto Activa Vermell movlw 0x01 ; Activat movwf Sortida ; Vermell movlw 0x00 ; Desactivat movwf Sortida+2 ; Verd movwf Sortida+4 ; Blau nop ; Temps a afegir nop nop nop goto Activa Verd movlw 0x01 ; Activat movwf Sortida+2 ; Verd movlw 0x00 ; Desactivat movwf Sortida ; Vermell movwf Sortida+4 ; Blau goto Activa Apagat movlw 0x00 ; Desactivat movwf Sortida ; Vermell movwf Sortida+2 ; Verd movwf Sortida+4 ; Blau Activa movlw 0x0C ; Shutdown mode movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho call Envia_max ; Ho envia als MAX7221 FiInt swapf ST_Copia,w ; Copia permutant ST_Copia a l'acumulador movwf STATUS ; I ho passa a STATUS recuperant el valor d'abans ; de la interrupció swapf W_Copia,f ; Permuta els bits de W_Copia swapf W_Copia,w ; Torna a permutar els bits de W_Copia ; i els guarda a l'acumulador sense variar STATUS retfie ; Torna al programa principal, on s'havia quedat
Inici bsf STATUS,RP0 ; Tria el banc 1 movlw b'10000101' ; Configuració de Timer0 ; Com a temporitzador basat en rellotge ; 101 - Factor d'escala de 64 ; I resistències de pull-up desactivades (valor per defecte) movwf OPTION_REG ; Ho guarda al registre de configuració del Timer0 movlw 0xFF ; Posa l'acumulador a FFh (tot uns) movwf TRISA ; Posa tots els bits del port A com a entrada clrf TRISB ; Posa tots els bits del port B com a sortida clrf TRISC ; Posa tots els bits del port C com a sortida movlw b'00010000' movwf ADCON1 ; Posa el conversor a 1/8 de la freqüència bcf STATUS,RP0 bsf STATUS,RP1 ; Tria el banc 2 movlw b'00000101' movwf ANSEL ; Configura AN0 i AN2 com entrada analògica bcf STATUS,RP0 bcf STATUS,RP1 ; Tria el banc 0 clrf PORTC clrf Port ; Posa a zero tots els bits de la variable Port movf Port,w movwf PORTB ; I ho envia al port B movlw b'00001001' movwf ADCON0 ; Activa el conversor A/D connectat a AN2 ; amb el resultat justificat per l'esquerra call Ini3max ; Inicialitza la matriu ; Configura Timer 0 i activa la matriu i les interrupcions ; Una interrupció cada, aproximadament, 10 ms movlw .1 movwf Actiu ; Posa en marxa el vermell movlw .100 ; Presselecció de 100, que són 156 iteracions movwf TMR0 ; Ho posa com a preselecció del temporitzador movlw b'10100000' ; Activem GIE i T0IE movwf INTCON ; Activa les interrupcions globals i la de Timer0 call Apaga ; Apaga els LED clrf x ; Posa x a zero clrf y ; Posa y a zero movlw 1 movwf mirar ; Posa mirar a 1 movwf cur_on ; Posa cur_on a 1 movlw cic_int ; Nombre de cicles per a la intermitència movwf compt_int call PosaZero ; Posa a zero els bytes del vector figura Bucle ; Mirem els polsadors ; Un cop s'ha fet l'acció del polsador, no es tornarà a fer fins ; que es detecti que s'han deixat anar call Llegir ; Llegeix els polsadors movf mirar,f ; S'han de mirar els polsadors? btfsc STATUS,Z ; Si és zero no s'han de mirar goto NoMirar ; Anem a veure si ja s'ha deixat anar movf Polsador,w xorlw b'00000001' ; Mirem si s'ha premut el polsador 1 btfss STATUS,Z ; Si és l'1, salta goto NoPol1 ; No és l'1 ; S'ha premut el polsador 1 incf x,f ; Incrementem x del cursor movlw b'00000111' ; Valor 7 andwf x,f ; Limitem x entre 0 i 7 goto Zmirar ; Ja estem del polsador 1 NoPol1 movf Polsador,w xorlw b'00000010' ; Mirem si s'ha premut el polsador 2 btfss STATUS,Z ; Si és el 2, salta goto NoPol2 ; No és el 2 ; S'ha premut el polsador 2 incf y,f ; Incrementem y del cursor movlw b'00000111' ; Valor 7 andwf y,f ; Limitem x entre 0 i 7 goto Zmirar ; Ja estem del polsador 2 NoPol2 movf Polsador,w xorlw b'00000100' ; Mirem si s'ha premut el polsador 3 btfss STATUS,Z ; Si és el 3, salta goto NoPol3 ; No és el 3 ; S'ha premut el polsador 3 movlw b'00000001' ; Posem un 1 a la columna 0 movwf mascara ; Ho guardem com a màscara movf x,w ; Agafem la x del cursor btfsc STATUS,Z ; Mirem si és zero goto xZero ; Si és zero no cal fer res movwf Comp ; Hem de rodar els bits x posicions rodaX bcf STATUS,C ; Volem entrar zeros rlf mascara,f ; Rodem a l'esquerra i entrem el zero decfsz Comp,f ; Decrementa Comp goto rodaX ; Si Comp no és zero, repeteix el bucle xZero ; Ja tenim l'1 posat a la columna movlw figura ; Agafem l'adreça de la primera posició del vector movwf FSR ; La posem com a punter d'adreçament indirecte movf y,w ; Agafem la y del cursor addwf FSR,f ; Ho afegim al punter movf mascara,w ; Agafa la màscara xorwf INDF,f ; L'aplica a la filera corresponent goto Zmirar ; Ja estem del polsador 3 NoPol3 movf Polsador,w xorlw b'00001000' ; Mirem si s'ha premut el polsador 4 btfss STATUS,Z ; Si és el 4, salta goto NoPol4 ; No és el 4 ; S'ha premut el polsador 4 ; El polsador 4 no fa res goto Zmirar ; Ja estem del polsador 4 NoPol4 movf Polsador,w xorlw b'00010000' ; Mirem si s'ha premut el polsador 5 btfss STATUS,Z ; Si és el 5, salta goto NoPol5 ; No és el 5 ; S'ha premut el polsador 5 call PosaZero ; Posa a zero els bytes del vector figura Zmirar ; Ja estem del polsador 5 clrf mirar ; Posa mirar a zero fins que es deixi el polsador NoPol5 goto Matriu ; Envia la figura actual a la matriu NoMirar movf Polsador,w ; Agafem la lectura dels polsadors btfss STATUS,Z ; Mira si és zero goto Matriu ; Si no és zero cal seguir esperant movlw 1 ; Si és zero, s'ha deixat el polsador movwf mirar ; Posa mirar a 1 Matriu ; Anem a mostrar la figura actual a la matriu de LED clrf caux ; Primer enviem la filera 0 movlw .8 ; Número de bytes que cal enviar movwf Compt ; Variable per comptar els bytes movlw figura ; Agafem l'adreça de la primera posició del vector movwf FSR ; La posem com a punter d'adreçament indirecte BucleMatriu clrf Sortida ; Vermell, en principi, a zero clrf Sortida+2 ; Verd, en principi, a zero movf INDF,w ; Agafa la filera actual movwf Sortida+4 ; La posa en el blau ; Mirem si s'ha de mostrar el cursor movf cur_on,w ; Mirem el valor de cur_on btfsc STATUS,Z ; Si no és zero, mostrem el cursor goto noCur ; Si és zero no hem de mostrar el cursor ; Anem a veure si estem a la filera del cursor movf caux,w ; Mirem la filera que estem enviant xorwf y,w ; I comparem amb la del cursor btfss STATUS,Z ; Si és zero, són iguals goto noCur ; No és la filera del cursor movlw b'00000001' ; Posem un 1 a la columna 0 movwf mascara ; Ho guardem com a màscara movf x,w ; Agafem la x del cursor btfsc STATUS,Z ; Mirem si és zero goto xnul ; Si és zero no cal fer res movwf Comp ; Hem de rodar els bits x posicions giraX bcf STATUS,C ; Volem entrar zeros rlf mascara,f ; Rodem a l'esquerra i entrem el zero decfsz Comp,f ; Decrementa Comp goto giraX ; Si Comp no és zero, repeteix el bucle xnul ; Ja tenim l'1 posat a la columna movf mascara,w ; Agafem la màscara que hem preparat (set 0 i un 1) iorwf Sortida,f ; L'apliquem al vermell iorwf Sortida+2,f ; i al verd, per fer el cursor groc comf mascara,w ; Agafem l'invers de la màscara (set 1 i un 0) andwf Sortida+4,f ; L'apliquem al blau per apagar el LED ; Fi del tractament del cursor noCur ; A la matriu s'hi envien valors entre 1 i 8 (no de 0 a 7) incf caux,w ; Incrementa l'índex i el guarda a w movwf Sortida+1 ; El posa per indicar la filera que escrivim movwf Sortida+3 ; El posa per indicar la filera que escrivim movwf Sortida+5 ; El posa per indicar la filera que escrivim call Envia3max ; Ho envia al MAX7221 incf FSR,f ; Incrementa el punter incf caux,f ; Incrementa l'índex decfsz Compt,f ; Decrementa Compt goto BucleMatriu ; Si Compt no és zero, repeteix el bucle movlw 1 ; Retard de 0,771 ms call Retms decfsz compt_int,f ; Decrementa el comptador per a la intermitència goto Bucle ; Si no és zero, torna a l'inici del bucle movlw cic_int ; Nombre de cicles per a la intermitència movwf compt_int incf cur_on,f ; Incrementa cur_on movlw b'00000001' ; Valor 1 andwf cur_on,f ; Limitem cur_on entre 0 i 1 goto Bucle ; Torna a repetir
; ; Posa a zero els bytes del vector figura ; PosaZero movlw .8 ; Número de bytes que cal posar a zero movwf Compt ; Variable per comptar els bytes movlw figura ; Agafem l'adreça de la primera posició del vector movwf FSR ; La posem com a punter d'adreçament indirecte BucleZero clrf INDF ; Posa a zero la posició actual incf FSR,f ; Incrementa el punter decfsz Compt,f ; Decrementa Compt goto BucleZero ; Si Compt no és zero, repeteix el bucle return ; ; Funció que llegeix els polsadors ; Llegir clrf Polsador ; Si aquest valor no es canvia és que no hi ha cap polsador premut nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon nop ; espera un microsegon, en total 5 bsf ADCON0,GO ; Inicia la conversió btfsc ADCON0,GO ; Quan el bit sigui 0 la conversió haurà acabat goto $-1 ; repetim la línia fins que deixi de ser 0 ; Comparació P1 movlw .220 ; Límit superior de P1 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP1 ; ADRESH >= W movlw .200 ; Límit inferior de P1 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP1 ; ADRESH < W movlw b'00000001' ; Polsador P1 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP1 ; Comparació P2 movlw .194 ; Límit superior de P2 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP2 ; ADRESH >= W movlw .174 ; Límit inferior de P2 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP2 ; ADRESH < W movlw b'00000010' ; Polsador P2 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP2 ; Comparació P3 movlw .163 ; Límit superior de P3 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP3 ; ADRESH >= W movlw .143 ; Límit inferior de P3 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP3 ; ADRESH < W movlw b'00000100' ; Polsador P3 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP3 ; Comparació P4 movlw .90 ; Límit superior de P4 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP4 ; ADRESH >= W movlw .70 ; Límit inferior de P4 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP4 ; ADRESH < W movlw b'00001000' ; Polsador P4 movwf Polsador ; Ho copia a Polsador goto NoP5 NoP4 ; Comparació P5 movlw .55 ; Límit superior de P5 subwf ADRESH,w ; W = ADRESH - W btfsc STATUS,C ; C = 1 si ADRESH >= W goto NoP5 ; ADRESH >= W movlw .35 ; Límit inferior de P5 subwf ADRESH,w ; W = ADRESH - W btfss STATUS,C ; C = 1 si ADRESH >= W goto NoP5 ; ADRESH < W movlw b'00010000' ; Polsador P5 movwf Polsador ; Ho copia a Polsador NoP5 return ; ; Apaga tots els LED ; Apaga movlw .8 ; Hem d'apagar vuit fileres movwf Filera ; Ho guarda al comptador Repetir movf Filera,w ; Filera actual movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw b'00000000' ; Apagat movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia3max ; Ho envia al MAX7221 decfsz Filera,f ; Passem a una altra filera goto Repetir return ; ; Inicialització de tres MAX7221 ; Ini3max movlw 0x0C ; Shutdown mode movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw 0x00 ; Desactivat movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia_max ; Ho envia al MAX7221 movlw 0x09 ; Decode mode movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw 0x00 ; No decode movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia_max ; Ho envia al MAX7221 movlw 0x0B ; Scan limit movwf Sortida+1 ; Ho prepara per enviar-ho movwf Sortida+3 ; Ho prepara per enviar-ho movwf Sortida+5 ; Ho prepara per enviar-ho movlw 0x07 ; Vuit fileres movwf Sortida ; Ho prepara per enviar-ho movwf Sortida+2 ; Ho prepara per enviar-ho movwf Sortida+4 ; Ho prepara per enviar-ho call Envia_max ; Ho envia al MAX7221 return ; ; Envia dades (48 bits) a tres MAX7221 ; desactivant les interrupcions ; Envia3max bcf INTCON,T0IE ; Desactiva les interrupcions momentàniament call Envia_max bsf INTCON,T0IE ; Reactiva les interrupcions a l'acabar return ; ; Envia dades (48 bits) a tres MAX7221 ; ; Els bits estan a les variables: ; Sortida Valor vermells ; Sortida+1 Adreça vermells ; Sortida+2 Valor verds ; Sortida+3 Adreça verds ; Sortida+4 Valor blaus ; Sortida+5 Adreça blaus ; Al final de la funció, el valor de Sortida queda corromput ; Si es vol conservar, cal copiar-lo a una altra variable ; ; Aquesta funció dura, aproximadament, 1 ms Envia_max bcf Port,5 ; S'assegura que Clock està desactivat bcf Port,6 ; S'assegura que Latch està desactivat movf Port,w ; Agafa el valor de Port movwf PORTB ; I el posa al port B movlw .48 ; Número de bits a enviar movwf Compta ; Variable per comptar els bits Bucle3max bcf Port,4 ; Desactiva Data. Si toca activar-ho, ja ho farem rlf Sortida,f ; Fa sortir el bit de més a l'esquerra cap a C rlf Sortida+1,f ; i roda els altres a l'esquerra rlf Sortida+2,f rlf Sortida+3,f rlf Sortida+4,f rlf Sortida+5,f btfsc STATUS,C ; Mira si el bit de l'esquerra era un 1 bsf Port,4 ; Si era 1, activa Data movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Data movwf PORTB ; I el posa al port B bsf Port,5 ; Activa Clock, forçant a llegir el bit movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Clock movwf PORTB ; I el posa al port B bcf Port,5 ; Desactiva Clock movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Clock movwf PORTB ; I el posa al port B decfsz Compta,f ; Decrementa Compta goto Bucle3max ; Si Compta no és zero, repeteix el bucle bsf Port,6 ; Torna a activar Latch ; Els valors es copiaran a la sortida del registre movf Port,w ; Agafa el valor de Port. El valor que ha canviat és Latch movwf PORTB ; I el posa al port B return ; ; Funció de retard de 0,771 W ms ; Retms movwf Retard2 Buclems decfsz Retard1,f goto Buclems decfsz Retard2,f goto Buclems return end

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