Programació en pic-as del PIC 16F690

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

Exemple D6 - Dibuixem sobre la matriu de LED (sis colors)

En aquest exemple farem servir els polsadors per anar movent un cursor per la matriu de LED i encendre del color triat els punts seleccionats. D'aquesta manera, aconseguirem fer un dibuix. El cursor serà del color que està triat en aquell moment i intermitent. 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 Canvia el color
5 Esborrar dibuix

L'ordre dels colors serà el següent:

Valor Color
Decimal Binari
0 000 Apagat
1 001 Vermell
2 010 Verd
3 011 Groc
4 100 Blau
5 101 Magenta
6 110 Cian

Fixem-nos que hem ordenat els colors de manera que cada bit ens representa un dels colors bàsics, això ens facilitarà la programació. Per poder veure el cursor, quan el color triat coincideixi amb el de la casella farem la intermitència amb blanc. Ens hem reservat el color blanc per aquesta finalitat. Podríem haver fet servir la pantalla LCD per indicar el color actual i llavors el cursor podria alternar dos colors que sempre fossin els mateixos i així podríem disposar del blanc per al dibuix.

Encara que en aquest programa no gastem molta memòria de dades (92 bytes, que cabrien al banc 0) hem optat per guardar la matriu 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. En aquest cas, tots els accessos a la matriu 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.

PROCESSOR 16F690
#include <xc.inc>
config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#define cic_int 35  ; Nombre de cicles per a la intermitència
Port EQU 0x20  ; Bits a enviar al port B
Sortida EQU 0x21  ; Valors a enviar al MAX7221 (6 bytes, 48 bits)
Compta EQU 0x27  ; Variable per comptar els bits a Envia_max
Compt EQU 0x28  ; Variable per comptar
compY EQU 0x29  ; Comptador per enviar fileres
compX EQU 0x2A  ; Comptador per enviar columnes
Filera EQU 0x2B  ; Variable per comptar fileres
Actiu EQU 0x2C  ; Variable que diu quin color està actiu
                ; Actiu = 0  Apagat
                ; Actiu = 1  Vermell
                ; Actiu = 2  Verd
                ; Actiu = 3  Blau
Polsador EQU 0x2D  ; Variable que conté un bit per a cada polsador per saber si està premut	
x EQU 0x2E  ; Coordenada X del cursor (0 a 7)
            ; X = 0 és la columna de la dreta
y EQU 0x2F  ; Coordenada Y del cursor (0 a 7)
yact EQU 0x30  ; Filera que estem enviant
xact EQU 0x31  ; Casella que estem enviant
mirar EQU 0x32  ; Espera que es deixi anar el polsador
temp EQU 0x33  ; Variable temporal
compt_int EQU 0x34  ; Comptador de cicles per a la intermitència
cur_on EQU 0x35  ; Controla l'estat del cursor
color EQU 0x36  ; Color seleccionat
mascara EQU 0x37  ; Màscara per preparar els colors
Retard1 EQU 0x38  ; Variables per als cicles de retard
Retard2 EQU 0x39
; 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ó 
; Zona de memòria de dades del banc 1
figura EQU 0xA0  ; Aquí guardarem el dibuix (64 bytes, 8 x 8 posicions)
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 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 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
  movlw 00010000B
  movwf ADCON1  ; Posa el conversor a 1/8 de la freqüència
  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
  movlw 00001001B
  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 10100000B  ; 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
  movwf color  ; Posa color a 1, o sigui vermell
  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 ZERO  ; Si és zero no s'han de mirar
  goto NoMirar		; Anem a veure si ja s'ha deixat anar
  movf Polsador,w
  xorlw 00000001B  ; Mirem si s'ha premut el polsador 1
  btfss ZERO  ; Si és l'1, salta
  goto NoEsPol1  ; No és l'1
  ; S'ha premut el polsador 1
  incf x,f  ; Incrementem x del cursor
  movlw 00000111B  ; Valor 7
  andwf x,f  ; Limitem x entre 0 i 7
  goto Zmirar  ; Ja estem del polsador 1
NoEsPol1:
  movf Polsador,w
  xorlw 00000010B  ; Mirem si s'ha premut el polsador 2
  btfss ZERO  ; Si és el 2, salta
  goto NoEsPol2  ; No és el 2
  ; S'ha premut el polsador 2
  incf y,f ; Incrementem y del cursor
  movlw 00000111B  ; Valor 7
  andwf y,f  ; Limitem y entre 0 i 7
  goto Zmirar  ; Ja estem del polsador 2
NoEsPol2:
  movf Polsador,w
  xorlw 00000100B  ; Mirem si s'ha premut el polsador 3
  btfss ZERO  ; Si és el 3, salta
  goto NoEsPol3  ; No és el 3
  ; S'ha premut el polsador 3
  movf y,w ; Agafem la filera
  movwf temp  ; Ho guardem a una variable temporal
  bcf CARRY  ; Volem entrar zeros
  rlf temp,f  ; Rodem a l'esquerra i entrem el zero, equival a multiplicar per 2
  rlf temp,f  ; Rodem a l'esquerra
  rlf temp,f  ; Rodem a l'esquerra, en total hem multiplicat per 8
  movf x,w  ; Agafem la columna
  addwf temp,f  ; Ho sumem al contingut de la variable temporal
  movlw figura  ; Agafem l'adreça de la primera posició de la matriu
  addwf temp,w  ; Ho sumem al contingut de la variable temporal, el resultat està a W
  movwf FSR  ; Ja tenim el punter d'adreçament indirecte
  movf color,w  ; Agafem el color actual
  movwf INDF  ; I el posem a la posició corresponent de la matriu
  goto Zmirar  ; Ja estem del polsador 3
NoEsPol3:
  movf Polsador,w
  xorlw 00001000B  ; Mirem si s'ha premut el polsador 4
  btfss ZERO  ; Si és el 4, salta
  goto NoEsPol4  ; No és el 4
  ; S'ha premut el polsador 4
  incf color,f  ; Passem al color següent
  movlw 00000111B  ; Valor 7
  xorwf color,w  ; Mirem si és 7
  btfss ZERO  ; Si és 7 hem de canviar-lo
  goto no7  ; Si no és 7 no cal fer res
  clrf color  ; El posem a zero
no7:
  goto Zmirar  ; Ja estem del polsador 4
NoEsPol4:
  movf Polsador,w
  xorlw 00010000B  ; Mirem si s'ha premut el polsador 5
  btfss ZERO  ; Si és el 5, salta
  goto NoEsPol5  ; 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
NoEsPol5:
  goto Matriu  ; Envia la figura actual a la matriu
NoMirar:
  movf Polsador,w  ; Agafem la lectura dels polsadors
  btfss ZERO  ; 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 yact  ; Primer enviem la filera 0
  movlw figura  ; Agafem l'adreça de la primera posició del vector
  movwf FSR  ; La posem com a punter d'adreçament indirecte
  movlw 8  ; Número de fileres que cal enviar
  movwf compY  ; Fileres
bucleY:  ; Bucle que recorre les fileres
  clrf xact  ; Primer enviem la casella 0
  movlw 8  ; Número de caselles de la filera
  movwf compX  ; Columnes
  clrf Sortida  ; Vermell, en principi, a zero
  clrf Sortida+2  ; Verd, en principi, a zero
  clrf Sortida+4  ; Blau, en principi, a zero
bucleX:  ; Bucle que recorre les caselles de cada filera
         ; Anem a veure si estem a la casella del cursor
         ; El cursor es mostra en el color actual però si coincideix
         ; amb el color de la casella el mostrem blanc
  movf yact,w  ; Mirem la filera que estem enviant
  xorwf y,w  ; I comparem amb la del cursor
  btfss ZERO  ; Si és zero, són iguals
  goto noCur  ; No és la filera del cursor
  movf xact,w  ; Mirem la casella que estem enviant
  xorwf x,w  ; I comparem amb la del cursor
  btfss ZERO  ; Si és zero, són iguals
  goto noCur  ; No és la casella del cursor
              ; Mirem si s'ha de mostrar el cursor
  movf cur_on,w  ; Mirem el valor de cur_on
  btfsc ZERO  ; Si no és zero, mostrem el cursor
  goto noCur  ; Si és zero no hem de mostrar el cursor
  movf color,w  ; Agafem el color actual
  movwf temp  ; El guardem a la variable temporal
  xorwf INDF,w  ; Comparem amb el color de la casella actual
  btfss ZERO  ; Si és zero, són iguals
  goto fiCur  ; Si no és 0 no cal fer res
  movlw 7  ; Si són iguals posa blanc
  movwf temp  ; El guardem a la variable temporal
  goto	fiCur  ; Ja està el cursor a punt
noCur:  ; Si no toca mostrar el cursor o estem en una casella normal
  movf INDF,w  ; Agafem el color de la casella actual
  movwf temp  ; El guardem a la variable temporal
fiCur:  ; Ja estem del cursor
        ; Ara anem a preparar els colors de la casella actual
        ; i els anirem afegint a la filera
        ; Primer el vermell
  movf temp,w  ; Agafem la casella actual
  andlw 00000001B  ; Serà 1 si hi ha vermell
  movwf mascara ; Ho posa com a màscara per al vermell
                ; Anem a posar aquest 1 a la columna que li toca
  movf xact,w  ; Agafem la x actual
  btfsc ZERO  ; Mirem si és zero
  goto xnulR  ; Si és zero no cal fer res, ja està a lloc
  movwf Compt  ; Hem de rodar els bits x posicions
giraR:
  bcf CARRY  ; Volem entrar zeros
  rlf mascara,f  ; Rodem a l'esquerra i entrem el zero
  decfsz Compt,f  ; Decrementa temp
  goto giraR  ; Si Comp no és zero, repeteix el bucle
xnulR:  ; Ja tenim l'1 posat a la columna per a cada color
  movf mascara,w  ; Agafem la màscara del vermell
  iorwf Sortida,f  ; L'aplica al color vermell
                   ; Ara al verd
  movf temp,w  ; Agafem la casella actual
  andlw 00000010B  ; Serà 10 si hi ha verd
  movwf mascara  ; Ho posa com a màscara per al verd
  bcf CARRY  ; Volem entrar zeros
  rrf mascara,f  ; Posem l'1 a la dreta
                 ; Anem a posar aquest 1 a la columna que li toca
  movf xact,w  ; Agafem la x actual
  btfsc ZERO  ; Mirem si és zero
  goto xnulG  ; Si és zero no cal fer res, ja està a lloc
  movwf Compt  ; Hem de rodar els bits x posicions
giraG:
  bcf CARRY  ; Volem entrar zeros
  rlf mascara,f  ; Rodem a l'esquerra i entrem el zero
  decfsz Compt,f  ; Decrementa temp
  goto giraG  ; Si Comp no és zero, repeteix el bucle
xnulG:  ; Ja tenim l'1 posat a la columna per a cada color
  movf mascara,w  ; Agafem la màscara del verd
  iorwf Sortida+2,f  ; L'aplica al color verd
                     ; Ara al blau
  movf temp,w  ; Agafem la casella actual
  andlw 00000100B  ; Serà 100 si hi ha blau
  movwf mascara  ; Ho posa com a màscara per al blau
  bcf CARRY  ; Volem entrar zeros
  rrf mascara,f  ; Movem l'1 a la dreta
  bcf CARRY  ; Volem entrar zeros
  rrf mascara,f  ; Posem l'1 a la dreta
                 ; Anem a posar aquest 1 a la columna que li toca
  movf xact,w  ; Agafem la x actual
  btfsc ZERO  ; Mirem si és zero
  goto xnulB  ; Si és zero no cal fer res, ja està a lloc
  movwf Compt  ; Hem de rodar els bits x posicions
giraB:
  bcf CARRY  ; Volem entrar zeros
  rlf mascara,f  ; Rodem a l'esquerra i entrem el zero
  decfsz Compt,f  ; Decrementa temp
  goto giraB  ; Si Comp no és zero, repeteix el bucle
xnulB:  ; Ja tenim l'1 posat a la columna per a cada color
  movf mascara,w  ; Agafem la màscara del blau
  iorwf Sortida+4,f  ; L'aplica al color blau
                     ; Hem preparat la casella actual, passem a la següent
  incf FSR,f  ; Passem a la casella següent
  incf xact,f  ; Passem a la casella següent
  decfsz compX,f  ; Decrementa compX
  goto bucleX  ; Si Compt no és zero, encara no hem acabat la filera
               ; Hem acabat la filera, anem a enviar-la
  incf yact,w  ; A la matriu se li envien les fileres numerades de l'1 al 8
  movwf Sortida+1  ; Filera per al vermell
  movwf Sortida+3  ; Filera per al verd
  movwf Sortida+5  ; Filera per al blau
  call Envia3max  ; Ho envia al MAX7221
                  ; Hem enviat la filera, passem a la següent
  incf yact,f  ; Passem a la filera següent
  decfsz compY,f  ; Decrementa compY
  goto bucleY  ; Si Compt no és zero, encara no hem acabat d'enviar la matriu
  ; Després d'enviar la matriu fem un petit retard
  movlw 1  ; Retard de 0,771 ms
  call Retms
  ; Un cop enviada la matriu, gestionem el cursor
  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
  movlw 00000001B  ; Valor 1
  xorwf cur_on,f  ; Inverteix cur_on
  goto Bucle  ; Torna a repetir
;
; Posa a zero els bytes de la matriu figura
;
PosaZero:
  movlw 64  ; 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 GO_DONE  ; Inicia la conversió
  btfsc GO_DONE  ; 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 CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP1  ; ADRESH >= W
  movlw 200  ; Límit inferior de P1
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP1  ; ADRESH < W
  movlw 00000001B  ; Polsador P1
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP1:  ; Comparació P2
  movlw 194  ; Límit superior de P2
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP2  ; ADRESH >= W
  movlw 174  ; Límit inferior de P2
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP2  ; ADRESH < W
  movlw 00000010B  ; Polsador P2
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP2:  ; Comparació P3
  movlw 163  ; Límit superior de P3
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP3  ; ADRESH >= W
  movlw 143  ; Límit inferior de P3
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP3  ; ADRESH < W
  movlw 00000100B  ; Polsador P3
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP3:  ; Comparació P4
  movlw 90  ; Límit superior de P4
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP4  ; ADRESH >= W
  movlw 70  ; Límit inferior de P4
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP4  ; ADRESH < W
  movlw 00001000B  ; Polsador P4
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP4:  ; Comparació P5
  movlw 55  ; Límit superior de P5
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP5  ; ADRESH >= W
  movlw 35  ; Límit inferior de P5
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP5  ; ADRESH < W
  movlw 00010000B  ; Polsador P5
  movwf Polsador  ; Ho copia a Polsador
NoEsP5:
  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 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 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 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 main

 

 

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