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

#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
compY			; Comptador per enviar fileres
compX			; Comptador per enviar columnes
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)
yact			; Filera que estem enviant
xact			; Casella que estem enviant
mirar			; Espera que es deixi anar el polsador
temp			; Variable temporal
compt_int		; Comptador de cicles per a la intermitència
cur_on			; Controla l'estat del cursor
color			; Color seleccionat
mascara			; Màscara per preparar els colors
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:.64		; Aquí guardarem el dibuix (8 x 8 posicions)
	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
	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	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
	movf	y,w		; Agafem la filera
	movwf	temp		; Ho guardem a una variable temporal
	bcf	STATUS,C	; 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
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
	incf	color,f		; Passem al color següent
	movlw	b'00000111'	; Valor 7
	xorwf	color,w		; Mirem si és 7
	btfss	STATUS,Z	; 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
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	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	STATUS,Z	; 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	STATUS,Z	; 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	STATUS,Z	; 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	STATUS,Z	; 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	b'00000001'	; 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	STATUS,Z	; 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	STATUS,C	; 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	b'00000010'	; Serà 10 si hi ha verd
	movwf	mascara		; Ho posa com a màscara per al verd
	bcf	STATUS,C	; 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	STATUS,Z	; 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	STATUS,C	; 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	b'00000100'	; Serà 100 si hi ha blau
	movwf	mascara		; Ho posa com a màscara per al blau
	bcf	STATUS,C	; Volem entrar zeros
	rrf	mascara,f	; Movem l'1 a la dreta
	bcf	STATUS,C	; 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	STATUS,Z	; 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	STATUS,C	; 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	b'00000001'	; 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	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

 

 

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