Programació en pic-as del PIC 16F690

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

Exemple MS - Text en moviment a la matriu de LED

En aquest exemple farem aparèixer un conjunt de caràcters que es desplacen d'esquerra a dreta de la matriu. En aquest cas concret són les xifres del 0 al 4, però podria ser qualsevol caràcter. Les xifres s'han posat desordenades (0, 2, 1 i 3) per indicar que es poden posar en qualsevol ordre; també es podien repetir. Cal que cada caràcter estigui definit; per fer-ho senzill i compacte guardem les definicions dels caràcters a la memòria de programa, com en un dels programes de l'exemple ML. Cada caràcter s'ha creat amb una matriu de 7 ⨯ 5 punts però el definim amb vuit fileres perquè així és més fàcil multiplicar per vuit (rodant els bits), que és el que necessitem per trobar el caràcter que ens cal a cada moment.

El programa treballa amb dos caràcters a la vegada, un que es mostra a la part esquerra de la matriu i un altre que es mostra a la part dreta. A mesura que es va desplaçant, es mostren menys píxels del caràcter de l'esquerra i més del de la dreta. Hem optat per iniciar i acabar la seqüència amb la matriu apagada, per això s'ha definit un bucle amb una posició més. A cada iteració del bucle s'agafa un caràcter per al costat esquerra de la matriu (buit en la primera iteració) i un per al costat dret (buit en la darrera iteració).

Per definir els caràcters ens hem basat en la definició que hi ha a la pàgina 17 del full de característiques de la pantalla sèrie i ho hem fet emprant aquest full de càlcul, que ja ens genera la línia completa per posar al programa.

L'altra millora és que hem implementat la possibilitat de triar el color. La funció EnviaText mira la variable Color i, segons el seu valor, fa sortir els caràcters en el color triat. El bucle del programa reprodueix el text amb cada un dels set colors possibles i després torna a començar, però es podria triar un sol color. Els valors que corresponen a cada color són els de la taula següent:

Valor de Color Color que li correspon
Decimal Binari
7 111 Blanc
6 110 Groc
5 101 Magenta
4 100 Vermell
3 011 Cian
2 010 Verd
1 001 Blau
0 000 Apagat

Podem observar que cada un dels tres bits menys significatius correspon a un dels tres colors primaris (vermell, verd i blau), i això fa molt més fàcil comprovar quins dels colors s'han d'activar.

PROCESSOR 16F690
#include <xc.inc>
#define numcar 4
#define blanc 99  ; Punter (inexistent) que representa el blanc
config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
Port EQU 0x20  ; Bits a enviar al port B
Sortida EQU 0x21  ; Valors a enviar al MAX7221 (6 bytes, 48 bits)
ComptBits EQU 0x27  ; Variable per comptar els bits
ComptRota EQU 0x28  ; Variable per comptar rotacions
Filera EQU 0x29  ; Variable per comptar fileres
AdreH EQU 0x2A  ; Adreça per la taula
AdreL EQU 0x2B
AdreHE EQU 0x2C  ; Adreça per al caràcter de l'esquerra
AdreLE EQU 0x2D
AdreHD EQU 0x2E  ; Adreça per al caràcter de la dreta
AdreLD EQU 0x2F
ValorE EQU 0x30  ; Valor a enviar al costat esquerre
ValorD EQU 0x31  ; Valor a enviar al costat dret
Valor EQU 0x32  ; Variable temporal per rodar els bits de ValorE i ValorD
Posic EQU 0x33  ; Posició a la llista de caràcters
Color EQU 0x34  ; Color en el que es mostrarà el text
                ; 4 vermell  2 verd       1 blau     7 blanc
                ; 6 groc     5 magenta    3 cian     0 apagat
Actiu EQU 0x35  ; Variable que diu quin color està actiu
                ; Actiu = 0		Apagat
                ; Actiu = 1		Vermell
                ; Actiu = 2		Verd
                ; Actiu = 3		Blau
Despla EQU 0x36  ; Posició del desplaçament
Esquerra EQU 0x37  ; Part esquerra de la línia
Dreta EQU 0x38  ; Part dreta de la línia
Retard1 EQU 0x39  ; Variables per als cicles de retard
Retard2 EQU 0x3A
Retard3 EQU 0x3B
; Zona de memòria de dades que no depèn del banc triat
W_Copia EQU 0x70  ; Guardarà el contingut de W durant la interrupció
ST_Copia EQU 0x71  ; Guardarà STATUS durant la interrupció 
PSECT code, class=CODE, delta=2, abs
main:  ; Adreça 0 h
  goto	Inici  ; Saltem al lloc on hi ha el programa principal
  nop  ; Zona de memòria de programa que no utilitzem
  nop
  nop
Interrup:  ; Adreça 4 h
  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 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 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 00000011B  ; Descarta els bits que no serveixen
  andwf Actiu,f
  btfsc ZERO
  goto NoZero  ; Si Actiu val 0 no ho canvia
  decf Actiu,f  ; Passem a activar un altre color
  btfss ZERO  ; 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 00000011B  ; Descarta els bits que no serveixen
  andwf Actiu,f
  btfsc ZERO  ; Salta si el resultat no és zero
  goto Apagat  ; Si està apagat ho desactiva tot
  movlw 1
  xorwf Actiu,w
  btfsc ZERO
  goto Vermell  ; Si val 1, activem el vermell
  movlw 2
  xorwf Actiu,w
  btfsc ZERO
  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 al 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 RP0  ; Tria el banc 1
  movlw 10000101B  ; 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
  bcf RP0
  bsf RP1  ; Tria el banc 2
  movlw 00000101B
  movwf ANSEL  ; Configura AN0 i AN2 com entrada analògica
  bcf RP0
  bcf 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
  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 10100000B  ; Activem GIE i T0IE
  movwf INTCON  ; Activa les interrupcions globals i la de Timer0
  call Apaga  ; Apaga els LED
  movlw 7  ; Comencem amb blanc
  movwf Color
Bucle:
  call EnviaText  ; Envia el text amb el color indicat
  movlw 7  ; En previsió, preparem per posar blanc
  decf Color,f  ; Canviem el color
  btfsc ZERO  ; Mira si hem arribat a zero
  movwf Color  ; Si hem arribat a zero, tornem a començar
  movlw 1  ; Retard
  call Retard
  goto Bucle  ; Torna a repetir
;
; Envia el text amb el color indicat
;
EnviaText:
  clrf Posic  ; Comencem pel primer caràcter
  ; Cal enviar tants caràcters com la llargada del text
  ; Amb un en blanc (representat per numcar) al principi i un al final
BucEnvTxt:
  ; Posic anirà de 0 fins a numcar
  ; Si Posic és 0, enviem un blanc
  ; Agafem el número del caràcter actual
  movlw blanc  ; Preparem per si cal enviar un blanc
  movf Posic,f  ; Mirem si és 0
  btfsc ZERO  ; Si és 0, s'envia un blanc
  goto blancE  ; Enviem un blanc
  movlw high Text  ; Carrega la part alta de l'adreça de la taula
  movwf AdreH  ; Ho guarda per posar-ho a PCLATH
  movlw low Text  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreL  ; Ho guarda per posar-ho a PCL
  decf Posic,w  ; Quin caràcter toca: Posic-1
  addwf AdreL,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreH,f  ; Si s'ha activat, incrementem AdreH
  call Llegir  ; Llegeix el caràcter
  movwf ValorE  ; Caràcter de la banda esquerra
  goto NoBlancE
blancE:
  movlw blanc  ; Cal enviar un blanc
  movwf ValorE  ; Caràcter de la banda esquerra
  movlw high Text  ; Carrega la part alta de l'adreça de la taula
  movwf AdreH  ; Ho guarda per posar-ho a PCLATH
  movlw low Text  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreL  ; Ho guarda per posar-ho a PCL
  movf Posic,w  ; Quin caràcter toca: Posic
  addwf AdreL,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreH,f  ; Si s'ha activat, incrementem AdreH
  call Llegir  ; Llegeix el caràcter
  goto blancD
NoBlancE:
  ; També ens cal el caràcter següent
  ; Excepte si ja estem a numcar
  movlw numcar  ; Agafem el valor de comparació
  xorwf Posic,w  ; Comparem amb la posició actual
  btfss ZERO  ; Si coincideixen, salta
  goto MiraD  ; Si no son iguals, mirem què hi ha
  movlw blanc  ; Toca un blanc
  goto blancD
MiraD:
  incf AdreL,f  ; Incrementa la posició
  btfsc ZERO  ; Mirem si s'activa Z
  incf AdreH,f  ; Si s'ha activat, incrementem AdreH
  call Llegir  ; Llegeix el caràcter
blancD:
  movwf ValorD  ; Caràcter de la banda dreta
  clrf Despla  ; Comencem sense desplaçament
  ; Per a cada parella de caràcters cal enviar vuit cops, un per desplaçament
BucEnvCar:
  movlw 1  ; Comencem per la filera 1
  movwf Filera
  ; Llegim la primera posició del caràcter de l'esquerra
  movf ValorE,w  ; En fem una còpia per poder rodar
  movwf Valor
  movlw high Carac  ; Carrega la part alta de l'adreça de la taula
  movwf AdreHE  ; Ho guarda per posar-ho a PCLATH
  movlw low Carac  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreLE  ; Ho guarda per posar-ho a PCL
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 2
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 4
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,w  ; Valor que volem enviar, multiplicat per 8; el deixem a w
  addwf AdreLE,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreHE,f  ; Si s'ha activat, incrementem AdreH
  ; Llegim la primera posició del caràcter de la dreta
  movf ValorD,w  ; En fem una còpia per poder rodar
  movwf Valor
  movlw high Carac  ; Carrega la part alta de l'adreça de la taula
  movwf AdreHD  ; Ho guarda per posar-ho a PCLATH
  movlw low Carac  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreLD  ; Ho guarda per posar-ho a PCL
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 2
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 4
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,w  ; Valor que volem enviar, multiplicat per 8; el deixem a w
  addwf AdreLD,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreHD,f  ; Si s'ha activat, incrementem AdreH
  ; Per a cada enviament calen vuit línies
BucEnvLin:
  ; Per defecte, els tres colors apagats
  clrf Sortida  ; Vermells
  clrf Sortida+2  ; Verds
  clrf Sortida+4  ; Blaus
  ; Deixem preparats els punters de filera
  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
  ; Anem a preparar el que cal enviar
  movlw blanc  ; Anem a veure si és un blanc
  xorwf ValorE,w  ; Valor de l'esquerra
  btfss ZERO  ; Si són iguals, salta
  goto NoBlancEsq  ; Si són diferents
  clrw  ; Si són iguals, blanc
  goto blancEsq
NoBlancEsq:  
  ; Llegim la part del caràcter de l'esquerra
  movf AdreHE,w  ; Copiem les adreces de l'esquerra
  movwf AdreH
  movf AdreLE,w  ; Copiem les adreces de l'esquerra
  movwf AdreL
  call Llegir  ; Llegeix la filera
blancEsq:
  movwf Esquerra
  movlw blanc  ; Anem a veure si és un blanc
  xorwf ValorD,w  ; Valor de la dreta
  btfss ZERO  ; Si són iguals, salta
  goto NoBlancDre  ; Si són diferents
  clrw  ; Si són iguals, blanc
  goto blancDre
NoBlancDre:  
  ; Llegim la part del caràcter de la dreta
  movf AdreHD,w  ; Copiem les adreces de la dreta
  movwf AdreH
  movf AdreLD,w  ; Copiem les adreces de la dreta
  movwf AdreL
  call Llegir  ; Llegeix la filera
blancDre:
  movwf Dreta
  ; Ara hem d'aplicar el desplaçament
  ; Si el desplaçament és nul, ens estalviem feina
  movf Despla,f  ; Nombre de rotacions a fer
  btfsc ZERO
  goto NoRodem  ; Si és zero, no rodem
  movf Despla,w
  movwf ComptRota  ; Nombre de rotacions a fer
  ; Rodem la part esquerra
RodemE:
  bcf CARRY  ; Ens assegurem que entren zeros
  rlf Esquerra,f  ; Rodem un cop
  decfsz ComptRota,f  ; Un menys
  goto RodemE  ; Si no estem, repetim
  ; Rodem la part dreta
  movlw 8  ; Són 8 bits
  movwf ComptRota  ; Nombre de rotacions a fer
  movf Despla,w
  subwf ComptRota,f  ; ComptRota = 8 - Despla
RodemD:
  bcf CARRY  ; Ens assegurem que entren zeros
  rrf Dreta,f  ; Rodem un cop
  decfsz ComptRota,f  ; Un menys
  goto RodemD  ; Si no estem, repetim
  ; Ja hem rodat, anem a composar la línia
  movf Esquerra,w  ; Agafem la part esquerra
  iorwf Dreta,w  ; Ho combinem amb la dreta
  goto HemRodat  ; Ja està a punt
NoRodem:
  movf  Esquerra,w  ; Si no hi ha desplaçament coincideix amb el de l'esquerra
  ; Ara anem a enviar-ho a la matriu
HemRodat:  
  ; Quins colors cal activar?
  btfsc Color,2  ; S'ha de posar vermell?
  movwf Sortida  ; Vermells
  btfsc Color,1  ; S'ha de posar verd?
  movwf Sortida+2  ; Verds
  btfsc Color,0  ; S'ha de posar blau?
  movwf Sortida+4  ; Blaus
  call Envia3max  ; Ho envia al MAX7221
  ; Hem enviat una línia, preparem la següent
  incf AdreLE,f  ; Incrementa el punter	
  btfsc ZERO  ; S'ha activat Z?
  incf AdreHE,f  ; Si s'ha activat, incrementem AdreH
  incf AdreLD,f  ; Incrementa el punter	
  btfsc ZERO  ; S'ha activat Z?
  incf AdreHD,f  ; Si s'ha activat, incrementem AdreH
  incf Filera,f  ; Filera següent
  movlw 9  ; Si és 9, ja hem acabat
  xorwf Filera,w
  btfss ZERO
  goto BucEnvLin  ; Si no és zero, envia el següent
  ; Ja hem enviat una posició, seguim desplaçant
  movlw 1  ; Retard de moviment
  call Retard
  incf Despla,f  ; Desplaça una posició
  movlw 8  ; Ja hem desplaçat les 8?
  xorwf Despla,w
  btfss ZERO
  goto BucEnvCar  ; Si no és vuit, seguim
  ; Ja hem fet tot el desplaçament, caràcter següent
  incf Posic,f  ; Desplaça una posició
  movlw numcar+1  ; Ja hem enviat tots els caràcters?
  xorwf Posic,w
  btfss ZERO
  goto BucEnvTxt  ; Si no estem, seguim
  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 00000000B  ; 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 T0IE  ; Desactiva les interrupcions momentàniament
  call Envia_max
  bsf 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 ComptBits  ; 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 CARRY  ; 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 ComptBits,f  ; Decrementa ComptBits
  goto Bucle3max  ; Si ComptBits 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,2 W s
;
Retard:		
  movwf Retard3
Bucles:
  decfsz Retard1,f		
  goto Bucles		
  decfsz Retard2,f		
  goto Bucles		
  decfsz Retard3,f	
  goto Bucles
  return
;
; Llegeix la taula amb les imatges
;
Llegir:
  bcf	T0IE	; Desactiva les interrupcions momentàniament
  movf AdreH,w  ; Llegim l'adreça de la variable
  bsf RP1  ; Tria el banc 2
  movwf EEADRH  ; Adreça EEPROM
  bcf RP1  ; Tria el banc 0
  movf AdreL,w  ; Llegim l'adreça de la variable
  bsf RP1  ; Tria el banc 2
  movwf EEADR  ; Adreça EEPROM
  bsf RP0  ; Tria el banc 3
  bsf EEPGD  ; Accés a memòria de programa
  bsf RD  ; Lectura
  nop
  nop  ; espera dos cicles
  bcf RP0  ; Tria el banc 2
  movf 	EEDAT,w  ; Llegim
  bcf RP1  ; Tria el banc 0
  bsf	T0IE	; Activa les interrupcions
  return
Carac:  ; Cada línia correspon a una xifra de 0 a 3 (vuit bytes per xifra)
  DB  00011100B, 00100010B, 00100110B, 00101010B, 00110010B, 00100010B, 00011100B, 00000000B  ; 0
  DB  00001000B, 00011000B, 00001000B, 00001000B, 00001000B, 00001000B, 00011100B, 00000000B  ; 1
  DB  00011100B, 00100010B, 00000010B, 00000100B, 00001000B, 00010000B, 00111110B, 00000000B  ; 2
  DB  00111110B, 00000100B, 00001000B, 00000100B, 00000010B, 00100010B, 00011100B, 00000000B  ; 3
Text:
  DB  0, 2, 1, 3  ; Seqüència
END main

Pot succeir que desitgem que en una mateixa seqüència hi hagi caràcters de dos o més colors. El següent programa permet indicar un color per a cada caràcter. Si hem definit menys de 33 caràcters, podem fer servir les mateixes posicions de la taula per codificar el caràcter i el color que cal mostrar a cada moment. Els tres bits de més a l'esquerra representen el color (amb el mateix criteri que abans) i els cinc de la dreta indiquen el caràcter. En el moment de llegir la llista es guardarà el valor llegit a dues variables, una per al caràcter i una per al color. La variable del caràcter es roda sempre tres posicions a l'esquerra per multiplicar per vuit, de manera que la indicació del color ja es perd. En el cas del color, el que fem és mirar els bits 7 (vermell), 6 (verd) i 5 (blau) directament. Els valors s'han posat en hexadecimal, per interpretar els colors cal mirar la taula següent.

Valor de Color Color que li correspon
Hexadecimal Binari
E 1110 Blanc
C 1100 Groc
A 1010 Magenta
8 1000 Vermell
6 0110 Cian
4 0100 Verd
2 0010 Blau
0 0000 Apagat

PROCESSOR 16F690
#include <xc.inc>
#define numcar 7
#define blanc 99  ; Punter (inexistent) que representa el blanc
config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
Port EQU 0x20  ; Bits a enviar al port B
Sortida EQU 0x21  ; Valors a enviar al MAX7221 (6 bytes, 48 bits)
ComptBits EQU 0x27  ; Variable per comptar els bits
ComptRota EQU 0x28  ; Variable per comptar rotacions
Filera EQU 0x29  ; Variable per comptar fileres
AdreH EQU 0x2A  ; Adreça per la taula
AdreL EQU 0x2B
AdreHE EQU 0x2C  ; Adreça per al caràcter de l'esquerra
AdreLE EQU 0x2D
AdreHD EQU 0x2E  ; Adreça per al caràcter de la dreta
AdreLD EQU 0x2F
ValorE EQU 0x30  ; Valor a enviar al costat esquerre
ValorD EQU 0x31  ; Valor a enviar al costat dret
Valor EQU 0x32  ; Variable temporal per rodar els bits de ValorE i ValorD
Posic EQU 0x33  ; Posició a la llista de caràcters
ColorE EQU 0x34  ; Color en el que es mostrarà el text
ColorD EQU 0x35  ; Color en el que es mostrarà el text
                ; 4 vermell  2 verd       1 blau     7 blanc
                ; 6 groc     5 magenta    3 cian     0 apagat
Actiu EQU 0x36  ; Variable que diu quin color està actiu
                ; Actiu = 0		Apagat
                ; Actiu = 1		Vermell
                ; Actiu = 2		Verd
                ; Actiu = 3		Blau
Despla EQU 0x37  ; Posició del desplaçament
Esquerra EQU 0x38  ; Part esquerra de la línia
Dreta EQU 0x39  ; Part dreta de la línia
Retard1 EQU 0x3A  ; Variables per als cicles de retard
Retard2 EQU 0x3B
Retard3 EQU 0x3C
; Zona de memòria de dades que no depèn del banc triat
W_Copia EQU 0x70  ; Guardarà el contingut de W durant la interrupció
ST_Copia EQU 0x71  ; Guardarà STATUS durant la interrupció 
PSECT code, class=CODE, delta=2, abs
main:  ; Adreça 0 h
  goto	Inici  ; Saltem al lloc on hi ha el programa principal
  nop  ; Zona de memòria de programa que no utilitzem
  nop
  nop
Interrup:  ; Adreça 4 h
  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 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 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 00000011B  ; Descarta els bits que no serveixen
  andwf Actiu,f
  btfsc ZERO
  goto NoZero  ; Si Actiu val 0 no ho canvia
  decf Actiu,f  ; Passem a activar un altre color
  btfss ZERO  ; 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 00000011B  ; Descarta els bits que no serveixen
  andwf Actiu,f
  btfsc ZERO  ; Salta si el resultat no és zero
  goto Apagat  ; Si està apagat ho desactiva tot
  movlw 1
  xorwf Actiu,w
  btfsc ZERO
  goto Vermell  ; Si val 1, activem el vermell
  movlw 2
  xorwf Actiu,w
  btfsc ZERO
  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 al 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 RP0  ; Tria el banc 1
  movlw 10000101B  ; 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
  bcf RP0
  bsf RP1  ; Tria el banc 2
  movlw 00000101B
  movwf ANSEL  ; Configura AN0 i AN2 com entrada analògica
  bcf RP0
  bcf 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
  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 10100000B  ; Activem GIE i T0IE
  movwf INTCON  ; Activa les interrupcions globals i la de Timer0
  call Apaga  ; Apaga els LED
Bucle:
  call EnviaText  ; Envia el text amb el color indicat
  movlw 1  ; Retard
  call Retard
  goto Bucle  ; Torna a repetir
;
; Envia el text amb el color indicat
;
EnviaText:
  clrf Posic  ; Comencem pel primer caràcter
  ; Cal enviar tants caràcters com la llargada del text
  ; Amb un en blanc (representat per numcar) al principi i un al final
BucEnvTxt:
  ; Posic anirà de 0 fins a numcar
  ; Si Posic és 0, enviem un blanc
  ; Agafem el número del caràcter actual
  movf Posic,f  ; Mirem si és 0
  btfsc ZERO  ; Si és 0, s'envia un blanc
  goto blancE  ; Enviem un blanc
  movlw high Text  ; Carrega la part alta de l'adreça de la taula
  movwf AdreH  ; Ho guarda per posar-ho a PCLATH
  movlw low Text  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreL  ; Ho guarda per posar-ho a PCL
  decf Posic,w  ; Quin caràcter toca: Posic-1
  addwf AdreL,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreH,f  ; Si s'ha activat, incrementem AdreH
  call Llegir  ; Llegeix el caràcter
  movwf ValorE  ; Caràcter de la banda esquerra
  movwf ColorE  ; Color de la banda esquerra
  goto NoBlancE
blancE:
  movlw blanc  ; Cal enviar un blanc
  movwf ValorE  ; Caràcter de la banda esquerra
  movwf ColorE  ; Color de la banda esquerra
  movlw high Text  ; Carrega la part alta de l'adreça de la taula
  movwf AdreH  ; Ho guarda per posar-ho a PCLATH
  movlw low Text  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreL  ; Ho guarda per posar-ho a PCL
  movf Posic,w  ; Quin caràcter toca: Posic
  addwf AdreL,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreH,f  ; Si s'ha activat, incrementem AdreH
  call Llegir  ; Llegeix el caràcter
  goto blancD
NoBlancE:
  ; També ens cal el caràcter següent
  ; Excepte si ja estem a numcar
  movlw numcar  ; Agafem el valor de comparació
  xorwf Posic,w  ; Comparem amb la posició actual
  btfss ZERO  ; Si coincideixen, salta
  goto MiraD  ; Si no son iguals, mirem què hi ha
  movlw blanc  ; Toca un blanc
  goto blancD
MiraD:
  incf AdreL,f  ; Incrementa la posició
  btfsc ZERO  ; Mirem si s'activa Z
  incf AdreH,f  ; Si s'ha activat, incrementem AdreH
  call Llegir  ; Llegeix el caràcter
blancD:
  movwf ValorD  ; Caràcter de la banda dreta
  movwf ColorD  ; Color de la banda dreta
  clrf Despla  ; Comencem sense desplaçament
  ; Per a cada parella de caràcters cal enviar vuit cops, un per desplaçament
BucEnvCar:
  movlw 1  ; Comencem per la filera 1
  movwf Filera
  ; Llegim la primera posició del caràcter de l'esquerra
  movf ValorE,w  ; En fem una còpia per poder rodar
  movwf Valor
  movlw high Carac  ; Carrega la part alta de l'adreça de la taula
  movwf AdreHE  ; Ho guarda per posar-ho a PCLATH
  movlw low Carac  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreLE  ; Ho guarda per posar-ho a PCL
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 2
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 4
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,w  ; Valor que volem enviar, multiplicat per 8; el deixem a w
  addwf AdreLE,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreHE,f  ; Si s'ha activat, incrementem AdreH
  ; Llegim la primera posició del caràcter de la dreta
  movf ValorD,w  ; En fem una còpia per poder rodar
  movwf Valor
  movlw high Carac  ; Carrega la part alta de l'adreça de la taula
  movwf AdreHD  ; Ho guarda per posar-ho a PCLATH
  movlw low Carac  ; Carrega la part baixa de l'adreça de la taula
  movwf AdreLD  ; Ho guarda per posar-ho a PCL
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 2
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,f  ; Valor que volem enviar, multiplicat per 4
  bcf CARRY  ; Ens assegurem que entra un zero
  rlf Valor,w  ; Valor que volem enviar, multiplicat per 8; el deixem a w
  addwf AdreLD,f  ; Ho suma a la posició
  btfsc CARRY  ; Mirem si s'activa C
  incf AdreHD,f  ; Si s'ha activat, incrementem AdreH
  ; Per a cada enviament calen vuit línies
BucEnvLin:
  ; Deixem preparats els punters de filera
  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
  ; Anem a preparar el que cal enviar
  movlw blanc  ; Anem a veure si és un blanc
  xorwf ValorE,w  ; Valor de l'esquerra
  btfss ZERO  ; Si són iguals, salta
  goto NoBlancEsq  ; Si són diferents
  clrw  ; Si són iguals, blanc
  goto blancEsq
NoBlancEsq:  
  ; Llegim la part del caràcter de l'esquerra
  movf AdreHE,w  ; Copiem les adreces de l'esquerra
  movwf AdreH
  movf AdreLE,w  ; Copiem les adreces de l'esquerra
  movwf AdreL
  call Llegir  ; Llegeix la filera
blancEsq:
  movwf Esquerra
  movlw blanc  ; Anem a veure si és un blanc
  xorwf ValorD,w  ; Valor de la dreta
  btfss ZERO  ; Si són iguals, salta
  goto NoBlancDre  ; Si són diferents
  clrw  ; Si són iguals, blanc
  goto blancDre
NoBlancDre:  
  ; Llegim la part del caràcter de la dreta
  movf AdreHD,w  ; Copiem les adreces de la dreta
  movwf AdreH
  movf AdreLD,w  ; Copiem les adreces de la dreta
  movwf AdreL
  call Llegir  ; Llegeix la filera
blancDre:
  movwf Dreta
  ; Ara hem d'aplicar el desplaçament
  ; Si el desplaçament és nul, ens estalviem feina
  movf Despla,f  ; Nombre de rotacions a fer
  btfsc ZERO
  goto NoRodem  ; Si és zero, no rodem
  movf Despla,w
  movwf ComptRota  ; Nombre de rotacions a fer
  ; Rodem la part esquerra
RodemE:
  bcf CARRY  ; Ens assegurem que entren zeros
  rlf Esquerra,f  ; Rodem un cop
  decfsz ComptRota,f  ; Un menys
  goto RodemE  ; Si no estem, repetim
  ; Rodem la part dreta
  movlw 8  ; Són 8 bits
  movwf ComptRota  ; Nombre de rotacions a fer
  movf Despla,w
  subwf ComptRota,f  ; ComptRota = 8 - Despla
RodemD:
  bcf CARRY  ; Ens assegurem que entren zeros
  rrf Dreta,f  ; Rodem un cop
  decfsz ComptRota,f  ; Un menys
  goto RodemD  ; Si no estem, repetim
  goto HemRodat
NoRodem:
  clrf Dreta  ; Si no rodem, Dreta no intervé
HemRodat:
  clrf Sortida  ; En previsió que el vermell pugui ser 0
  movf Esquerra,w  ; Per si el de l'esquerra té vermell
  btfsc ColorE,7  ; S'ha de posar vermell a l'esquerra?
  movwf Sortida  ; Sí, el posem; si no, és 0
  movf Dreta,w  ; Per si el de la dreta té vermell
  btfsc ColorD,7  ; S'ha de posar vermell a la dreta?
  iorwf Sortida  ; Sí, el posem
  clrf Sortida+2  ; En previsió que el verd pugui ser 0
  movf Esquerra,w  ; Per si el de l'esquerra té verd
  btfsc ColorE,6  ; S'ha de posar verd a l'esquerra?
  movwf Sortida+2  ; Sí, el posem; si no, és 0
  movf Dreta,w  ; Per si el de la dreta té verd
  btfsc ColorD,6  ; S'ha de posar verd a la dreta?
  iorwf Sortida+2  ; Sí, el posem
  clrf Sortida+4  ; En previsió que el blau pugui ser 0
  movf Esquerra,w  ; Per si el de l'esquerra té blau
  btfsc ColorE,5  ; S'ha de posar blau a l'esquerra?
  movwf Sortida+4  ; Sí, el posem; si no, és 0
  movf Dreta,w  ; Per si el de la dreta té blau
  btfsc ColorD,5  ; S'ha de posar blau a la dreta?
  iorwf Sortida+4  ; Sí, el posem
  call Envia3max  ; Ho envia al MAX7221
  ; Hem enviat una línia, preparem la següent
  incf AdreLE,f  ; Incrementa el punter	
  btfsc ZERO  ; S'ha activat Z?
  incf AdreHE,f  ; Si s'ha activat, incrementem AdreH
  incf AdreLD,f  ; Incrementa el punter	
  btfsc ZERO  ; S'ha activat Z?
  incf AdreHD,f  ; Si s'ha activat, incrementem AdreH
  incf Filera,f  ; Filera següent
  movlw 9  ; Si és 9, ja hem acabat
  xorwf Filera,w
  btfss ZERO
  goto BucEnvLin  ; Si no és zero, envia el següent
  ; Ja hem enviat una posició, seguim desplaçant
  movlw 1  ; Retard de moviment
  call Retard
  incf Despla,f  ; Desplaça una posició
  movlw 8  ; Ja hem desplaçat les 8?
  xorwf Despla,w
  btfss ZERO
  goto BucEnvCar  ; Si no és vuit, seguim
  ; Ja hem fet tot el desplaçament, caràcter següent
  incf Posic,f  ; Desplaça una posició
  movlw numcar+1  ; Ja hem enviat tots els caràcters?
  xorwf Posic,w
  btfss ZERO
  goto BucEnvTxt  ; Si no estem, seguim
  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 00000000B  ; 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 T0IE  ; Desactiva les interrupcions momentàniament
  call Envia_max
  bsf 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 ComptBits  ; 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 CARRY  ; 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 ComptBits,f  ; Decrementa ComptBits
  goto Bucle3max  ; Si ComptBits 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,2 W s
;
Retard:		
  movwf Retard3
Bucles:
  decfsz Retard1,f		
  goto Bucles		
  decfsz Retard2,f		
  goto Bucles		
  decfsz Retard3,f	
  goto Bucles
  return
;
; Llegeix la taula amb les imatges
;
Llegir:
  bcf	T0IE	; Desactiva les interrupcions momentàniament
  movf AdreH,w  ; Llegim l'adreça de la variable
  bsf RP1  ; Tria el banc 2
  movwf EEADRH  ; Adreça EEPROM
  bcf RP1  ; Tria el banc 0
  movf AdreL,w  ; Llegim l'adreça de la variable
  bsf RP1  ; Tria el banc 2
  movwf EEADR  ; Adreça EEPROM
  bsf RP0  ; Tria el banc 3
  bsf EEPGD  ; Accés a memòria de programa
  bsf RD  ; Lectura
  nop
  nop  ; espera dos cicles
  bcf RP0  ; Tria el banc 2
  movf 	EEDAT,w  ; Llegim
  bcf RP1  ; Tria el banc 0
  bsf	T0IE	; Activa les interrupcions
  return
Carac:  ; Cada línia correspon a una xifra de 0 a 3 (vuit bytes per xifra)
  DB  00011100B, 00100010B, 00100110B, 00101010B, 00110010B, 00100010B, 00011100B, 00000000B  ; 0
  DB  00001000B, 00011000B, 00001000B, 00001000B, 00001000B, 00001000B, 00011100B, 00000000B  ; 1
  DB  00011100B, 00100010B, 00000010B, 00000100B, 00001000B, 00010000B, 00111110B, 00000000B  ; 2
  DB  00111110B, 00000100B, 00001000B, 00000100B, 00000010B, 00100010B, 00011100B, 00000000B  ; 3
Text:  ; color i valor
  DB  0x80, 0x42, 0x21, 0xC3, 0xA1, 0x62, 0xE0
  ; 0 vermell, 2 verd, 1 blau, 3 groc, 1 magenta, 2 cian, 0 blanc
END main

 

 

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