Cuente el número de veces que se presiona un botón con ATmega

1

Tengo que contar el número de veces que se presiona un botón en 5 segundos y mostrarlo en una matriz de LED.

Si el número de veces que se hace clic en el botón es 1, entonces el último LED debería brillar ( 0001 - valor binario de 1). De manera similar, para 2 clics, el tercer LED debería brillar ( 0010 - binario de 2).

Pero cuando intento esto, siempre obtengo la salida para el caso 0 , sin importar cuántas veces haga clic en el botón.

¿Cuál es el problema?

#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>

int extratime=0;
int num_presses=0;


int main(void)
{
  DDRD = 0b11111111;
  PORTD = 0b00000000;
  DDRB = 0b11110000;
  PORTB = 0b00000000;
  char button_state;   


  TCCR1B = (1 << WGM12);
  OCR1A = 15625;
  TIMSK = (1 << OCIE1A);
  sei();
  TCCR1B |= (1 << CS12) | (1 << CS10);

  while(1)
  {
    if (bit_is_clear(PINB, 0)) //button is pressed
    {     
      if (button_state==0) //was previously not pressed)
      {
        num_presses++;
      }
      button_state=1;
    }
    else 
    {
      if (button_state==1) //was previously pressed
      {

      }
      button_state=0;
    } 


  }
}

ISR(TIMER1_COMPA_vect)
{
  extratime++;
  if(extratime == 5)
  {           
    switch(num_presses)
    {
             case 0: PORTD = 0b10010000;
                     _delay_ms(10000);
                     break;
             case 1: PORTD = 0b10000000;
                      _delay_ms(10000);
                      break;
              case 2: PORTD = 0b01000000;
                      _delay_ms(10000);
                      break;
              case 3: PORTD = 0b11000000;
                      _delay_ms(10000);
                      break;
              case 4: PORTD = 0b00100000;
                      _delay_ms(10000);
                      break;
              case 5: PORTD = 0b10100000;
                      _delay_ms(10000);
                      break;
             default: PORTD =0b11110000;
                     break;  
    } 
    extratime = 0;  
    num_presses = 0;
  }

}

este es mi nuevo código, incluso esto no funciona ...     #incluir     #incluir     #incluir

int extra_time=0;
int num_presses=0;

int main(void)
{
    DDRD = 0b11111111;
    PORTD = 0b10000000;
    DDRB = 0b00000111;
    PORTB = 0b00000000;
    char button_state;  

    TCCR1B = (1 << WGM12);
    OCR1A = 15625;
    TIMSK = (1 << OCIE1A);
    sei();
    TCCR1B |= (1 << CS12) | (1 << CS10);

    while(1)
    {
      if (bit_is_clear(PINB, 0)) //button is pressed
    {    
       if (button_state==0) //was previously not pressed)
     {
    num_presses++;
     }
     button_state=1;
    }
      else
     {
       if (button_state==1) //was previously pressed
     { 

     }
      button_state=0;
     }

     if (TCNT1 >= 15625)
    {
      if (extra_time == 5)
       {
         switch(num_presses)
       {
           case 0:
                 PORTD = 0b11100000; 
                 break;
           case 1:
                 PORTD = 0b00100000;
                 break;
           case 2:
                 PORTD = 0b01000000;
                 break;
           case 3:
                 PORTD = 0b01100000;
                 break;
           default:
                 PORTD = 0b10100000 ;
                 break;
          }
         extra_time = 0;
     }
     else
     {
         ++extra_time;
     }
     TCNT1 = 0;
     }
   }
  }

Por favor ayuda ... Tengo que presentar este proyecto mañana.

    
pregunta user3264385

1 respuesta

1

Si siempre obtiene el caso de cero, entonces parece que su microcontrolador no se registra cuando se presiona el botón. Puede haber muchas razones y sin un circuito real, es difícil decir exactamente qué podría estar mal. Le sugiero que revise su circuito y vea si al presionar un botón realmente cambia el voltaje (reemplace la MCU con un solo LED y cuando presione el botón, debería apagarse)

Y cuando esté funcionando, habrá un problema con el botón de rebote. Si no lo está publicando con hardware, en la imagen de abajo puede ver que hay un pequeño período de tiempo en el que los valores saltan entre 0 y 1 lógicos, por lo que deberá usar los temporizadores internos para retrasar el registro del botón o registrar un botón presione después de cierta cantidad de muestras (hay una gran cantidad de bibliotecas de software de rebote en Internet)

Tambiéncompiléunprogramamodificadoenbitsparamega32de1MHzconLCD,elcódigosepuedever aquí . El programa, que funciona según lo previsto, registra una serie de clics de botón y los imprime. Se utilizó una configuración de pull-up (como sugiere su código). Dado que no hay debouncing de hardware, a veces registra unos pocos clics más de los que he presionado. Así que por ahora, COMPRUEBE su circuito, luego DOBLE VERIFIQUE.

ACTUALIZADO

Código de ejemplo (compilado con atmel studio 6.2)
Utilizado con el circuito de abajo. Tenga en cuenta que esta configuración tiene botones que rebotan y puede registrar más pulsaciones de las que realmente presionó.

Si esta configuración no funciona, entonces es posible que la MCU esté defectuosa (pero es poco probable), así que de nuevo, DOBLE REVISE su circuito.
Ver si todas las conexiones son correctas;
Vea si su cableado (diodos, interruptores, etc.) es correcto;
Ya que no puede cargar su circuito por algún motivo, si está usando una fuente de reloj externa, vea si está conectada correctamente y si los bytes de los fusibles están configurados (luego configure F_CPU a su frecuencia de reloj externo)
Evite usar ciclos de gran retraso, use para (;;) si debe hacerlo.
Y nuevamente, he dado un ejemplo del circuito con el cual el código funciona lo suficientemente bien (sin contar la falta de software del software) y si hay algo diferente en su configuración, DEBE PROPORCIONAR información adicional si desea más ayuda.

    
respondido por el elent

Lea otras preguntas en las etiquetas