Fork me on GitHub

Microcontrolandos

O Blog está passando por uma fase de mudanças. Todos os posts estão sendo atualizados, códigos, links e imagens estão sendo arrumados. Conteúdos novos ainda estão por vir.

PIC: Genius, Jogo da Memória

Share:

PIC: Genius, Jogo da Memória



Neste post vamos criar o jogo Genius com o PIC16F628A e outro com PIC16F877A.

O Jogo é formado basicamente por 4 Leds ( Amarelo, Azul, Verde e Vermelho ), 5 botões e 1 buzzer.

O botões utiliza os resistores de pull-up internos do PIC. Também foi utilizado o oscilador interno de 4Mhz( para o PIC16F628A ). No caso do PIC16F877A necessita de um cristal oscilador externo.


Obs.:
  • Habilitar as bibliotecas Sound C_Stdlib.

CÓDIGO
MikroC PRO PIC
#define NOTE_A 440
#define NOTE_D 294
#define NOTE_B 523
#define NOTE_C 261
#define NOTE_F 349
#define NOTE_E 329
#define NOTE_G 392

#define NIVEIS 20


sbit Start at PORTB.B3;
sbit Botao1 at PORTB.B4;
sbit Botao2 at PORTB.B5;
sbit Botao3 at PORTB.B6;
sbit Botao4 at PORTB.B7;
sbit Led1 at PORTB.B0;
sbit Led2 at PORTB.B1;
sbit Led3 at PORTB.B2;
sbit Led4 at PORTA.B1;

char level = 1; //Nivel inicial
char Memoria1[NIVEIS]; //Memoria para armazanar a sequncia gerada pelo PIC
char Memoria2[NIVEIS]; //Memoria para armazenar a sequencia de acordo com os cliques nos botões

void Som_Botao1()
{
    Led1 = 1;
    Sound_Play( NOTE_F, 300 );
    Delay_ms( 300 );
    Led1 = 0;
}

void Som_Botao2()
{
    Led2 = 1;
    Sound_Play( NOTE_B, 300 );
    Delay_ms( 300 );
    Led2 = 0;
}

void Som_Botao3()
{
    Led3 = 1;
    Sound_Play( NOTE_C, 300 );
    Delay_ms( 300 );
    Led3 = 0;
}

void Som_Botao4()
{
    Led4 = 1;
    Sound_Play( NOTE_D, 300 );
    Delay_ms( 300 );
    Led4 = 0;
}

void Som_Inicial()
{
    Led1 = 1; Led2 = 1; Led3 = 1; Led4 = 1;
    Sound_Play( 200, 100 );
    Delay_ms( 100 );
    Sound_Play( 400, 100 );
    Delay_ms( 100 );
    Sound_Play( 200, 100 );
    Delay_ms( 500 );
    Led1 = 0; Led2 = 0; Led3 = 0; Led4 = 0;
}

void Som_Perdeu()
{
    Led1 = 1; Led2 = 1; Led3 = 1; Led4 = 1;
    Sound_Play( 200, 300 );
    Delay_ms( 300 );
    Sound_Play( 150, 300 );
    Delay_ms( 300 );
    Sound_Play( 100, 300 );
    Delay_ms( 300 );
    Led1 = 0; Led2 = 0; Led3 = 0; Led4 = 0;
}

void Som_Ganhou()
{
    Led1 = 1; Led2 = 1; Led3 = 1; Led4 = 1;
    Sound_Play( 500, 100 );
    Delay_ms( 300 );
    Sound_Play( 700, 300 );
    Delay_ms( 200 );
    Sound_Play( 900, 500 );
    Delay_ms( 500 );
    Sound_Play( 800, 200 );
    Delay_ms( 200 );
    Sound_Play( 900, 500 );
    Delay_ms( 500 );
    Led1 = 0; Led2 = 0; Led3 = 0; Led4 = 0;
}

void GerarSequencia()
{
unsigned semente;
char i, random;

    semente = (TMR1H << 8) + TMR1L;
    srand( semente );
    
    for( i=0; i < level; i++)
    {
         random = (char)(rand() % 4); //Gera um número aleatório entre 0 e 3
         Memoria1[i] = random;
         
         if(random == 0)
           Som_Botao1();
         else if(random == 1)
           Som_Botao2();
         else if(random == 2)
           Som_Botao3();
         else
           Som_Botao4();
           
         Delay_ms( 200 );
    }

}

char VerificarSequencia()
{
char i;
     for( i=0; i < level; i++)
     {
         if( Memoria2[i] != Memoria1[i] )
          return 0;
     }
     return 1;
}

void main()
{
char cnt = 0;
char flags = 0;

    T1CON = 0x81; //Utilizado como semente para gerar os números aleatórios
    CMCON = 0x07; //Desliga o comparador
    NOT_RBPU_Bit = 0; //Habilita os Resistores de Pull-UP
    TRISB = 0b11111000;
    TRISA = 0;
    Sound_Init( &PORTA, 0 ); 
    
    Som_Inicial();
    
Inicio:
    while(Start); //Espera o botão Start ser pressionado
    
    Delay_ms( 1000 );

    while(1)
    {
        cnt = 0;
        GerarSequencia(); //Gera uma sequencia
        
        while(1)
        {
           if(!Botao1) flags.B0 = 1;
           else if(!Botao2) flags.B1 = 1;
           else if(!Botao3) flags.B2 = 1;
           else if(!Botao4) flags.B3 = 1;

           if(Botao1 && flags.B0)
           {
             flags.B0 = 0;
             Memoria2[cnt++] = 0;
             Som_Botao1();
           }
           
           else if(Botao2 && flags.B1)
           {
             flags.B1 = 0;
             Memoria2[cnt++] = 1;
             Som_Botao2();
           }
           
           else if(Botao3 &&  flags.B2)
           {
             flags.B2 = 0;
             Memoria2[cnt++] = 2;
             Som_Botao3();
           }
           
           else if(Botao4 &&  flags.B3)
           {
             flags.B3 = 0;
             Memoria2[cnt++] = 3;
             Som_Botao4();
           }
           
           if( cnt == level )
             break;
        
        }
        
        if( VerificarSequencia() )
        {
           level++;
           if(level == NIVEIS)
           {
              level = 1;
              Som_Ganhou();
              goto Inicio;
           }
        }
        else
        {
           level = 1;
           Som_Perdeu();
           goto Inicio;
        }
        
        Delay_ms ( 1000 );
    }
    
}


VERSÃO 2



Nesta outra versão com o PIC16F877A foi adicionado dois displays de 7 segmentos CC para fazer a contagem dos acertos.

Obs.:
  • Habilitar as bibliotecas Sound e C_Stdlib.
  • Não se esqueça de colocar os resistores na saída da PORTC.


CÓDIGO
MikroC PRO PIC
#define NOTE_A 440
#define NOTE_D 294
#define NOTE_B 523
#define NOTE_C 261
#define NOTE_F 349
#define NOTE_E 329
#define NOTE_G 392

#define NIVEIS 30

//Botoes
sbit Start at PORTB.B3;
sbit Botao1 at PORTB.B4;
sbit Botao2 at PORTB.B5;
sbit Botao3 at PORTB.B6;
sbit Botao4 at PORTB.B7;
//Leds
sbit Led1 at PORTB.B0;
sbit Led2 at PORTB.B1;
sbit Led3 at PORTB.B2;
sbit Led4 at PORTA.B1;
//selecao do display
sbit Disp1 at PORTD.B6;
sbit Disp2 at PORTD.B7;

//nivel atual do jogo
char level = 1;
//buffers
char Memoria1[NIVEIS];
char Memoria2[NIVEIS];
//numeros para o display
char Display[10] = { 63, 6, 91, 79, 102, 109, 125, 7, 127, 111 };


void Som_Botao1()
{
    Led1 = 1;
    Sound_Play( NOTE_F, 300 );
    Delay_ms( 300 );
    Led1 = 0;
}

void Som_Botao2()
{
    Led2 = 1;
    Sound_Play( NOTE_B, 300 );
    Delay_ms( 300 );
    Led2 = 0;
}

void Som_Botao3()
{
    Led3 = 1;
    Sound_Play( NOTE_C, 300 );
    Delay_ms( 300 );
    Led3 = 0;
}

void Som_Botao4()
{
    Led4 = 1;
    Sound_Play( NOTE_D, 300 );
    Delay_ms( 300 );
    Led4 = 0;
}

void Som_Inicial()
{
    Led1 = 1; Led2 = 1; Led3 = 1; Led4 = 1;
    Sound_Play( 200, 100 );
    Delay_ms( 100 );
    Sound_Play( 400, 100 );
    Delay_ms( 100 );
    Sound_Play( 200, 100 );
    Delay_ms( 500 );
    Led1 = 0; Led2 = 0; Led3 = 0; Led4 = 0;
}

void Som_Perdeu()
{
    Led1 = 1; Led2 = 1; Led3 = 1; Led4 = 1;
    Sound_Play( 200, 300 );
    Delay_ms( 300 );
    Sound_Play( 150, 300 );
    Delay_ms( 300 );
    Sound_Play( 100, 300 );
    Delay_ms( 300 );
    Led1 = 0; Led2 = 0; Led3 = 0; Led4 = 0;
}

void Som_Ganhou()
{
    Led1 = 1; Led2 = 1; Led3 = 1; Led4 = 1;
    Sound_Play( 500, 100 );
    Delay_ms( 300 );
    Sound_Play( 700, 300 );
    Delay_ms( 200 );
    Sound_Play( 900, 500 );
    Delay_ms( 500 );
    Sound_Play( 800, 200 );
    Delay_ms( 200 );
    Sound_Play( 900, 500 );
    Delay_ms( 500 );
    Led1 = 0; Led2 = 0; Led3 = 0; Led4 = 0;
}

//Gera uma sequencia
void GerarSequencia()
{
unsigned semente;
char random;
char i;

    semente = (TMR1H << 8) + TMR1L;
    srand( semente );
    
    for( i=0; i < level; i++)
    {
         random = (char)(rand() % 4);
         Memoria1[i] = random;
         
         if(random == 0)
           Som_Botao1();
         else if(random == 1)
           Som_Botao2();
         else if(random == 2)
           Som_Botao3();
         else
           Som_Botao4();
           
         Delay_ms( 200 );
    }

}

//Verifica a sequencia do usuário com a
//sequencia gerado pelo pic
char VerificarSequencia()
{
char i;
     for( i=0; i < level; i++)
     {
         if( Memoria2[i] != Memoria1[i] )
          return 0;
     }
     return 1;
}

//Escreve os numeros no display
static char flag = 1;
void Write_Display()
{
char temp = level - 1;
  
  Disp1 = flag.B0;
  Disp2 = !flag.B0;
  
  if( flag.B0 )
  {
      PORTC = Display[temp/10];
  }
  else
  {
      PORTC = Display[temp%10];
  }
  
  flag.B0 = ~flag.B0;
}

//Interrupção a cada 4ms para escreve no display
void Interrupt()
{
  TMR0IF_Bit = 0;
  Write_Display();
  TMR0 = 6;
}

void main()
{
char cnt = 0;
char flags = 0;
    
    T1CON = 0x81; //habilita o timer 1
    CMCON = 0x07; //desliga os comparadores analogico
    ADCON1 = 0x06; //desliga o conversor AD
    
    TRISB = 0b11111000;
    TRISA = 0;
    TRISC = 0;
    TRISD = 0;
    PORTD = 0;
    PORTC = 0;
    
    Sound_Init( &PORTA, 0 );
    
    //Configura timer0 para gerar interrupção a cada 4ms
    OPTION_REG = 0x04;
    TMR0 = 6;
    INTCON = 0xA0;
    
    Som_Inicial();
    
    Inicio:
    while(Start);
    
    Delay_ms( 2000 );
    
    while(1)
    {
        cnt = 0;
        GerarSequencia();
        
        while(1)
        {
           if(!Botao1) flags.B0 = 1;
           else if(!Botao2) flags.B1 = 1;
           else if(!Botao3) flags.B2 = 1;
           else if(!Botao4) flags.B3 = 1;

           if(Botao1 && flags.B0)
           {
             flags.B0 = 0;
             Memoria2[cnt++] = 0;
             Som_Botao1();
           }
           
           else if(Botao2 && flags.B1)
           {
             flags.B1 = 0;
             Memoria2[cnt++] = 1;
             Som_Botao2();
           }
           
           else if(Botao3 &&  flags.B2)
           {
             flags.B2 = 0;
             Memoria2[cnt++] = 2;
             Som_Botao3();
           }
           
           else if(Botao4 &&  flags.B3)
           {
             flags.B3 = 0;
             Memoria2[cnt++] = 3;
             Som_Botao4();
           }
           
           if( cnt == level )
             break;
        
        }
        
        if( VerificarSequencia() )
        {
           level++;
                      
           if(level == NIVEIS)
           {
              level = 1;
              Som_Ganhou();
              goto Inicio;
           }
           
        }
        else
        {
           level = 1;
           Som_Perdeu();
           goto Inicio;
        }
        
        Delay_ms(1000);
    }
}

13 comentários:

  1. Bacana esse jogo do tempo que era menino.
    Um Bom Dia para Você.

    ResponderExcluir
  2. Oi possivel de ter um codico em mikroC v.8 ?

    ResponderExcluir
  3. Ou deixar uma verçao pra download
    Obrigado

    ResponderExcluir
  4. Eu compilo no mplabx e não consigo habilitar a biblioteca sound para fazer o Genius. Onde posso encontrar. Obrigado.

    ResponderExcluir
  5. Boa tarde. Eu copiei e colei este código para o MikroC e fiz o teste no Proteus 8. Funcionou, exceto por uma desordem nos LED's. Exemplo: quando inicio o programa ele pisca o LED verde, daí pressiono o botão correspondente do LED. Até aí ok. Mas quando ele passa pro nível dois, em vez dele gerar a sequência com o primeiro LED, no caso o verde e algum outro, não, ele gera dois cores diferente da primeira sequência. Exemplo: azul e amarelo. Sendo que deveria ser verde, que doi o primeiro gerado e outra cor aleatória. Espero que entendam o problema. E gostaria muito de uma ajuda. Conto com vocês. E ótimo tutorial!!

    ResponderExcluir
  6. Sou iniciante em programação e microcontroladores pic! como faço para Habilitar as bibliotecas Sound e C_Stdlib, para o pic16f628a? Obrigado.

    ResponderExcluir