Es tracta de recórrer un laberint. Durant el trajecte, segons la dificultat, es poden anar recollint una o més monedes, acció que repercutirà en la puntuació final. La següent taula indica el significat dels diferents colors que pot representar la matriu de LED:
| Color | Significat |
| Vermell | Punt final, on s'ha d'arribar |
| Cian | Monedes a recollir |
| Magenta | Parets del laberint |
| Groc | Posició del jugador |
Els polsadors tenen les funcions que s'indiquen a continuació:
| Polsador | Finalitat |
| 1 | Pujar |
| 2 | Baixar |
| 3 | Esquerra |
| 4 | Dreta |
| 5 | Escollir la dificultat |
El programa és el següent:
#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 iniciar = 0;
char x = 7; // Coordenada X del cursor (0 a 7)
char y = 0; // Coordenada Y del cursor (0 a 7)
char TEMPS = 3; // Emplena la barra de temps
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 = 3; // Color vermell
char compte = 0; // Compta les vegades que passa el bucle
char posicions = 0; // Controla les posicions de la barra de temps
char dificultat = 0; // Cada valor que pren correspon a una dificultat
char t = 0; // Controla la velocitat de la partida
// canviant el nombre de vegades que es fa el bucle per sumar el temps
char reprodueix=0; // Controla quantes vegades s'ha reproduit el so de victòria i reinicia el joc
char DifActual = 999; // Comprova la dificultat (fàcil, mitja o difícil)
char JocIniciat=0; // Comprova si la partida ha començat o no
char desplazamiento = 0; //Desplaça els colors aleatòriament a la matriu de LED
char moneda1=0; // Comprova si s'ha agafat la moneda 1
char moneda2=0; // Comprova si s'ha agafat la moneda 2
char moneda3=0; // Comprova si s'ha agafat la moneda 3
char sumaMonedes=0; // Suma les monedes que s'han afagat
char escrit=0; // Comprova que no es torni a escriure una paraula ja escrita a la pantalla LCD
char posMoneda=2; // Indica la posició en que s'ha de dibuixar la moneda al final de la partida
// La matriu serveix per dibuixar les parets del laberint, així com
// per identificar les posicions que son paret i les que no
char figura[8][8] = { {0, 0, 0, 5, 0, 0, 0, 5},
{5, 5, 0, 5, 0, 5, 0, 5},
{0, 0, 0, 0, 0, 5, 0, 0},
{0, 5, 5, 5, 5, 5, 5, 0},
{0, 0, 5, 0, 0, 0, 0, 0},
{5, 5, 5, 0, 5, 5, 5, 0},
{5, 0, 0, 0, 5, 0, 5, 0},
{0, 0, 5, 5, 5, 0, 0, 0} };
// Definició de les funcions que farem servir
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B); // Envia la nota musical al brunzidor
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
void EnviaL(char Caracter); // Envia un caràcter
void Esborra(void); // Esborra la pantalla i posa el cursor a l'inici
void Cursor(char Filera, char Columna); // Posiciona el cursor
// (filera 1 a 2 i columna 1 a 32, segons pantalla)
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
ANSEL = 0b00000101; // Configura AN0 i AN2 com entrada analògica
ANSELH = 0; // Desactiva les altres entrades analògiques
TRISC = 0; // Tot el port C és de sortida
TRISB = 0; // Tot el port B és de sortida
__delay_ms(2000); // Esperem que arrenqui la pantalla
TXSTAbits.BRGH = 1; // Configuració de velocitat
BAUDCTLbits.BRG16 = 0; // Paràmetre de velocitat de 8 bits
SPBRG = 25; // Velocitat de 9600 baud
TXSTAbits.SYNC = 0; // Comunicació asíncrona
TXSTAbits.TX9 = 0; // Comunicació de 8 bits
while (1) { // Inici del bucle de programa
if(reprodueix == 3){ // Reinicia el joc i torna a la pantalla d'inici
x = 7; // Coordenada X del cursor (0 a 7)
y = 0; // Coordenada Y del cursor (0 a 7)
TEMPS = 3; // Emplena la barra de temps
mirar = 1; // Espera que es deixi anar el polsador
compt_int = 0; // Comptador de cicles per a la intermitència
cur_on = 1; // Controla l'estat del cursor
color = 3; // Color vermell
compte = 0; // Compta les vegades que passa el bucle
posicions = 0; // Controla les posicions de la barra de temps
dificultat = 0; // Cada valor que pren correspon a una dificultat
t = 0; // Controla la velocitat de la partida, canviant el
// nombre de vegades que es fa el bucle per sumar el temps
reprodueix=0; // Controla quantes vegades s'ha reproduit el so de victòria i reinicia el joc
DifActual=999; // Comprova la dificultat (fàcil, mitja o difícil)
JocIniciat=0; // Comprova si la partida ha començat o no
desplazamiento = 0; // Desplaça els colors aleatòriament a la matriu de LED
moneda1=0; // Comprova si s'ha agafat la moneda 1
moneda2=0; // Comprova si s'ha agafat la moneda 2
moneda3=0; // Comprova si s'ha agafat la moneda 3
sumaMonedes=0; // Suma les monedes que s'han afagat
escrit=0; // Comprova que no es torni a escriure una paraula ja escrita a la pantalla LCD
posMoneda=2; // Indica la posició en que s'ha de dibuixar la moneda al final de la partida
iniciar = 0;
}
if((dificultat == 0) && (iniciar == 0)&& (DifActual != 0)){
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('E'); // Lletra
EnviaL('S'); // Lletra
EnviaL('C'); // Lletra
EnviaL('U'); // Lletra
EnviaL('L'); // Lletra
EnviaL('L'); // Lletra
EnviaL(' '); // Lletra
EnviaL('L'); // Lletra
EnviaL('A'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('P'); // Lletra
EnviaL('r'); // Lletra
EnviaL('e'); // Lletra
EnviaL('m'); // Lletra
Cursor(2,1); //Canvia la posició a la pantalla LCD
EnviaL('D'); // Lletra
EnviaL('I'); // Lletra
EnviaL('F'); // Lletra
EnviaL('I'); // Lletra
EnviaL('C'); // Lletra
EnviaL('U'); // Lletra
EnviaL('L'); // Lletra
EnviaL('T'); // Lletra
EnviaL('A'); // Lletra
EnviaL('T'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('B'); // Lletra
EnviaL('T'); // Lletra
EnviaL('N'); // Lletra
EnviaL('5'); // Nombre
DifActual=0; //Canvia la dificultat
}
if((dificultat == 1) && (iniciar == 0)&& (DifActual != 1)){
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('D'); // Lletra
EnviaL('I'); // Lletra
EnviaL('F'); // Lletra
EnviaL('I'); // Lletra
EnviaL('C'); // Lletra
EnviaL('U'); // Lletra
EnviaL('L'); // Lletra
EnviaL('T'); // Lletra
EnviaL('A'); // Lletra
EnviaL('T'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('P'); // Lletra
EnviaL('r'); // Lletra
EnviaL('e'); // Lletra
EnviaL('m'); // Lletra
Cursor(2,1); //Canvia la posició a la pantalla LCD
EnviaL('F'); // Lletra
EnviaL('A'); // Lletra
EnviaL('C'); // Lletra
EnviaL('I'); // Lletra
EnviaL('L'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('B'); // Lletra
EnviaL('T'); // Lletra
EnviaL('N'); // Lletra
EnviaL('5'); // Nombre
DifActual=1; //Canvia la dificultat
t = 160; //Canvia el temps disponible durant la partida
}
if((dificultat == 2) && (iniciar == 0)&& (DifActual != 2)){
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('D'); // Lletra
EnviaL('I'); // Lletra
EnviaL('F'); // Lletra
EnviaL('I'); // Lletra
EnviaL('C'); // Lletra
EnviaL('U'); // Lletra
EnviaL('L'); // Lletra
EnviaL('T'); // Lletra
EnviaL('A'); // Lletra
EnviaL('T'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('P'); // Lletra
EnviaL('r'); // Lletra
EnviaL('e'); // Lletra
EnviaL('m'); // Lletra
Cursor(2,1); //Canvia la posició a la pantalla LCD
EnviaL('M'); // Lletra
EnviaL('I'); // Lletra
EnviaL('T'); // Lletra
EnviaL('J'); // Lletra
EnviaL('A'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('B'); // Lletra
EnviaL('T'); // Lletra
EnviaL('N'); // Lletra
EnviaL('5'); // Nombre
DifActual = 2; //Canvia la dificultat a triar
t = 110; //Canvia el temps disponible durant la partida
}
if ((dificultat == 3) && (iniciar == 0)&& (DifActual != 3)){
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('D'); // Lletra
EnviaL('I'); // Lletra
EnviaL('F'); // Lletra
EnviaL('I'); // Lletra
EnviaL('C'); // Lletra
EnviaL('U'); // Lletra
EnviaL('L'); // Lletra
EnviaL('T'); // Lletra
EnviaL('A'); // Lletra
EnviaL('T'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('P'); // Lletra
EnviaL('r'); // Lletra
EnviaL('e'); // Lletra
EnviaL('m'); // Lletra
Cursor(2,1); //Canvia la posició del cursor a la pantalla LCD
EnviaL('D'); // Lletra
EnviaL('I'); // Lletra
EnviaL('F'); // Lletra
EnviaL('I'); // Lletra
EnviaL('C'); // Lletra
EnviaL('I'); // Lletra
EnviaL('L'); // Lletra
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL(' '); // Espai
EnviaL('B'); // Lletra
EnviaL('T'); // Lletra
EnviaL('N'); // Lletra
EnviaL('5'); // Nombre
DifActual=3; //Canvia la dificultat a triar
t = 65; //Canvia el temps disponible durant la partida
}
if ((iniciar == 1)&& (JocIniciat == 0)){
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('T'); // Lletra
EnviaL('E'); // Lletra
EnviaL('M'); // Lletra
EnviaL('P'); // Lletra
EnviaL('S'); // Lletra
EnviaL(' '); // Lletra
EnviaL('R'); // Lletra
EnviaL('E'); // Lletra
EnviaL('S'); // Lletra
EnviaL('T'); // Lletra
EnviaL('A'); // Lletra
EnviaL('N'); // Lletra
EnviaL('T'); // Lletra
EnviaL(':'); // Símbol
JocIniciat = 1; // La partida passa a estar iniciada
}
if ((compte > t) && (posicions < 17) && (JocIniciat > 0)){
JocIniciat = JocIniciat + 1;
Cursor(2, posicions); // Canvia la posició del cursor de la pantalla LCD
EnviaL(TEMPS); // Emplena una posició de la barra de temps
compte = 0; // Reinicia el compte vegades que passa el bucle del programa
posicions = posicions + 1; // Canvia la posició a emplenar a la barra de temps
}
if ((posicions == 17) && (reprodueix<3)){ //Comprova si la barra de temps està plena
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('H'); // Lletra
EnviaL('A'); // Lletra
EnviaL('S'); // Lletra
EnviaL(' '); // Espai
EnviaL('P'); // Lletra
EnviaL('E'); // Lletra
EnviaL('R'); // Lletra
EnviaL('D'); // Lletra
EnviaL('U'); // Lletra
EnviaL('T'); // Lletra
EnviaL('!'); // Símbol
EnviaL('!'); // Símbol
EnviaL('!'); // Símbol
TRISC = 0b00100000; // Definim com volem les E/S del port C
// RC5 (sortida del PWM), de moment, com a entrada
PORTC = 0; // Desactiva les sortides del port C
CCP1CON = 0b00001100; // Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
// DC1B = 00 (bits 5-4) els dos bits de menys pes són 0
// CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten
// Ho posa com a configuració del PWM
PIR1bits.TMR2IF = 0; // Desactiva el bit d'interrupció del Timer 2
T2CON = 0b00000011; // Configura el Timer 2
// bits T2KCPS (bits 1-0) a 11 prescalat de 16
// bit 2 (TMR2ON) a 0, Timer aturat
// Postscaler TOUTPS (bits 6-3) no afecten al PWM
TocaNota(189, 95, 0); // Valor que correspon aproximadament a do3
TocaNota(212, 106, 2); // Valor que correspon aproximadament a re3
TocaNota(238, 119, 2); // Valor que correspon aproximadament a mi3
__delay_ms(200); // Retard de 0,2 s
reprodueix=reprodueix+1; // Torna a reproduir el so fins a 3 vegades
}
if ((posicions == 99) && (reprodueix<3)&& (escrit==0)){
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
EnviaL('H'); // Lletra
EnviaL('A'); // Lletra
EnviaL('S'); // Lletra
EnviaL(' '); // Espai
EnviaL('G'); // Lletra
EnviaL('U'); // Lletra
EnviaL('A'); // Lletra
EnviaL('N'); // Lletra
EnviaL('Y'); // Lletra
EnviaL('A'); // Lletra
EnviaL('T'); // Lletra
EnviaL('!'); // Símbol
EnviaL('!'); // Símbol
Cursor(2,1); //Canvia la posició del cursor a la pantalla LCD
sumaMonedes=moneda1+moneda2+moneda3; //Suma les monedes que s'han recollit durant la partida
escrit=1; //Canvia el valor perquè no es torni a escriure la frase
for (signed char k = 1; k <= DifActual; k++){ //Dibuixa parells de claudàtors segons el nivell
EnviaL('['); // Signe
EnviaL(' '); // Espai
EnviaL(']'); // Lletra
}
if (sumaMonedes>0){ //Si no s'han aconseguit monedes no es dibuixarà res més
for (signed char k = 1; k <= sumaMonedes; k++){
// Introdueix les estrelles obtingudes dins els claudàtors
Cursor(2,posMoneda); //Canvia la posició del cursor a la pantalla LCD
EnviaL('*'); // Símbol
posMoneda=posMoneda+3; //Canvia la posició en què s'ha de mostrar la moneda
}
}
TRISC = 0b00100000; // Definim com volem les E/S del port C
// RC5 (sortida del PWM), de moment, com a entrada
PORTC = 0; // Desactiva les sortides del port C
CCP1CON = 0b00001100; // Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
// DC1B = 00 (bits 5-4) els dos bits de menys pes són 0
// CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten
// Ho posa com a configuració del PWM
PIR1bits.TMR2IF = 0; // Desactiva el bit d'interrupció del Timer 2
T2CON = 0b00000011; // Configura el Timer 2
// bits T2KCPS (bits 1-0) a 11 prescalat de 16
// bit 2 (TMR2ON) a 0, Timer aturat
// Postscaler TOUTPS (bits 6-3) no afecten al PWM
// Inici del bucle de programa
TocaNota(238, 119, 2); // Valor que correspon aproximadament a do3
TocaNota(212, 106, 2); // Valor que correspon aproximadament a re3
TocaNota(189, 95, 0); // Valor que correspon aproximadament a mi3
__delay_ms(200); // Retard de 0,2 s
TocaNota(238, 119, 2); // Valor que correspon aproximadament a do3
TocaNota(212, 106, 2); // Valor que correspon aproximadament a re3
TocaNota(189, 95, 0); // Valor que correspon aproximadament a mi3
__delay_ms(200); // Retard de 0,2 s
reprodueix=3; // Reinicia el joc
}
// 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 == 5) && (iniciar == 0)){ // Si s'ha premut el polsador 5 (DIFICULTAT)
dificultat = dificultat + 1; // Canvia la dificultat
mirar = 0;
}
if ((Polsad == 5) && (dificultat == 4) && (iniciar == 0)){
// Si s'ha premut el polsador 5 (DIFICULTAT) quan la dificultat és difícil
dificultat = 0; //Torna a començar l'elecció de dificultat
mirar = 0;
}
if ((Polsad == 1) && (x < 7 && figura[y][(7-x)-1] == 0) && (iniciar > 0)){
// Si s'ha premut el polsador 1 // ESQUERRA // LA X Y LA Y no es recorren (0,0)xy ==(0,8))
x = (x + 1); // Incrementa x
mirar = 0;
}
if ((Polsad == 2) && (x > 0 && figura[y][(7-x)+1] == 0) && (dificultat > 0)){
// Si s'ha premut el polsador 2 // DRETA // LA X Y LA Y no es recorren (0,0)xy ==(0,8))
x = (x - 1); // Disminueix x
mirar = 0;
if ((iniciar == 0) ) { // Si el joc no s'ha iniciat i es prem el polsador 2,
// comença la partida
iniciar = 1; // Incrementa x però la manté entre 0 i 7
}
}
if ((Polsad == 3) && (y > 0 && figura[y-1][(7-x)] == 0) && (iniciar > 0)){
// Si s'ha premut el polsador 3 // AMUNT // LA X Y LA Y no es recorren (0,0)xy ==(0,8))
y = (y - 1); // Disminueix y
mirar = 0;
}
if ((Polsad == 4) && (y < 7 && figura[y+1][7-x] == 0) && (iniciar > 0)){
// Si s'ha premut el polsador 4 // AVALL // LA X Y LA Y no es recorren (0,0)xy ==(0,8))
y = (y + 1); // Incrementa y
mirar = 0;
}
} else {
if (Polsad == 0) { // Si no s'ha premut cap polsador (o dos a la vegada)
mirar = 1;
}
}
// Mostrarem la figura actual a la matriu de LED
for (signed char j = 0; j < 8; j++) { // Fileres
char mascara;
char col = 0;
for (signed char k = 0; k < 8; k++) { // Columnes
col = 0; // Canvia el color
if ((y == j) && (x == k)) { // Si estem a la casella del cursor
if (cur_on == 1) { // Si toca el cursor encès
col = color; // Color actual
}
} else {
col = figura[j][7 - k]; // Utilitzar el valor de la figura
}
if ((x == 7) && (y == 7)){ // Condició per a la victòria (afegirem efecte multicolor)
posicions=99;
desplazamiento = rand() % 7; // Desplaçament aleatori entre 0 y 6
if (compte % 1 == 0) {
desplazamiento = rand() % 7; // Desplaçament aleatori entre 0 y 6
}
// Apliquem el desplaçament per al color en funció de la columna
switch((k + desplazamiento) % 7) { // Movem el patró de colors
case 0:
col = 2; // Vermell
break;
case 1:
col = 4; // Taronja
break;
case 2:
col = 5; // Groc
break;
case 3:
col = 6; // Verd
break;
case 4:
col = 2; // Blau cel
break;
case 5:
col = 7; // Blau
break;
case 6:
col = 7; // Lila
break;
}
}
if (posicions == 17) { // Condició per a la derrota (posicions == 17)
col = 1; // Color per la derrota (vermell)
color = 1;
}
if ((j == 7) && (k == 7) && (posicions != 99)) {
// Si estem a la casella del cursor a la última posició
col = 1;
}
//Dibuixarem les monedes a la pantalla de LED
//------------------CAS DE DIFICULTAT FÀCIL------------------
// Només tindrem una moneda
if ((j == 2) && (k == 7) &&(DifActual==1)&&(moneda1==0)&&(posicions<17)) {
// Si estem a la casella de la moneda
col=6; // Dibuixa la moneda
}
if ((y == 2) && (x == 7)&&(DifActual==1)){
// Si passem per sobre de la casella, la moneda desapareix i es té en compte que la hem afagat
moneda1=1;
}
//------------------CAS DE DIFICULTAT MITJA------------------
// Tindrem dues monedes
if ((j == 4) && (k == 6) &&(DifActual==2)&&(moneda1==0)&&(posicions<17)) {
// Si estem a la casella de la moneda
col=6; // Dibuixa la moneda
}
if ((y == 4) && (x == 6)&&(DifActual==2)){
// Si passem per sobre de la casella, la moneda desapareix i es té en compte que la hem afagat
moneda1=1;
}
if ((j == 6) && (k == 0) &&(DifActual==2)&&(moneda2==0)&&(posicions<17)) {
// Si estem a la casella de la moneda
col=6; // Dibuixa la moneda
}
if ((y == 6) && (x == 0)&&(DifActual==2)){
// Si passem per sobre de la casella, la moneda desapareix i es té en compte que la hem afagat
moneda2=1;
}
//------------------CAS DE DIFICULTAT DIFÍCIL------------------
// Tindrem tres monedes
if ((j == 4) && (k == 6) &&(DifActual==3)&&(moneda1==0)&&(posicions<17)) {
// Si estem a la casella de la moneda
col=6; // Dibuixa la moneda
}
if ((y == 4) && (x == 6)&&(DifActual==3)){
// Si passem per sobre de la casella, la moneda desapareix i es té en compte que la hem afagat
moneda1=1;
}
if ((j == 6) && (k == 2) &&(DifActual==3)&&(moneda2==0)&&(posicions<17)) {
// Si estem a la casella de la moneda
col=6; // Dibuixa la moneda
}
if ((y == 6) && (x == 2)&&(DifActual==3)){
// Si passem per sobre de la casella, la moneda desapareix i es té en compte que la hem afagat
moneda2=1;
}
if ((j == 1) && (k == 1) &&(DifActual==3)&&(moneda3==0)&&(posicions<17)) {
// Si estamos en la casilla del cursor
col=6;
}
if ((y == 1) && (x == 1)&&(DifActual==3)){
// Si passem per sobre de la casella, la moneda desapareix i es té en compte que la hem afagat
moneda3=1;
}
// Colocar los bits en la columna correspondiente
mascara = col & 0b0000001; // Será 1 si hay rojo
Sortida[0] = Sortida[0] | (mascara << k);
mascara = (col & 0b0000010) >> 1; // Será 1 si hay verde
Sortida[2] = Sortida[2] | (mascara << k);
mascara = (col & 0b0000100) >> 2; // Será 1 si hay azul
Sortida[4] = Sortida[4] | (mascara << k);
}
Sortida[1] = j + 1; // Fila
Sortida[3] = j + 1; // Fila
Sortida[5] = j + 1; // Fila
Envia3max(Sortida); // 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){
// void interrupt temporit(void) { // Línia alternativa
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
compte = compte + 1;
}
}
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] = 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("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("movwf PORTB"); // I el posa al port B
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("movwf PORTB"); // I el posa al port B
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("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&7fh)");
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("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;
}
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B) {
TRISC = 0b00100000; // Definim com volem les E/S del port C
// RC5 (sortida del PWM), de moment, com a entrada
PR2 = ValPR2; // Carrega PR2
CCP1CON = CCP1CON & 0b11001111; // Posa a zero els bits que corresponen a DC1B
ValDC1B = ValDC1B % 4; // DC1B va de 0 a 3
ValDC1B = ValDC1B * 16; // Desplaça els bits a la posició que els correspon a CCP1CON
CCP1CON = CCP1CON | ValDC1B; // Coloca DC1B al seu lloc
CCPR1L = ValCCPR1L; // Carrega CCPR1L, registre que ens dona l'amplada de tON
PIR1bits.TMR2IF = 0; // Desactiva el bit d'interrupció del Timer 2
T2CON = 0b00000111; // Configura el Timer 2
// bits T2KCPS (bits 1-0) a 11 prescalat de 16
// bit 2 (TMR2ON) a 1, Timer activat
// Postscaler TOUTPS (bits 6-3) no afecten al PWM
while (PIR1bits.TMR2IF == 0) // Espera l'activació del bit d'interrupció del Timer 2
; // Esperem
TRISC = 0b00000000; // Posem RC5 (sortida del PWM) com a sortida
__delay_ms(200); // Retard de 0,2 s
TRISC = 0b00100000; // Posem RC5 (sortida del PWM) com a entrada
// O sigui, silenci
__delay_ms(200); // Retard de 0,2 s
}
void EnviaL(char Caracter) {
INTCONbits.GIE = 0; // Desactiva les interrupcions momentàniament
RCSTAbits.SPEN = 1; // Activa comunicació sèrie
TXSTAbits.TXEN = 1; // Activa comunicació
TXREG = Caracter; // Agafa el caràcter i l'envia
__delay_ms(1); // Donem temps
while (PIR1bits.TXIF == 0) // Esperem que s'acabi d'enviar
; // No fem res
RCSTAbits.SPEN = 0; // Desactiva comunicació sèrie
TXSTAbits.TXEN = 0; // Desactiva comunicació
INTCONbits.GIE = 1; // Activa les interrupcions
}
void Esborra(void) {
EnviaL(254); // Caràcter de control
EnviaL(1); // Esborra la pantalla i posa el cursor a l'inici
}
void Cursor(char Filera, char Columna) {
char Posicio = 0; // Variable per a calcular la posició
if (Filera == 2) {
Posicio = 64; // La primera columna de la segona fila és 64;
}
if (Columna > 0 && Columna < 33) { // Comprovem que sigui un valor raonable
Posicio = Posicio + Columna; // Sumem les adreces
Posicio = Posicio - 1; // Restem 1 perquè numera des de 0
}
Posicio = Posicio + 128; // Posa el bit de posicionat a 1
EnviaL(254); // Control de la posició del cursor
EnviaL(Posicio); // Canvia el cursor de lloc
}

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