Programació en C del PIC 16F690

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

Desenvolupament de jocs senzills

Joc de memòria (Simon)

Aquest joc és similar al popular joc Simon. Es tracta de memoritzar una seqüència que, si es va encertant, cada cop és més llarga. En la seqüència hi intervenen quatre elements i cada un d'ells està caracteritzat per un LED, un color a la matriu i una nota; per tant, la persona que juga pot memoritzar qualsevol de les tres coses. A més, hi ha quatre nivells de 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>
#include <stdlib.h>    // Carrega el fitxer on hi ha la funció rand()
#define _XTAL_FREQ 4000000    // Define la frecuencia de operación
#define Polsador1 RA3    // Li assigna un nom a l'adreça del polsador
char Polsad;    // Variable para almacenar el pulsador presionado
char llista[20];   // Secuencia de LEDs en PORTC (en binario para activar RC0, RC1, RC2, RC3) maximo long 20
char nn1;
char numr;
char numv;
char numa;
char numm;
char nn = 20;    // Longitd de la lista
char n = 1;   // Número de LEDs en la secuencia a mostrar
char n1 = 0;  // Contador para la secuencia de LEDs
char n2 = 0;  // Contador para el ingreso de pulsadores del usuario
char a = 0;   // Variable temporal para la secuencia de LEDs
char b = 0;   // Variable temporal para la secuencia de pulsadores
char r = 0;
char r1 = 0;
char cte = 1;
char puntM = 48;// Variable para guardar la puntuación en 10 Mil
char puntm = 48;// Variable para guardar la puntuación en Miles
char punt = 48;// Variable para guardar la puntuación (48 equivale a 0)
char highscore = 0;// Variable para guardar puntuación máxima
char jugadas = 1;// Variable para guaradar cuantas veces se ha jugado
char jugadas1 = 0;
char dif = 2;// Dificultad
char number = 4;// 4,3,2 luces
char replay = 3;//Variable para guardar la cantidad de veces que puedes repetir
char replay1 = 3;
char notadiff = 1;// 1 funciona, 0 no
char luzdiff = 1;// 1 funciona, 0 no
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
// Definició de les funcions que farem servir 
void GenSecAl(void);
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 TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
void Toca(char);
char Polsador(void);    // Prototipo de la función para leer los pulsadores
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)
void Repetir(char r);
void Matriz(char luz);
void Selection(char select);
void Diff(char dif);
void main(void){
    ANSEL = 0b00000101;    // Configura AN0 y AN2 como entradas analógicas
    ANSELH = 0;    // Desactiva las otras entradas analógicas
    TRISC = 0;    // Configura el puerto C como salida
    TRISB = 0;    // Configura el puerto B como salida
    __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
    TRISA = 0xFF;    // Configura el puerto A como entrada
    ADCON1 = 0b00010000;    // Conversor A/D con velocidad de 1/8 del reloj
    ADCON0 = 0b00001001;    // Activa el A/D en AN2
    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)
    ANSELH = 0;    // Desactiva les altres entrades analògiques
    PORTC = 0;    // Inicialitza a 0 el port C
    PORTB = 0;    // Inicialitza a 0 el port B
    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
    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
    Selection(5);
    Polsad = Polsador();   // Detectar el pulsador presionado
    while (Polsador1 == 1){
        while (Polsad == 0){
            __delay_ms(10);    // Retardo para estabilizar el ADC
            Polsad = Polsador();   // Detectar el pulsador presionado
            Selection(Polsad);
            Diff(Polsad);
            Polsad = 0;
            if (Polsador1 == 0){
                break;
            }
        } 
    }
    srand(TMR0);    // Agafa una llavor
    GenSecAl();  // Genera la primera secuencia aleatoria
    while (1){ // Bucle infinito
        // Asegurarse de que la longitud no excede los elementos de `llista`
        if (n > sizeof(llista)){
            n = 1;  // Vuelve al inicio porque ha terminado la lista
            GenSecAl();  // Genera otra secuencia aleatoria
        }
        // Mostrar la secuencia de LEDs
        for (n1 = 0; n1 < n; n1++){
            a = llista[n1];
            // Asignar los valores correctos de `a` a `PORTC`
            switch (a){
                case 1: PORTC = 0b00000001; Toca(1); Matriz(1); break;  // LED 1
                case 2: PORTC = 0b00000010; Toca(2); Matriz(2); break;  // LED 2
                case 3: PORTC = 0b00000100; Toca(3); Matriz(3); break;  // LED 3
                case 4: PORTC = 0b00001000; Toca(4); Matriz(4); break;  // LED 4
                default: PORTC = 0; break;    // Apaga los LEDs en caso de error
            }
            __delay_ms(100);    // Retardo para visualizar el LED
            PORTC = 0;    // Apaga los LEDs entre pasos
            __delay_ms(100);
        }
        // Apaga los LEDs al finalizar la secuencia
        PORTC = 0;
        Apaga();    // Apaga matriz al terminar
        __delay_ms(100);
        // Esperar el ingreso de la secuencia de pulsadores por el usuario
        n2 = 0;    // Reinicia el contador de ingreso del usuario
        int success = 1;    // Variable para indicar si el usuario ingresó correctamente la secuencia
        // Bucle para validar la secuencia del usuario
        while (n2 < n){
            Polsad = 0;  // Reiniciamos el valor de Polsad antes de detectar un nuevo pulsador
            // Esperar a que el usuario presione un botón válido
            while (Polsad == 0){
                __delay_ms(10);    // Retardo para estabilizar el ADC
                Polsad = Polsador();   // Detectar el pulsador presionado
            }            
            //__delay_ms(200);    // Esperar un tiempo para evitar lecturas múltiples
            b = llista[n2];    // Obtiene el valor correcto de la secuencia en la posición actual
            if ((Polsad == 5) && (replay > 0)){
                Repetir(n2);
                replay = replay - 1;
            }
            if (Polsad >= 1 && Polsad <= 4){  // Verifica que el pulsador es válido
                if (Polsad == b){    // Comparar con el valor de la secuencia
                    Toca(Polsad);
                    Matriz(b);
                    n2++;    // Avanzar al siguiente pulsador
                    punt = punt + 1;    // Incremtamos puntuacion por acierto
                } else {
                    // Manejo del error como ya está implementado
                    PORTC = 0b00001111; TocaNota(118, 59, 2);  // Enciende todos los LEDs como señal de error
                    __delay_ms(50);
                    PORTC = 0;
                    __delay_ms(50);
                    PORTC = 0b00001111; TocaNota(118, 59, 2);
                    __delay_ms(50);
                    PORTC = 0;
                    __delay_ms(50);
                    n = 1;    // Reinicia el juego a la primera secuencia
                    replay = replay1;
                    jugadas = jugadas + 1;
                    puntM = 48;
                    puntm = 48;
                    punt = 48;
                    Esborra();
                    Cursor(1, 7);
                    EnviaL('E');
                    EnviaL('R');
                    EnviaL('R');
                    EnviaL('O');
                    EnviaL('R');
                    __delay_ms(300);
                    Esborra();
                    success = 0;    // Indica que el usuario se equivocó
                    GenSecAl();
                    break;    // Salir del bucle de ingreso del usuario
                }
            }
        }
        //Si el usuario completó correctamente la secuencia
        if (success && n2 == n){
            n = n + 1;    // Incrementa la longitud de la secuencia
            if (n > highscore){
                highscore = n;
            }
            punt = punt + 2 + n/5;    // Bonificación por acabar la secuencia + extra por larga duración
            while (punt > 57){ // Si pasamos de 900 puntos convertirlos en 1 mil
                punt = punt - 10;
                puntm = puntm + 1;
                if (puntm > 57){ // Si pasamos de 9 mil puntos convertirlos a 10 mil
                    puntm = puntm - 10;
                    puntM = puntM + 1;
                    if (puntM > 57){ // Llegamos al maximo de numeros, reiniciamos (podria ser eliminada ya que es imposible)
                        puntM = 48;
                        puntm = 48;
                        punt = 48;
                    }
                }
            }
            Esborra();    // Esborra la pantalla i posa el cursor a l'inici
            if (puntM > 48){
                EnviaL(puntM);
                EnviaL(puntm);
            }
            if ((puntm > 48) && (puntM == 48)){
                EnviaL(puntm);
            }
            EnviaL(punt);    // Puntuación
            EnviaL(48);
            EnviaL(48);
            Cursor(1, 8);
            EnviaL('N');    // Lletra
            EnviaL(' ');
            EnviaL('=');    // Lletra
            EnviaL(' ');
            EnviaL(n+48);    // Lletra
            Cursor(1, 15);
            if (jugadas > 9){
                jugadas1 = jugadas1 + 1;
                jugadas = jugadas - 10;
                EnviaL(jugadas1 + 48);
                EnviaL(jugadas + 48);
            }
            if (jugadas < 10){
                EnviaL(' ');
                EnviaL(jugadas + 48);
            }
            Cursor(2, 1);    // Posició
            EnviaL('H');
            EnviaL('I');
            EnviaL('G');
            EnviaL('H');
            EnviaL(' ');
            EnviaL('S');
            EnviaL('C');
            EnviaL('O');
            EnviaL('R');
            EnviaL('E');
            if (highscore > 9){
                EnviaL('=');
                EnviaL(49);
                EnviaL(highscore + 38);
            } else {
                EnviaL(' ');
                EnviaL('=');    
                EnviaL(' ');
                EnviaL(highscore + 48);
            }
            Cursor(2, 16);
            EnviaL(replay + 48);
        }
    }
}
// Pantalla
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
    }
}
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
    }
}
// Pantalla LCD
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
}
// Brunzidor
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
}
// Programas propios
void Selection(char select){ //5 base, 1,2,3,4 segun dificultad
    if (select == 5){
        Esborra();
        EnviaL('S');
        EnviaL('E');
        EnviaL('L');
        EnviaL('E');
        EnviaL('C');
        EnviaL('T');
        EnviaL(' ');
        EnviaL('G');
        EnviaL('A');
        EnviaL('M');
        EnviaL('E');
        EnviaL('M');
        EnviaL('O');
        EnviaL('D');
        EnviaL('E');
        Cursor(2, 1);
        EnviaL('E');
        EnviaL('Z');
        EnviaL('Y');
        EnviaL(' ');
        EnviaL('M');
        EnviaL('E');
        EnviaL('D');
        EnviaL(' ');
        EnviaL('H');
        EnviaL('R');
        EnviaL('D');
        EnviaL(' ');
        EnviaL('E');
        EnviaL('X');
        EnviaL('T');
    }
    if (select == 4){
        Esborra();
        EnviaL('S');
        EnviaL('E');
        EnviaL('L');
        EnviaL('E');
        EnviaL('C');
        EnviaL('T');
        EnviaL(' ');
        EnviaL('G');
        EnviaL('A');
        EnviaL('M');
        EnviaL('E');
        EnviaL('M');
        EnviaL('O');
        EnviaL('D');
        EnviaL('E');
        Cursor(2, 6);
        EnviaL('E');
        EnviaL('A');
        EnviaL('S');
        EnviaL('Y');
    }
    if (select == 3){
        Esborra();
        EnviaL('S');
        EnviaL('E');
        EnviaL('L');
        EnviaL('E');
        EnviaL('C');
        EnviaL('T');
        EnviaL(' ');
        EnviaL('G');
        EnviaL('A');
        EnviaL('M');
        EnviaL('E');
        EnviaL('M');
        EnviaL('O');
        EnviaL('D');
        EnviaL('E');
        Cursor(2, 5);
        EnviaL('M');
        EnviaL('E');
        EnviaL('D');
        EnviaL('I');
        EnviaL('U');
        EnviaL('M');
    }
    if (select == 2){
        Esborra();
        EnviaL('S');
        EnviaL('E');
        EnviaL('L');
        EnviaL('E');
        EnviaL('C');
        EnviaL('T');
        EnviaL(' ');
        EnviaL('G');
        EnviaL('A');
        EnviaL('M');
        EnviaL('E');
        EnviaL('M');
        EnviaL('O');
        EnviaL('D');
        EnviaL('E');
        Cursor(2, 6);
        EnviaL('H');
        EnviaL('A');
        EnviaL('R');
        EnviaL('D');
    }
    if (select == 1){
        Esborra();
        EnviaL('S');
        EnviaL('E');
        EnviaL('L');
        EnviaL('E');
        EnviaL('C');
        EnviaL('T');
        EnviaL(' ');
        EnviaL('G');
        EnviaL('A');
        EnviaL('M');
        EnviaL('E');
        EnviaL('M');
        EnviaL('O');
        EnviaL('D');
        EnviaL('E');
        Cursor(2, 3);
        EnviaL('!');
        EnviaL(' ');
        EnviaL('E');
        EnviaL('X');
        EnviaL('T');
        EnviaL('R');
        EnviaL('E');
        EnviaL('M');
        EnviaL('E');
        EnviaL(' ');
        EnviaL('!');
    }
}
void Diff(char dif){
    // number, replay, luz, notadiff
    if (dif == 4){ // EZY
        number = 2;
        replay = 9;
        notadiff = 1;
        luzdiff = 1;
    }
    if (dif == 3){ // MED
        number = 3;
        replay = 5;
        notadiff = 1;
        luzdiff = 1;
    }
    if (dif == 2){ // Ez
        number = 4;
        replay = 3;
        notadiff = 1;
        luzdiff = 1;
    }
    if (dif == 1){ // Ez
        number = 4;
        replay = 0;
        notadiff = 0;
        luzdiff = 0;
    }
    replay1 = replay;
}
void Repetir(char r){
    for (r1 = r; r1 < n; r1++){
        r = llista[r1];
        // Asignar los valores correctos de `a` a `PORTC`
        switch (r){
            case 1: PORTC = 0b00000001; Toca(1); Matriz(1); break;  // LED 1
            case 2: PORTC = 0b00000010; Toca(2); Matriz(2); break;  // LED 2
            case 3: PORTC = 0b00000100; Toca(3); Matriz(3); break;  // LED 3
            case 4: PORTC = 0b00001000; Toca(4); Matriz(4); break;  // LED 4
            default: PORTC = 0; break;    // Apaga los LEDs en caso de error
        }
        __delay_ms(100);    // Retardo para visualizar el LED
        PORTC = 0;    // Apaga los LEDs entre pasos
        Apaga();    // Apaga matriz entre pasos
        __delay_ms(100);
    }
}
void Matriz(char luz){
    if (luzdiff == 1){
        numr = 0b00000000; // ponemos todos a 0
        numv = 0b00000000;
        numa = 0b00000000;
        switch(luz){
            case 1: numr = 0b00001111; numm = 2; break;  // Rojo  
            case 2: numr = 0b11110000; numv = 0b11110000; numm = 2; break;  // Amarillo
            case 3: numv = 0b00001111; numm = 1; break;  // Verde
            case 4: numa = 0b11110000; numm = 1; break;  // Azul
        }
        for (nn1 = 1; nn1 < 9; nn1++){
            Sortida[1] = nn1;  // Filera 1
            Sortida[3] = nn1;
            Sortida[5] = nn1;
            if (numm == 1 && nn1 <= 4){
                Sortida[0] = numr;    // Rojo
                Sortida[2] = numv;    // Verde
                Sortida[4] = numa;    // Azul
            }
            if (numm == 2 && nn1 > 4){
                Sortida[0] = numr;    // Rojo
                Sortida[2] = numv;    // Verde
                Sortida[4] = numa;    // Azul
            }
            Envia3max(Sortida);    // Ho envia al MAX7221
        }
    } else {
        __delay_ms(100);
    }
}
void Toca(char nota){
    if (notadiff == 1){
        switch (nota){
            case 1: TocaNota(238, 119, 2); break;  // LED 1
            case 2: TocaNota(158, 79, 2); break;  // LED 2
            case 3: TocaNota(189, 95, 0); break;  // LED 3
            case 4: TocaNota(126, 63, 2); break;  // LED 4
            default: break;    // Apaga los LEDs en caso de error
        }
    } else {
        __delay_ms(100);
    }
}
// Polsadores
char Polsador(void){
    char Pols = 0;
    ADCON0bits.GO = 1;    // Inicia la conversión A/D
    while (ADCON0bits.GO == 1);    // Espera a que termine la conversión

    // Asigna un valor de pulsador según el valor de ADRESH
    if (ADRESH < 220 && ADRESH > 200){
        Pols = 4;
    }
    if (ADRESH < 194 && ADRESH > 174){
        Pols = 3;
    }
    if (ADRESH < 163 && ADRESH > 143){
        Pols = 2;
    }
    if (ADRESH < 90 && ADRESH > 70){
        Pols = 1;
    }
    if (ADRESH < 55 && ADRESH > 35){
        Pols = 5;    // Comprova polsador 5
    }
    return Pols;
}
void GenSecAl(void){
    for (char i = 0; i < nn; i++){
        a = rand();
        llista[i] = a % number + 1;  // Genera números aleatorios para la secuencia
    }
}

 

 

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