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 e 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);
}
}



Bacana esse jogo do tempo que era menino.
ResponderExcluirUm Bom Dia para Você.
onde fica o positivo e o negativo
ResponderExcluirProcura no datasheet do CI.
ResponderExcluirqual o compilador que foi utilizado?
ResponderExcluirMikroC PRO PIC v6.0
Excluirobrigado
Excluirteria como eu habilitar as outras portas que não estão sendo usadas para outra coisa, mais especificamente 4 portas
ExcluirOi possivel de ter um codico em mikroC v.8 ?
ResponderExcluirOu deixar uma verçao pra download
ResponderExcluirObrigado
Eu compilo no mplabx e não consigo habilitar a biblioteca sound para fazer o Genius. Onde posso encontrar. Obrigado.
ResponderExcluirBoa 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!!
ResponderExcluirOla onde coloco a alimentação 5v e gnd no PIC
ResponderExcluirSou iniciante em programação e microcontroladores pic! como faço para Habilitar as bibliotecas Sound e C_Stdlib, para o pic16f628a? Obrigado.
ResponderExcluir