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

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include <xc.h>					// Carrega el fitxer de funcions
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
#define cic_int  5				// Nombre de cicles per a la intermitència
char Port;					// Gestió del port a la funció Envia_max
char Compta;					// Comptador de bits a la funció Envia_max
char Sortida[6];				// Valors a enviar al MAX7221 (48 bits)
char Sorti[6];					// Valors a enviar al MAX7221 des de la interrupció
char Actiu; 					// Variable que diu quin color està actiu
						// Actiu = 0		Apagat
						// Actiu = 1		Vermell
						// Actiu = 2		Verd
						// Actiu = 3		Blau
char Polsad;					// Polsador que s'ha premut
char figura[8][8];
char x = 0;					// Coordenada X del cursor (0 a 7)
						// X = 0 és la columna de la dreta
char y = 0;					// Coordenada Y del cursor (0 a 7)
char mirar = 1;					// Espera que es deixi anar el polsador
char compt_int = 0;				// Comptador de cicles per a la intermitència
char cur_on = 1;				// Controla l'estat del cursor
char color = 1;					// Comencem amb vermell
						// Definició de les funcions que farem servir 
void Envia3max(char Valor[]);			// Envia un joc de valors als tres MAX7221
						// desactivant interrupcions
void Envia_max(void);				// Envia un joc de valors als tres MAX7221
void Ini3max(void);				// Inicialitza els tres MAX7221
void Apaga(void);				// Apaga tots els LED
char Polsador(void);				// Funció de lectura dels polsadors
void main (void) {
	OPTION_REG = 0b10000101;       		// 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)
	TRISC = 0;				// Tot el port C és de sortida
	TRISB = 0;				// Tot el port B és de sortida
	TRISA = 0xFF;				// Tot el port A és d'entrada
	ANSEL = 0b00000101;			// Configura AN0 i AN2 com entrada analògica
	ANSELH = 0;				// Desactiva les altres entrades analògiques
	PORTC = 0;				// Inicialitza a 0 el port C
	PORTB = 0;				// Inicialitza a 0 el port B
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	ADCON0 = 0b00001001;			// Activa el conversor A/D connectat a AN2
						// amb el resultat justificat per l'esquerra
	Ini3max();				// Inicialitza els tres MAX7221
	Actiu = 1;				// Activa el color vermell
	TMR0 = 100;				// Presselecció de 100, que són 156 iteracions
						// Correspon a una interrupció cada 7,5 ms
	INTCON = 0b10100000;			// Activem GIE i T0IE
	Apaga();				// Apaga tots els LED
	for (signed char j = 0; j < 8; j++){
		for (signed char k = 0; k < 8; k++){
			figura[j][k] = 0;	// Comencem amb tots els LED apagats
		}
	}
	while (1) {
						// 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
		Polsad = Polsador();		// Llegim els polsadors
		if (mirar == 1){
			if (Polsad == 1) {	// Si s'ha premut el polsador 1
				x = (x + 1) % 8;		// Incrementa x però la manté entre 0 i 7
				mirar = 0;
			}
			if (Polsad == 2) {	// Si s'ha premut el polsador 2
				y = (y + 1) % 8;		// Incrementa y però la manté entre 0 i 7
				mirar = 0;
			}
			if (Polsad == 3) {	// Si s'ha premut el polsador 3
						// Posem el color al LED corresponent
				figura[y][x] = color;
				mirar = 0;
			}
			if (Polsad == 4) {	// Si s'ha premut el polsador 4
				color = (color + 1) % 7;	// Incrementa però manté entre 0 i 6
				mirar = 0;
			}
			if (Polsad == 5) {	// Si s'ha premut el polsador 5
				for (signed char j = 0; j < 8; j++){
					for (signed char k = 0; k < 8; k++){
						figura[j][k] = 0;		// Apaguem tot
					}
				}
				mirar = 0;
			}
		} else {
			if (Polsad == 0) {	// Si no s'ha premut cap polsador (o dos a la vegada)
				mirar = 1;
			}
		}
						// Anem a mostrar la figura actual a la matriu de LED
		for (signed char j = 0; j < 8; j++){	// Fileres
			char mascara;
			char col;
			Sortida[0] = 0;		// Vermells
			Sortida[2] = 0;		// Verds
			Sortida[4] = 0;		// Blaus
			for (signed char k = 0; k < 8; k++){		// Caselles de la filera
				if ((y == j) && (x == k)){	// 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
					if (cur_on == 1){	// Si toca el cursor encès
						col = color;	// Color actual
						if (col == figura[y][x]){	// Si coincideixen
							col = 7;		// posem blanc
						}
					} else {
						col = figura[y][x];		// Color de la posició actual
					}
				} else {	// Si no hi estem, és una casella normal
					col = figura[j][k];	// Color de la posició actual
				}
						// Posem els bits a la columna corresponent
				mascara = col & 0b0000001;		// Serà 1 si hi ha vermell
				Sortida[0] = (char) (Sortida[0] | (mascara << k));
				mascara = (col & 0b0000010) >> 1;	// Serà 1 si hi ha verd
				Sortida[2] = (char) (Sortida[2] | (mascara << k));
				mascara = (col & 0b0000100) >> 2;	// Serà 1 si hi ha blau
				Sortida[4] = (char) (Sortida[4] | (mascara << k));
			}
			Sortida[1] = (char) (j+1);	// Filera
			Sortida[3] = (char) (j+1);
			Sortida[5] = (char) (j+1);
			Envia3max(Sortida);	// Ho envia al MAX7221
		}
		__delay_ms(1);
		compt_int++;
		if (compt_int == cic_int){	// Si toca intermitència
			compt_int = 0;
			cur_on = (cur_on + 1) % 2;		// Canvia el cursor
		}
	}
}
void __interrupt() temporit(void){
	if (INTCONbits.T0IF) {			// Comprovem que hi ha interrupció per Timer 0
		TMR0 = 100;			// Preselecció de Timer0
		INTCONbits.T0IF = 0;		// Desactiva el bit que indica interrupció pel Timer0
		if (Actiu != 0) {		// Si la matriu no està apagada
			Actiu--;		// Passem a activar un altre color
			if (Actiu == 0) {	// Si hem arribat a zero
				Actiu = 3;	// Torna a posar el 3
			}
		}
						// D'entrada els desactivem els tres
		Sorti[0] = 0x00;		// Vermell
		Sorti[2] = 0x00;		// Verd
		Sorti[4] = 0x00;		// Blau
		if (Actiu == 1) {		// Si és vermell
			Sorti[0] = 0x01;	// Vermell activat
		}
		if (Actiu == 2) {		// Si és verd
			Sorti[2] = 0x01;	// Verd activat
		}
		if (Actiu == 3) {		// Si és blau
			Sorti[4] = 0x01;	// Blau activat
		}
		Sorti[1] = 0x0C;		// Shutdown mode
		Sorti[3] = 0x0C;		// Shutdown mode
		Sorti[5] = 0x0C;		// Shutdown mode
		Envia_max();		// Ho envia al MAX7221
	}
}
void Envia3max(char Valor[]) {			// Envia un joc de valors als tres MAX7221
	INTCONbits.T0IE = 0;			// Desactiva les interrupcions momentàniament
	char Port = 0;				// Variable on guardem l'estat del port B
	char Temp;				// Variable temporal
	for (signed char j = 5; j >= 0; j--){		// Hem d'enviar 6 bytes
		for (signed char k = 1; k < 9; k++){			// De 8 bits
			Temp = Valor[j] & 0b10000000;		// Agafa el bit de més a l'esquerra
								// Temp només podrà valer 0 o 128
			if (Temp == 0) {			// Si val 0
				Port = Port & 0b11101111;	// Desactiva Data (bit 4)
			} else {				// Si val 128
				Port = Port | 0b00010000;	// Activa Data (bit 4)
			}
			Valor[j] = (char) (Valor[j] << 1);		// Rodem els bits per situar el següent
			PORTB = Port;				// Ho posa al port B
			Port = Port | 0b00100000;		// Activa Clock (bit 5) i força lectura
			PORTB = Port;				// Ho posa al port B
			Port = Port & 0b11011111;		// Desactiva Clock (bit 5)
			PORTB = Port;				// Ho posa al port B
		}
	}
	Port = Port | 0b01000000;		// Activa Latch (bit 6) per copiar a les sortides
	PORTB = Port;				// Ho posa al port B
	INTCONbits.T0IE = 1;			// Reactiva les interrupcions a l'acabar
}
void Envia_max(void) {				// Envia un joc de valors als tres MAX7221
	asm("banksel _Port");
	asm("bcf (_Port&7fh),5");		// S'assegura que Clock està desactivat
	asm("bcf (_Port&7fh),6");		// S'assegura que Latch està desactivat
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Compta");
	asm("movlw 48");			// Número de bits a enviar
	asm("movwf (_Compta&7fh)");		// Variable per comptar els bits
	asm("Bucle:");
	asm("banksel _Port");
	asm("bcf (_Port&7fh),4");		// Desactiva Data. Si toca activar-ho, ja ho farem
	asm("banksel _Sorti");
	asm("rlf (_Sorti&7fh),f");		// Fa sortir el bit de més a l'esquerra cap a C
	asm("rlf ((_Sorti+1)&7fh),f");		// i roda els altres a l'esquerra
	asm("rlf ((_Sorti+2)&7fh),f");
	asm("rlf ((_Sorti+3)&7fh),f");
	asm("rlf ((_Sorti+4)&7fh),f");
	asm("rlf ((_Sorti+5)&7fh),f");
	asm("banksel _Port");
	asm("btfsc STATUS,0");			// Mira si el bit de l'esquerra era un 1
	asm("bsf (_Port&7fh),4");		// Si era 1, activa Data
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Data
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Port");
	asm("bsf (_Port&7fh),5");		// Activa Clock, forçant a llegir el bit
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Clock
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Port");
	asm("bcf (_Port&7fh),5");		// Desactiva Clock
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Clock
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Compta");
	asm("decfsz (_Compta&7fh),f");		// Decrementa Compta
	asm("goto (Bucle&7ffh)");			// Si Compta no és zero, repeteix el bucle
	asm("banksel _Port");
	asm("bsf (_Port&7fh),6");		// Torna a activar Latch
						// Els valors es copiaran a la sortida del registre
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Latch
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
}
void Ini3max(void) {				// Inicialitza els tres MAX7221
	char Bytes[6];				// Els sis bytes que cal enviar
	Bytes[0] = 0x00;			// Desactivat
	Bytes[1] = 0x0C;			// Shutdown mode
	Bytes[2] = 0x00;
	Bytes[3] = 0x0C;
	Bytes[4] = 0x00;
	Bytes[5] = 0x0C;
	Envia3max(Bytes);			// Els envia
	Bytes[0] = 0x00;			// No decode
	Bytes[1] = 0x09;			// Decode mode
	Bytes[2] = 0x00;
	Bytes[3] = 0x09;
	Bytes[4] = 0x00;
	Bytes[5] = 0x09;
	Envia3max(Bytes);			// Els envia
	Bytes[0] = 0x07;			// Vuit fileres
	Bytes[1] = 0x0B;			// Scan limit
	Bytes[2] = 0x07;
	Bytes[3] = 0x0B;
	Bytes[4] = 0x07;
	Bytes[5] = 0x0B;
	Envia3max(Bytes);			// Els envia
}
void Apaga(void) {				// Apaga tots els LED
	char Bytes[6];				// Els sis bytes que cal enviar
	for (unsigned char j = 1; j <= 8; j++){		// Hem d'enviar 8 fileres
		Bytes[1] = j;			// Filera
		Bytes[3] = j;
		Bytes[5] = j;
		Bytes[0] = 0x00;		// Vermells
		Bytes[2] = 0x00;		// Verds
		Bytes[4] = 0x00;		// Blaus
		Envia3max(Bytes);		// Els envia
	}
}
char Polsador(void) {
	char Pols = 0;
	ADCON0bits.GO = 1;		// Posa en marxa el conversor
	while (ADCON0bits.GO == 1)	// Mentre no acabi
		;    			// ens esperem
	if (ADRESH < 220 && ADRESH > 200) {
		Pols = 1;		// Comprova polsador 1
	}
	if (ADRESH < 194 && ADRESH > 174) {
		Pols = 2;		// Comprova polsador 2
	}
	if (ADRESH < 163 && ADRESH > 143) {
		Pols = 3;		// Comprova polsador 3
	}
	if (ADRESH < 90 && ADRESH > 70) {
		Pols = 4;		// Comprova polsador 4
	}
	if (ADRESH < 55 && ADRESH > 35) {
		Pols = 5;		// Comprova polsador 5
	}
	return Pols;
}

Com ja s'ha comentat, podem implementar la funció Envia3max en assemblador. Aquest programa quedaria així:

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include <xc.h>					// Carrega el fitxer de funcions
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
#define cic_int  5				// Nombre de cicles per a la intermitència
char Port;					// Gestió del port a la funció Envia_max
char Compta;					// Comptador de bits a la funció Envia_max
char Comptar;					// Comptador de bits a la funció Envia3max
char Sortida[6];				// Valors a enviar al MAX7221 (48 bits)
char Sorti[6];					// Valors a enviar al MAX7221 des de la interrupció
char Actiu; 					// Variable que diu quin color està actiu
						// Actiu = 0		Apagat
						// Actiu = 1		Vermell
						// Actiu = 2		Verd
						// Actiu = 3		Blau
char Polsad;					// Polsador que s'ha premut
char figura[8][8];
char x = 0;					// Coordenada X del cursor (0 a 7)
						// X = 0 és la columna de la dreta
char y = 0;					// Coordenada Y del cursor (0 a 7)
char mirar = 1;					// Espera que es deixi anar el polsador
char compt_int = 0;				// Comptador de cicles per a la intermitència
char cur_on = 1;				// Controla l'estat del cursor
char color = 1;					// Comencem amb vermell
						// Definició de les funcions que farem servir 
void Envia3max(void);				// Envia un joc de valors als tres MAX7221
						// desactivant interrupcions
void Envia_max(void);				// Envia un joc de valors als tres MAX7221
void Ini3max(void);				// Inicialitza els tres MAX7221
void Apaga(void);				// Apaga tots els LED
char Polsador(void);				// Funció de lectura dels polsadors
void main (void) {
	OPTION_REG = 0b10000101;       		// 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)
	TRISC = 0;				// Tot el port C és de sortida
	TRISB = 0;				// Tot el port B és de sortida
	TRISA = 0xFF;				// Tot el port A és d'entrada
	ANSEL = 0b00000101;			// Configura AN0 i AN2 com entrada analògica
	ANSELH = 0;				// Desactiva les altres entrades analògiques
	PORTC = 0;				// Inicialitza a 0 el port C
	PORTB = 0;				// Inicialitza a 0 el port B
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	ADCON0 = 0b00001001;			// Activa el conversor A/D connectat a AN2
						// amb el resultat justificat per l'esquerra
	Ini3max();				// Inicialitza els tres MAX7221
	Actiu = 1;				// Activa el color vermell
	TMR0 = 100;				// Presselecció de 100, que són 156 iteracions
						// Correspon a una interrupció cada 7,5 ms
	INTCON = 0b10100000;			// Activem GIE i T0IE
	Apaga();				// Apaga tots els LED
	for (signed char j = 0; j < 8; j++){
		for (signed char k = 0; k < 8; k++){
			figura[j][k] = 0;	// Comencem amb tots els LED apagats
		}
	}
	while (1) {
						// 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
		Polsad = Polsador();		// Llegim els polsadors
		if (mirar == 1){
			if (Polsad == 1) {	// Si s'ha premut el polsador 1
				x = (x + 1) % 8;		// Incrementa x però la manté entre 0 i 7
				mirar = 0;
			}
			if (Polsad == 2) {	// Si s'ha premut el polsador 2
				y = (y + 1) % 8;		// Incrementa y però la manté entre 0 i 7
				mirar = 0;
			}
			if (Polsad == 3) {	// Si s'ha premut el polsador 3
						// Posem el color al LED corresponent
				figura[y][x] = color;
				mirar = 0;
			}
			if (Polsad == 4) {	// Si s'ha premut el polsador 4
				color = (color + 1) % 7;	// Incrementa però manté entre 0 i 6
				mirar = 0;
			}
			if (Polsad == 5) {	// Si s'ha premut el polsador 5
				for (signed char j = 0; j < 8; j++){
					for (signed char k = 0; k < 8; k++){
						figura[j][k] = 0;		// Apaguem tot
					}
				}
				mirar = 0;
			}
		} else {
			if (Polsad == 0) {	// Si no s'ha premut cap polsador (o dos a la vegada)
				mirar = 1;
			}
		}
						// Anem a mostrar la figura actual a la matriu de LED
		for (signed char j = 0; j < 8; j++){	// Fileres
			char mascara;
			char col;
			Sortida[0] = 0;		// Vermells
			Sortida[2] = 0;		// Verds
			Sortida[4] = 0;		// Blaus
			for (signed char k = 0; k < 8; k++){		// Caselles de la filera
				if ((y == j) && (x == k)){	// 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
					if (cur_on == 1){	// Si toca el cursor encès
						col = color;	// Color actual
						if (col == figura[y][x]){	// Si coincideixen
							col = 7;		// posem blanc
						}
					} else {
						col = figura[y][x];		// Color de la posició actual
					}
				} else {	// Si no hi estem, és una casella normal
					col = figura[j][k];	// Color de la posició actual
				}
						// Posem els bits a la columna corresponent
				mascara = col & 0b0000001;		// Serà 1 si hi ha vermell
				Sortida[0] = (char) (Sortida[0] | (mascara << k));
				mascara = (col & 0b0000010) >> 1;	// Serà 1 si hi ha verd
				Sortida[2] = (char) (Sortida[2] | (mascara << k));
				mascara = (col & 0b0000100) >> 2;	// Serà 1 si hi ha blau
				Sortida[4] = (char) (Sortida[4] | (mascara << k));
			}
			Sortida[1] = (char) (j+1);	// Filera
			Sortida[3] = (char) (j+1);
			Sortida[5] = (char) (j+1);
			Envia3max();			// Ho envia al MAX7221
		}
		__delay_ms(1);
		compt_int++;
		if (compt_int == cic_int){	// Si toca intermitència
			compt_int = 0;
			cur_on = (cur_on + 1) % 2;		// Canvia el cursor
		}
	}
}
void __interrupt() temporit(void){
	if (INTCONbits.T0IF) {			// Comprovem que hi ha interrupció per Timer 0
		TMR0 = 100;			// Preselecció de Timer0
		INTCONbits.T0IF = 0;		// Desactiva el bit que indica interrupció pel Timer0
		if (Actiu != 0) {		// Si la matriu no està apagada
			Actiu--;		// Passem a activar un altre color
			if (Actiu == 0) {	// Si hem arribat a zero
				Actiu = 3;	// Torna a posar el 3
			}
		}
						// D'entrada els desactivem els tres
		Sorti[0] = 0x00;		// Vermell
		Sorti[2] = 0x00;		// Verd
		Sorti[4] = 0x00;		// Blau
		if (Actiu == 1) {		// Si és vermell
			Sorti[0] = 0x01;	// Vermell activat
		}
		if (Actiu == 2) {		// Si és verd
			Sorti[2] = 0x01;	// Verd activat
		}
		if (Actiu == 3) {		// Si és blau
			Sorti[4] = 0x01;	// Blau activat
		}
		Sorti[1] = 0x0C;		// Shutdown mode
		Sorti[3] = 0x0C;		// Shutdown mode
		Sorti[5] = 0x0C;		// Shutdown mode
		Envia_max();			// Ho envia al MAX7221
	}
}
void Envia3max(void) {				// Envia un joc de valors als tres MAX7221
	asm("bcf INTCON,5");			// Desactiva les interrupcions momentàniament
	asm("banksel _Port");
	asm("bcf (_Port&7fh),5");		// S'assegura que Clock està desactivat
	asm("bcf (_Port&7fh),6");		// S'assegura que Latch està desactivat
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Comptar");
	asm("movlw 48");			// Número de bits a enviar
	asm("movwf (_Comptar&7fh)");		// Variable per comptar els bits
	asm("Bucles:");
	asm("banksel _Port");
	asm("bcf (_Port&7fh),4");		// Desactiva Data. Si toca activar-ho, ja ho farem
	asm("banksel _Sorti");
	asm("rlf (_Sortida&7fh),f");		// Fa sortir el bit de més a l'esquerra cap a C
	asm("rlf ((_Sortida+1)&7fh),f");	// i roda els altres a l'esquerra
	asm("rlf ((_Sortida+2)&7fh),f");
	asm("rlf ((_Sortida+3)&7fh),f");
	asm("rlf ((_Sortida+4)&7fh),f");
	asm("rlf ((_Sortida+5)&7fh),f");
	asm("banksel _Port");
	asm("btfsc STATUS,0");			// Mira si el bit de l'esquerra era un 1
	asm("bsf (_Port&7fh),4");		// Si era 1, activa Data
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Data
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Port");
	asm("bsf (_Port&7fh),5");		// Activa Clock, forçant a llegir el bit
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Clock
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Port");
	asm("bcf (_Port&7fh),5");		// Desactiva Clock
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Clock
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Comptar");
	asm("decfsz (_Comptar&7fh),f");		// Decrementa Compta
	asm("goto (Bucles&7ffh)");		// Si Compta no és zero, repeteix el bucle
	asm("banksel _Port");
	asm("bsf (_Port&7fh),6");		// Torna a activar Latch
						// Els valors es copiaran a la sortida del registre
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Latch
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("bsf INTCON,5");			// Reactiva les interrupcions a l'acabar
}
void Envia_max(void) {				// Envia un joc de valors als tres MAX7221
	asm("banksel _Port");
	asm("bcf (_Port&7fh),5");		// S'assegura que Clock està desactivat
	asm("bcf (_Port&7fh),6");		// S'assegura que Latch està desactivat
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Compta");
	asm("movlw 48");			// Número de bits a enviar
	asm("movwf (_Compta&7fh)");		// Variable per comptar els bits
	asm("Bucle:");
	asm("banksel _Port");
	asm("bcf (_Port&7fh),4");		// Desactiva Data. Si toca activar-ho, ja ho farem
	asm("banksel _Sorti");
	asm("rlf (_Sorti&7fh),f");		// Fa sortir el bit de més a l'esquerra cap a C
	asm("rlf ((_Sorti+1)&7fh),f");		// i roda els altres a l'esquerra
	asm("rlf ((_Sorti+2)&7fh),f");
	asm("rlf ((_Sorti+3)&7fh),f");
	asm("rlf ((_Sorti+4)&7fh),f");
	asm("rlf ((_Sorti+5)&7fh),f");
	asm("banksel _Port");
	asm("btfsc STATUS,0");			// Mira si el bit de l'esquerra era un 1
	asm("bsf (_Port&7fh),4");		// Si era 1, activa Data
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Data
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Port");
	asm("bsf (_Port&7fh),5");		// Activa Clock, forçant a llegir el bit
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Clock
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Port");
	asm("bcf (_Port&7fh),5");		// Desactiva Clock
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Clock
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
	asm("banksel _Compta");
	asm("decfsz (_Compta&7fh),f");		// Decrementa Compta
	asm("goto (Bucle&7ffh)");			// Si Compta no és zero, repeteix el bucle
	asm("banksel _Port");
	asm("bsf (_Port&7fh),6");		// Torna a activar Latch
						// Els valors es copiaran a la sortida del registre
	asm("movf (_Port&7fh),w");		// Agafa el valor de Port. El valor que ha canviat és Latch
	asm("banksel PORTB");
	asm("movwf PORTB");			// I el posa al port B
}
void Ini3max(void) {				// Inicialitza els tres MAX7221
	Sortida[0] = 0x00;			// Desactivat
	Sortida[1] = 0x0C;			// Shutdown mode
	Sortida[2] = 0x00;
	Sortida[3] = 0x0C;
	Sortida[4] = 0x00;
	Sortida[5] = 0x0C;
	Envia3max();				// Els envia
	Sortida[0] = 0x00;			// No decode
	Sortida[1] = 0x09;			// Decode mode
	Sortida[2] = 0x00;
	Sortida[3] = 0x09;
	Sortida[4] = 0x00;
	Sortida[5] = 0x09;
	Envia3max();				// Els envia
	Sortida[0] = 0x07;			// Vuit fileres
	Sortida[1] = 0x0B;			// Scan limit
	Sortida[2] = 0x07;
	Sortida[3] = 0x0B;
	Sortida[4] = 0x07;
	Sortida[5] = 0x0B;
	Envia3max();				// Els envia
}
void Apaga(void) {				// Apaga tots els LED
	for (unsigned char j = 1; j <= 8; j++){		// Hem d'enviar 8 fileres
		Sortida[1] = j;			// Filera
		Sortida[3] = j;
		Sortida[5] = j;
		Sortida[0] = 0x00;		// Vermells
		Sortida[2] = 0x00;		// Verds
		Sortida[4] = 0x00;		// Blaus
		Envia3max();			// Els envia
	}
}
char Polsador(void) {
	char Pols = 0;
	ADCON0bits.GO = 1;		// Posa en marxa el conversor
	while (ADCON0bits.GO == 1)	// Mentre no acabi
		;    			// ens esperem
	if (ADRESH < 220 && ADRESH > 200) {
		Pols = 1;		// Comprova polsador 1
	}
	if (ADRESH < 194 && ADRESH > 174) {
		Pols = 2;		// Comprova polsador 2
	}
	if (ADRESH < 163 && ADRESH > 143) {
		Pols = 3;		// Comprova polsador 3
	}
	if (ADRESH < 90 && ADRESH > 70) {
		Pols = 4;		// Comprova polsador 4
	}
	if (ADRESH < 55 && ADRESH > 35) {
		Pols = 5;		// Comprova polsador 5
	}
	return Pols;
}

 

 

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