Programació en mpasm del PIC 16F690

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

Exemple ML - Mostrem uns dibuixos a la matriu de LED

En l'exemple següent mostrarem un parell de dibuixos a la matriu de LED. El programa és llarg però senzill. En la part d'inicialització configura el microcontrolador. En el bucle simplement va alternant els dos patrons de les figures següents deixant un temps entre canvi i canvi per tal que els patrons es puguin veure suficientment bé.

Sentit prohibit           Fletxa verda amunt

#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
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
Retard1			; Variables per als cicles de retard
Retard2
Retard3
	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
	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
	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
	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
Bucle
				; Matriu 1
	movlw	0x01		; Filera 1
	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'00111100'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00000000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x02		; Filera 2
	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'01111110'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00000000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x03		; Filera 3
	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'11111111'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00000000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x04		; Filera 4
	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'11111111'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'01111110'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'01111110'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x05		; Filera 5
	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'11111111'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'01111110'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'01111110'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x06		; Filera 6
	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'11111111'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00000000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x07		; Filera 7
	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'01111110'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00000000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x08		; Filera 8
	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'00111100'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00000000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
				; Fi de la matriu 1
	movlw	.7		; Retard d'1,4 segons que realment són 1,6
	call	Retard
				; Matriu 2
	movlw	0x01		; Filera 1
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00011000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x02		; Filera 2
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00111100'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x03		; Filera 3
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'01111110'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x04		; Filera 4
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'11111111'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x05		; Filera 5
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00011000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x06		; Filera 6
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00011000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x07		; Filera 7
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00011000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
	movlw	0x08		; Filera 8
	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'	; Vermells				
	movwf	Sortida		; Ho prepara per enviar-ho
	movlw	b'00011000'	; Verds
	movwf	Sortida+2	; Ho prepara per enviar-ho
	movlw	b'00000000'	; Blaus
	movwf	Sortida+4	; Ho prepara per enviar-ho
	call	Envia3max	; Ho envia al MAX7221
				; Fi de la matriu 2
	movlw	.7		; Retard d'1,4 segons que realment són 1,6
	call	Retard
	goto	Bucle		; Torna a repetir
				;
				; 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,2 W s
				;
Retard				
	movwf	Retard3
Bucles
	decfsz	Retard1,f		
	goto	Bucles		
	decfsz	Retard2,f		
	goto	Bucles		
	decfsz	Retard3,f	
	goto	Bucles
	return
	end

El següent programa fa el mateix que el primer que hem vist però guardant els dibuixos amb la directiva dt i recuperant-los modificant el comptador de programa.

#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
Filera			; Variable per comptar fileres
Compt			; Comptador per al bucle d'enviar
AdreH			; Adreça per al salt
AdreL			; Adreça per al salt
Actiu			; Variable que diu quin color està actiu
			; Actiu = 0		Apagat
			; Actiu = 1		Vermell
			; Actiu = 2		Verd
			; Actiu = 3		Blau
Retard1			; Variables per als cicles de retard
Retard2
Retard3
W_Copia			; Guardarà el contingut de W durant la interrupció
ST_Copia		; Guardarà STATUS durant la interrupció 
	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 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	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
	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
	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
Bucle
	movlw	high Matriu1	; Carrega la part alta de l'adreça de la taula
	movwf	AdreH		; Ho guarda per posar-ho a PCLATH
	movlw	low Matriu1	; Carrega la part baixa de l'adreça de la taula
	movwf	AdreL		; Ho guarda per posar-ho a PCL
	call	EnviaMat
	movlw	.7		; Retard d'1,4 segons que realment són 1,6
	call	Retard
	movlw	high Matriu2	; Carrega la part alta de l'adreça de la taula
	movwf	AdreH		; Ho guarda per posar-ho a PCLATH
	movlw	low Matriu2	; Carrega la part baixa de l'adreça de la taula
	movwf	AdreL		; Ho guarda per posar-ho a PCL
	call	EnviaMat
	movlw	.7		; Retard d'1,4 segons que realment són 1,6
	call	Retard
	goto	Bucle		; Torna a repetir
				;
				; Es prepara per llegir la taula amb les imatges
				;
Llegir
	bcf	INTCON,T0IE	; Desactiva les interrupcions momentàniament
	call	Llegeix
	bsf	INTCON,T0IE	; Reactiva les interrupcions a l'acabar
	return
				;
				; Llegeix la taula amb les imatges
				;
Llegeix
	movf	AdreH,w		; Agafa l'adreça de destí
	movwf	PCLATH		; Modifica el valor de PCLATH
	movf	AdreL,w		; Agafa l'adreça de destí
	movwf	PCL		; Modifica el valor de PCL (i, per tant, també el de PCH)
Matriu1				; Cada línia són vermell, verd i blau per a dues fileres
	dt	b'00111100', b'00000000', b'00000000', b'01111110', b'00000000', b'00000000'
	dt	b'11111111', b'00000000', b'00000000', b'11111111', b'01111110', b'01111110'
	dt	b'11111111', b'01111110', b'01111110', b'11111111', b'00000000', b'00000000'
	dt	b'01111110', b'00000000', b'00000000', b'00111100', b'00000000', b'00000000'
Matriu2
	dt	b'00000000', b'00011000', b'00000000', b'00000000', b'00111100', b'00000000'
	dt	b'00000000', b'01111110', b'00000000', b'00000000', b'11111111', b'00000000'
	dt	b'00000000', b'00011000', b'00000000', b'00000000', b'00011000', b'00000000'
	dt	b'00000000', b'00011000', b'00000000', b'00000000', b'00011000', b'00000000'
				;
				; Envia les dades d'una de les matrius als MAX7221
				;
EnviaMat
	movlw	.1		; Primera filera
	movwf	Filera
	movlw	.8		; Número de fileres a enviar
	movwf	Compt		; Ho guarda al comptador
BucMat
	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
	call	Llegir		; Llegeix la filera
	movwf	Sortida		; Vermells
	incf	AdreL,f		; Incrementa el punter	
	btfsc	STATUS,Z	; S'ha activat Z?
	incf	AdreH,f		; Si s'ha activat, incrementem AdreH
	call	Llegir		; Llegeix la filera
	movwf	Sortida+2	; Verds
	incf	AdreL,f		; Incrementa el punter	
	btfsc	STATUS,Z	; S'ha activat Z?
	incf	AdreH,f		; Si s'ha activat, incrementem AdreH
	call	Llegir		; Llegeix la filera
	movwf	Sortida+4	; Blaus
	incf	AdreL,f		; Incrementa el punter	
	btfsc	STATUS,Z	; S'ha activat Z?
	incf	AdreH,f		; Si s'ha activat, incrementem AdreH
	call	Envia3max	; Ho envia al MAX7221
	incf	Filera,f	; Filera següent
	decfsz	Compt		; Decrementa el comptador
	goto	BucMat		; Si no és zero, envia el següent
	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,2 W s
				;
Retard				
	movwf	Retard3
Bucles
	decfsz	Retard1,f		
	goto	Bucles		
	decfsz	Retard2,f		
	goto	Bucles		
	decfsz	Retard3,f	
	goto	Bucles
	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.