Ir ao conteúdo
  • Cadastre-se

PROBLEMA PIC 16F876A + TECLADO POR VARREDURA + 3 DISPLAYS 7 SEGMENTOS


Ir à solução Resolvido por .if,

Posts recomendados

Boa Tarde Pessoal,

Estou desenvolvendo meu projeto de TCC, que consiste num contador eletrônico utilizando um PIC 16F876A.

Utilizo a estrutura por varredura e mascara com numeração hexadecimal no display, e também um teclado por varredura.

 

Acontece que na minha simulação no ISIS PROTEUS o programa funciona redondo. Mas quando gravo no PIC, existe algum tipo de interferência nos botões e vários erros acontecem.

Quando aperto o botão referente ao número 7 o pino B do Display de 7 segmentos não aparece, quando aperto 4 também. Quando aperto 9, o PIC se perde em algum LOOP infinito e apaga os Displays e só sai quando aperto o botão referente ao 0, mostrando "90" nos displays.

 

Alguém tem alguma ideia para me ajudar? Sou novo em programação PIC, mas não tenho ideia se é problema de Hardware ou Software.

 

Talvez algum pino do PIC que deixei flutuando? Pode gerar algum tipo de ruido?

 

Agradeço qualquer tipo de ajuda!

Segue meu Programa.

#include <16F876A.h>#FUSES NOWDT                    //No Watch Dog Timer#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)#FUSES PUT                      //Power Up Timer#FUSES NOPROTECT                //Code not protected from reading#FUSES NODEBUG                  //No Debug mode for ICD#FUSES NOBROWNOUT               //No brownout reset#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O#FUSES NOCPD                    //No EE protection#FUSES NOWRT                    //Program memory not write protected//#FUSES RESERVED                 //Used to set the reserved FUSE bits#use delay(clock=4000000)//Definição das saidas dos displays#define UNIDADE  PIN_A2#define DEZENA   PIN_A1#define CENTENA  PIN_A0//definicao da entrada dos botoes (VARREDURA DO TECLADO)#define COLUNA_1 PIN_C0#define COLUNA_2 PIN_C1#define COLUNA_3 PIN_C2#define LINHA_1  PIN_C3#define LINHA_2  PIN_C4#define LINHA_3  PIN_C5#define LINHA_4  PIN_C6//definicao da saida do buzzer(som), motor e sensor#define SOM      PIN_C7#define MOTOR    PIN_A5#define SENSOR   PIN_A3   //variaveis            //    "0"  "1"   "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9"   unsigned char ucMascara[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //mascara com os numeros de 0 a 9 hexadecimal, varial de 8 bits (0 a 255) sempre positiva   long int uiTecla=0;             //variavel do contador      long int uiValor=0;            //variavel para mostrar o valor no display   long int uiTotal=0;   long int liRepete=0;   unsigned int uiFlag_tecla=0;   unsigned int i = 0;   unsigned int liga = 0;   unsigned int tempo = 1;   void apita (void){   //delay muito baixo nem vai ter como ouvir o bip    //testar o tempo   //output_high(SOM);   //delay_ms(tempo);   //output_low(SOM);}void desaperta (void){   tempo=1;   while(input(COLUNA_1)||(input(COLUNA_2))||(input(COLUNA_3)))   {//      apita();  //enquanto o botao estiver apertado vai ficar apitando   }   }void display(void){   uiValor=uiTotal;   output_b(ucMascara[uiValor%10]);   output_high(UNIDADE);   delay_ms(5);   output_low(UNIDADE);   uiValor/=10;   //mostra o valor da dezena   output_b(ucMascara[uiValor%10]);   output_high(DEZENA);   delay_ms(5);   output_low(DEZENA);   uiValor/=10;   //mostra o valor da centena   output_b(ucMascara[uiValor%10]);   output_high(CENTENA);   delay_ms(5);   output_low(CENTENA);}void limpa_pinos (void){   //zera linhas   output_low(LINHA_1);   output_low(LINHA_2);   output_low(LINHA_3);   output_low(LINHA_4);   //zera colunas   output_low(COLUNA_1);   output_low(COLUNA_2);   output_low(COLUNA_3);}testa_botao (void){     limpa_pinos();   output_high(LINHA_1);   //testa primeira linha (7  8  9)   if(input(COLUNA_1)&&(uiFlag_tecla==0))// testa coluna 1         {            desaperta();            uiFlag_tecla=1;            return(7);         }   if(input(COLUNA_2)&&(uiFlag_tecla==0)) //testa coluna 2         {            desaperta();            uiFlag_tecla=1;            return(8);         }   if(input(COLUNA_3)&&(uiFlag_tecla==0)) //testa coluna 3         {            desaperta();            uiFlag_tecla=1;            return(9);         }   limpa_pinos();   output_high(LINHA_2);   //testa segunda linha (4 5 6)   if(input(COLUNA_1)&&(uiFlag_tecla==0))// testa coluna 1         {            desaperta();            uiFlag_tecla=1;            return(4);         }   if(input(COLUNA_2)&&(uiFlag_tecla==0))         {            desaperta();            uiFlag_tecla=1;            return(5);         }   if(input(COLUNA_3)&&(uiFlag_tecla==0))         {            desaperta();            uiFlag_tecla=1;            return(6);         }     limpa_pinos();   output_high(LINHA_3);   //testa segunda linha (7 8 9)   if(input(COLUNA_1)&&(uiFlag_tecla==0))// testa coluna 1         {            desaperta();            uiFlag_tecla=1;            return(1);         }   if(input(COLUNA_2)&&(uiFlag_tecla==0))         {            desaperta();            uiFlag_tecla=1;            return(2);         }   if(input(COLUNA_3)&&(uiFlag_tecla==0))         {            desaperta();            uiFlag_tecla=1;            return(3);         }limpa_pinos();   output_high(LINHA_4);   //testa segunda linha (cancel 0 enter)   if(input(COLUNA_1)&&(uiFlag_tecla==0))// testa coluna 1         {            desaperta();            uiFlag_tecla=1;            return(10);         }   if(input(COLUNA_2)&&(uiFlag_tecla==0))         {            desaperta();            uiFlag_tecla=1;            return(0);         }   if(input(COLUNA_3)&&(uiFlag_tecla==0))         {            desaperta();            uiFlag_tecla=1;            return(11);         }          // se nenhuma tecla for pressionada retorna o valor 20      return(20);  }void gira_motor (void){   output_high(MOTOR);   liRepete = uiTotal;   while (uiTotal>0)      {         if(input(SENSOR))            {               while (input(SENSOR))               {                  delay_ms(1);               }            uiTotal--;            }      display();      }   output_low(MOTOR);}void main(){   while(true)   {      if (liga==0)         {         tempo=100;         apita();         delay_ms(100);         apita();         tempo=1;         liga=1;        }      uiTecla = testa_botao();      if ((uiTecla!=20)&&(uiTecla!=10)&&(uiTecla!=11))         {         if ((i==0)&&(uiTecla!=0))            {            uiTotal = uiTecla;            uiFlag_tecla=0;            i++;            }         else if (i==1)            {            uiTotal = (uiTotal*10) + uiTecla;            uiFlag_tecla=0;            i++;            }         else if (i==2)            {            uiTotal = (uiTotal*10) + uiTecla;            uiFlag_tecla=0;            i++;            }         }      else if ((uiTecla==10)&&(uiTotal>0))         {         uiTotal = 0;         uiFlag_tecla=0;         i=0;         }      else if (uiTecla==11)         {         if ((uiTotal==0)&&(liRepete!=0))            uiTotal=liRepete;         else if (uiTotal!=0)            gira_motor();         uiFlag_tecla=0;         i=0;         }      else      uiFlag_tecla=0;      display();     }}
Link para o comentário
Compartilhar em outros sites

  • Membro VIP

pino 1 reset está com cap pro gnd e 10k pro vcc? vcc=regulado? tem capacitor de desacoplamento? correntes parasitas?=corrente dos displays não fluir pelo gnd mc. etc?

 

de presente. rotina de beep com duração e tom:

void beep(unsigned int duracao, unsigned char tom){unsigned char tmp;while(duracao --)   {   tmp=tom;   RB0^=1;   while(tmp--);   }}

ex.: beep(5000,30); //obs: freq depende da frequencia do mc. interrupt pode zoar o bip

Link para o comentário
Compartilhar em outros sites

Desculpe não sou um Expert, talvez tenha feito algo errado.

 

Estou obtendo + 5V  e GND de um Circuito LM7805 ligados com dois capacitores para filtro (1000 microF e 10microF). Estes Seriam os filtros ideais?

 

OS Pinos estão assim ligados:

 

PINO 1 - +5V direto

 

PINO 20 - +5V direto

 

PINOS 18, 19, 6, 8 e 28 = GND

 

PINOS 9 e 10 = Ligados em um Cristal de 4Mhz e capacitores de 22pF

 

Estas ligações estão corretas? Liguei os pinos 28 e 18 para não deixalos flutuando, porque achei que entraria ruido.

Obrigado desde já.

Obrigado também pela paciência

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Sem problemas. Paciência é meu sobrenome. além do mais você disse palavras mágicas. Coisa rara...vamos ver...
-pino 1 no + 5. tente substituir por um resistor no +5 e um capacitor 100nF pro gnd
-7805= correto. 1000u na entrada e 10u na saída=ok
-ligue apenas os pinos VCC no +5 e VSS no gnd. Para não flutuar os outros, basta deixá-los como saída. TRISB=0x00 p.ex. Os que tiver na dúvida, ligue um resistor de 1K pro gnd e não direto. Só por segurança.
-4Mhz tente usar XT nos fusíveis. e deixe o BROWNOUT ligado
-Não sei como está seu circuito (se protoboard p.ex.) mas ligue os catodos comuns (se for o caso) com um fio direto no terminal do meio (gnd) do 7805. Isso faz com que não haja corrente parasita passando pelo gnd do mc
-perdão por não analisar seu fonte 100%. Aguarde alguma boa alma programadora ccs pra avaliar p você ok? Uma coisa que posso dizer é que existe maneira mais otimizada para acionar display e ler teclado 4x3 p.ex. usando interrupção. Além do mais se for mais de um display. Recentemente publiquei uma maneira manêra de fazê-lo. Sorry... não ccs.

bfds pro 6 tudo

Link para o comentário
Compartilhar em outros sites

Bom dia..

Desculpe a demora pra responder, comprei novos componentes e montei uma placa novinha, e ainda assim não funcionou.

Primeiramente não liguei o teclado, e os valores do display se mostravam corretos, mas quando ligo o teclado, a varredura não funciona direito.

Você conhece algum outro jeito de ler teclado 4x3?

Agradeço qualquer ajuda

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
  • Solução

bom, não vi nos meus fontes mas criei e testei isso. Não é varredura. é uma leitura meio que direta de 2 nibbles. e mais rápida. é fácil de entender e nem precisa de muita explicação. A não ser que insista muito muito muito meesssmo.
sua matriz de teclas em no PORTB. sorry, se quiser vai ter que converter a maneira de acesso direto ao hw do meu compilador pra maneira do seu

#include <pic.h>// ************************ configuração ***********************__CONFIG(FOSC_XT & PWRTE_ON & LVP_OFF & DEBUG_OFF & WDTE_OFF & BOREN_ON);   //876aunsigned char leteclado(){unsigned char tecla;TRISB=0b11110000;PORTB=0b11110000;tecla=PORTB;TRISB=0b00001111;PORTB=0b00001111;tecla|=PORTB;return tecla;}//***************************************************//*********************************************************void main(void){TRISC=0x00;for(;{PORTC=leteclado();//só pra eu ver no simulador}}

no simulador conseguimos ver o registro PORTC variando de acordo com as teclas. Notei que:

*=0x6e#=0x3e1=0x672=0x573=0x37..etc

p.ex., no seu program basta fazer:

#define _aste 0x6e#define _cerca 0x3e#define _1 =x67#define _2 0x57#define _3 0x37..etc

e no seu fonte faça o que quiser p.ex.

tec=leteclado();if (tec==_aste) ...if (tec==_1) ...if (tec==_2) ...

ou

switch (tec){case _1 façaisso(); break;case _2 façaaquilo(); break;//...etc}

abç

 

post-528815-0-97339400-1413305203_thumb.

Link para o comentário
Compartilhar em outros sites

Prezado colega carlosporto, vou tentar me juntar com a colega Isadora Ferraz em ajudá-lo.

Esse problema costuma ocorrer também em razão do boucing dos botões. É que, no apertar e soltar dos botões, há aquele "repique" dos contatos que, para o uC acaba representando vários apertos no mesmo botão (como o proteus não simula isso, o "erro" não aparece na simulação). E, penso que o seu teclado pode estar apresentando este fenômeno. Meu conselho é que você, além do que a Isadora já apresentou para a parte eletrônica, faça instruções de deboucing. A lógica que sugiro é descrita pelo seguinte algoritimo:

 

- botão apertado.

- aguarda tempo (uns 15 a 25ms bastam - depende da qualidade do botão/teclado).

- passado esse tempo, se o botão estiver apertado, executa a ação.

 

Trata-se mesmo de uma ideia, porque o seu teclado está trabalhado por varredura, então você terá que pensar a solução mais prática).

Em termos de código, seria algo parecido com isso:

if(botao = 1) // se o botão for apertado {   delay_ms(25); //aguarde 25ms     if(botão = 1) //se o botão continua apertado       {          // executa a ação        }

Aqui no CH já apareceram boas informações sobre o tema. Aqui tem uma delas:

 

http://forum.clubedohardware.com.br/forums/topic/654410-debouncing-para-iniciantes/

 

Bons trabalhos.

 

Adriano.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Muito bem lembrado amigo @advtec ! Como adição pra redução do debouncing, sugiro um capacitor em paralelo com os botões. xute 100nF

Me lembro que fiz algo assim pra difenciar ruído do botão:

tmp=0;while (!pino_de_entrada) tmp++;if (tmp>1000)  botao=ok;

ou algo próximo disso... assim não perco tempo com delay. ... literalmente

abç

Link para o comentário
Compartilhar em outros sites


Boa Tarde Pessoal, Muito Obrigado pela ajuda, a parte fisica esta funcionando perfeitamente agora.

Porém ainda estou tendo dificuldades para implementar uma varredura 4x3 como a @Isadora Ferraz me passou o código, você poderia me explicar basicamente o que o código faz? Como é para o meu TCC, vou ter que saber explicar isso depois.

 

Estou tendo dificuldades em transformar o código para o meu compilador CCS, segue o que consegui.

   unsigned char tecla;   set_tris_c(0b11110000);   output_c(0b11110000);      tecla=output_c; //essa função não é possivel no CCS   set_tris_c(0b00001111);   output_c(0b00001111);   tecla|=output_c; //Não entendi o que essa função faz.   return tecla;

Obrigado novamente, vocês são muito legais ;)

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Claro amigo. Afinal estamos aqui pra isso
Note que a metade da porta é entrada e a outra, saída. O que fazemos é transferir os bits 0 da saída para a entrada se tiver contato entre eles (tecla pressionada)

   set_tris_c(0b11110000); //ok   output_c(0b11110000); //ok   tecla=input_c;//? sorry. não conheço o ccs. veja no help dele como LER o valor da porta.   //Lê 4 bits da direita. Só isso.    set_tris_c(0b00001111); //ok   output_c(0b00001111); //ok   tecla|=input_c; //Mesma coisa: leitura de porta. na "tecla" já estão os bits da direira, lembra?   //Agora faço uma soma OR com os 4 bits da esquerda pra compor o byte (8bits) completo     return tecla;

Alguma porta tem pullup interno e nem precisa dos resistores.

Sucessos!

Link para o comentário
Compartilhar em outros sites

Boa Tarde novamente, sei que estou sendo chato...

meu código agora ficou asssim:

unsigned char leteclado (){   unsigned char tecla;   set_tris_c(0b11110000);   output_c(0b11110000);   tecla=input_c();   set_tris_c(0b00001111);   output_c(0b00001111);   tecla|= input_c();   return (tecla);}void main(void){   set_tris_b(0x00);   while(true)   {   output_b(leteclado());   }}

Mas estou monitorando o PORTB no simulador e o valor não muda.

Você colocou alguma condição especial no Wach Window do seu simulador?

 

Alguma boa alma que programa com o CCS para me ajudar?

Todo mundo usa o MikroC? devo eu mudar meu simulador?

 

Obrigado novamente, e boa noite

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

no simulador você colocou os pullups? pullup e não resistor. Seu portb está como saída?

watch=normal

 

no meu caso leio direto o registro da porta da tecla. no seu é função (um dos motivos que me faz não querer bem o ccs). você tem que ver DIREITINHO o que ela faz. De repente este treco tá zoando o TRIS.

abç

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...