Ir ao conteúdo
  • Cadastre-se

Varredua de botões por Interrupção PIC16F883


Posts recomendados

Bom dia, estou desenvolvendo um código para incrementar a contagem em um display de 7 segmentos a cada vez que o botão B1 for pressionado, para otimizar meu código eu decidi fazer a varredura dos botões através das interrupções, então em um tempo de aproximadamente 20ms eu testo meu botão B1 através do estouro do TMR0... porém como nunca é do jeito que a gente quer meu código não esta rodando perfeitamente no protheus, alguém sugeri o motivo ? Segue código comentado...

 

unsigned char catodo, cont = 0x00;       // variaveis auxiliares
 unsigned char segmento[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};   // vetor para display 7seg

 void interrupt ()
 {
 if (T0IF_bit)                                      // testa flag de estouro tmr0
 {
  T0IF_bit = 0;                                     // limpa flag
  TMR0 = 0xA0;                                      // inicia tmr0 em   160

 if (B1 == 0)                                       // se b1 pressionado...
  {
  cont ++;                                          // cont ++
  Delay_ms(150);
  }
  }
  }


 

void main ()
{
OPTION_REG =   0b10000110;      // Desabilitando resistores de puldow, oscilador interno, prescaller 1:256
TMR0  = 0xA0;                   // inicia tmr0 160
INTCON.GIE = 1;                 // habilita interrupçao global
INTCON.PEIE = 1;                // habilita interrupçao por perifericos internos
INTCON.T0IE = 1;                // habilita interrupçao por estouro timer 0


TRISE = 0b00001000;
TRISC = 0b00000000;
TRISB = 0b00000000;
PORTB = 0b00000000;
PORTC = 0b00100000;
PORTE = 0b00001000;

   while (1)
{

    catodo = segmento [cont];         // atribui o vetor segmento com o parametro cont há variavel catodo
    PORTB = catodo;
     if (cont > 9)                    // limite de contagem ate 9
    {
    cont = 0;
    }

}
}

Link para o comentário
Compartilhar em outros sites

Tá não entendi muito bem o seu código. Tem um erro ai no mínimo:

TRISB = 0b00000000; isso define todas as portas como saída e você disse que B1 é uma das portas. se B1 é entrada* então ficaria TRISB = 0b00000010;

 

Se você olhar no datasheet do teu mic e olhar no PORTB registradores você vai ver que terá que alterar ANSELH = 0; ou os bits que você que sejam apenas entra e saída (você coloca isso no void principal). Isso se deve novamente ao fato do PORTB poder ser configurado como entrada e saída ou analógico.

 

Se ainda tiver mais problema no teu código avisa que posso dar uma outra olhada.

Link para o comentário
Compartilhar em outros sites

@Bommu Perneta  na verdade eu não copiei a parte das diretivas ''B1'' é na verdade RB3_bit, e eu não entendi muito bem o lance sobre ANSELH, este registrador não configura apenas os pinos do PORTA se eles sarão analógicos ou digitais ?

adicionado 1 minuto depois

@Isadora Ferraz poderia ser mais especifica como eu deveria mudar minha logica ??

Link para o comentário
Compartilhar em outros sites

Que vê dá procura na net pelo datasheet do mesmo, dá um ctrl+F no pdf e procurar por PORTB vai indo até encontrar a parte de dos registradores, e procura por essa palavra por lá ^^ você pode fazer um exemplo simples no proteus

 

Pagina 49 do PDF do datasheet


 

Citação

 

"

3.4.1

ANSELH REGISTER

The ANSELH register (Register 3-4) is used to

configure the Input mode of an I/O pin to analog.

Setting the appropriate ANSELH bit high will cause all

digital reads on the pin to be read as ‘

0

’ and allow

analog functions on the pin to operate correctly.

The state of the ANSELH bits has no affect on digital

output functions. A pin with TRIS clear and ANSELH

set will still operate as a digital output, but the Input

mode will be analog. This can cause unexpected

behavior when executing read-modify-write

instructions on the affected port."

 

 

Página 50 do datasheet


 

Citação

 

"ANSELH: ANALOG SELECT HIGH REGISTER

bit 7-6

Unimplemented:

Read as ‘

0

bit 5-0

ANS<13:8>

: Analog Select bits

Analog select between analog or digital function on pins AN<13:8>, respectively.

1

= Analog input. Pin is assigned as analog input

(1)

.

0

= Digital I/O. Pin is assigned to port or special function.

Note 1:

Setting a pin to an analog input automatically disables the digital input circuitry, weak pull-ups, and

interrupt-on-change if available. The corresponding TRIS bit must be set to Input mode in order to allow

external control of the voltage on the pin.

"

 

 

Abaixo Eu só comentei teu código

//// unsigned char catodo, cont = 0x00;       // variaveis auxiliares
///unsigned char segmento[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};   // vetor para display 7seg
/*
 void interrupt ()
 {
 if (T0IF_bit)                                      // testa flag de estouro tmr0
 {
  T0IF_bit = 0;                                     // limpa flag
  TMR0 = 0xA0;                                      // inicia tmr0 em   160

 if (B1 == 0)                                       // se b1 pressionado...
  {
//  cont ++;                                          // cont ++
  Delay_ms(150);
  }
  }
  }

  */


void main ()
{
/*
OPTION_REG =   0b10000110;      // Desabilitando resistores de puldow, oscilador interno, prescaller 1:256
TMR0  = 0xA0;                   // inicia tmr0 160
INTCON.GIE = 1;                 // habilita interrupçao global
INTCON.PEIE = 1;                // habilita interrupçao por perifericos internos
INTCON.T0IE = 1;                // habilita interrupçao por estouro timer 0
  */

TRISE = 0b00001000;
TRISC = 0b00000000;
TRISB = 0b00000010;
PORTB = 0b00000000;
PORTC = 0b00100000;
PORTE = 0b00001000;

ANSELH = 0;       // retirar do analog.

   while (1)
{

  if (PORTB.B1==1){PORTB.B2=1; delay_ms(500);}
   PORTB.B2=0;
/*  PORTB.B0=0;
   delay_ms(500);
  PORTB.B0=1;
   delay_ms(500);
   PORTB.B2=1;
  */

}
}

Se você você retirar esse comando o programa que lé o botão no Proteus não vai funcionar, a lógica pelo menos.

 

Capturar.PNG.faace9f1ea5c54b26e5e21f20f66108d.PNG

 

adicionado 1 minuto depois

Ta uma ***** a passagem do texto, melhor ler no datasheet uhahuauhahu

adicionado 5 minutos depois

http://ww1.microchip.com/downloads/en/DeviceDoc/41291B.pdf

Link para o comentário
Compartilhar em outros sites

meu codigo esta assim agora, esta funcionando normalmente no protheus a cada pressionada do botão e incrementa um valor no display, porém o led que esta ligado ao pino RB7 nunca acende, este pino independente do de qualquer coisa so esta ficando em nivel baixo... Segue o codigo 

 

 

#define B1 RE3_bit


 unsigned char catodo, cont = 0x00;       // variaveis auxiliares
 unsigned char segmento[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};   // vetor para display 7seg

 void interrupt ()
 {
 if (T0IF_bit)                                      // testa flag de estouro tmr0
 {
  T0IF_bit = 0;                                     // limpa flag
  TMR0 = 0x00;
  if (B1 == 0)
 {
   cont ++;
   Delay_ms(250);


 }                                    // inicia tmr0 em   160
 }
 }


 

void main ()
{
OPTION_REG =   0b10000111;      // Desabilitando resistores de puldow, oscilador interno, prescaller 1:256
TMR0  = 0x00;                   // inicia tmr0 em 0
INTCON.GIE = 1;                 // habilita interrupçao global
INTCON.PEIE = 1;                // habilita interrupçao por perifericos internos
INTCON.T0IE = 1;                // habilita interrupçao por estouro timer 0


TRISE = 0b00001000;
TRISB = 0b00000000;
PORTB = 0b00000000;
PORTE = 0b00001000;
ANSELH = 0;
 while (1)
{

    catodo = segmento [cont];         // atribui o vetor segmento com o parametro cont há variavel catodo
    PORTB = catodo;
     if (cont > 9)                    // limite de contagem ate 9
    {
    cont = 0;
    }

}
}

Link para o comentário
Compartilhar em outros sites

É esse linha aqui

PORTB = catodo;

Ele tá modificando essa porta para 0 . Ele está no while, fora do botão e repetindo toda hora... ou seja vai ficar zero todo o tempo..

adicionado 14 minutos depois

unsigned char segmento[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67};

 

de hexadecimal binário

0xF3 = 00111111

0x06= 00000110

0x5b= 01011011

0x4f= 01001111

0x66=01100110

0x6d=01101101

0x7d=01111101

0x07=00000111

0x7f=01111111

0x67=01100111

 

Sendo que da esquerda para direita cada digito do binário que são 8 nesse caso são as porta do PORTB segundo o código, onde ficamos respectivamente B7,B6,B5,B4,B3,B2,B1,B0 e note que todo tempo o primeiro que seria o B7 fica todo tempo em 0, logo desligado. Está ai uma explicação.

 

@Joao Fabri

 

 

Link para o comentário
Compartilhar em outros sites

@Bommu Perneta nossa é verdade, e no meu hardware sem querer eu estava usando o pino G do display no pino RB7 invés de RB6 por isso não ascendia... Cara agora eu tenho uma outra duvida sobre esse meu mic, eu acompanho wr kits no youtube e la ele sempre desliga os comparadores qundo não vai usar através do comando CMCON = 0x07 mas quando vou tentar colocr isso no meu codigo ele da erro, sera que meu mic em questão usa um registrador diferente para tratar os compardores ?? Obrigado

Link para o comentário
Compartilhar em outros sites

Depende da versão que você usa do teu mikroC Pro...por exemplo, a versão que ele usa parece bem diferente da minha, muitos registradores parecem diferentes do que uso, se você for desativar um "com nome semelhante" teu proteus ou mic não funciona... então tem que ser o nome exato que ele fala, se não tiver o mesmo nome exato você pode tentar adaptar e trocar um, desligar outro e vai vendo o que funciona no seu caso.

adicionado 0 minutos depois

ah... pelo que vejo o curso dele é bom.

adicionado 4 minutos depois

Ah não se esqueça que precisa alimentar o pic, dependendo pode colocar cristal e tal. ^^ deixar em alto com um resistor de 10k o reset e por ai vai... tudo pode dar erro ^^

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
13 horas atrás, Joao Fabri disse:

como eu deveria mudar minha logica ??

Tentemos...

 

Pelo que entendi você lê o status do botão a cada 20mS usando o timer só pra isso. Isso não é necessário. Use o timer pra algo mais nobre e coerente com seu nome. Se você programar uma interrupção por mudança de estado da entrada, já lhe é suficiente. Hás de ler o datasheet pra ver como programar o pino pra isso.

 

Eis o modo que "simula" uma interrupção por sw por mudança de estado. É auto explicativo pra um programador mediano em c
 

while (1)
{
    catodo = segmento [cont];         // atribui o vetor segmento com o parametro cont há variavel catodo
    PORTB = catodo;
while(B1);while(!B1); //<<===
cont++;
     if (cont > 9)                    // limite de contagem ate 9
    {
    cont = 0;
    }
}

No proteus deve funcionar. Na prática, hás de ser apresentado ao termo debouncing

  • Curtir 1
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...