Número de conteo de pulsación de botón por interrupción externa

2

Es un requisito que cuente el número de pulsaciones de botón por externo o por cualquier otra interrupción.

Entonces, cuando uso la interrupción externa para incrementar el contador en 1, a veces se incrementa en 2 o 3 debido al rebote. ¿Alguien puede decirme cómo contar con precisión en este caso?

void Handle_PB() // my ISR called by pushbutton press falling edge
{
    pb++;
    if(pb>3)
    {  num1=1;
    }
    if(pb>4)
    {  num2=1;
       pb=0;
    }
} 

pb es el contador de pulsadores. y num1 y num2 son indicadores.

Entonces, después de presionar 4 veces el botón, quiero hacer alguna otra tarea. Sencillamente, después de presionar 5 veces el botón, quiero hacer otra tarea. por lo que es importante contar el número exacto de una pulsación de botón. Conozco el principio de rebote. Pero, ¿dónde puedo colocar este código de demora de rebote ya que está impulsado por interrupciones?

    
pregunta litun bls

3 respuestas

2

1) Es mejor, si puede lidiar con el debouncing en el propio hardware. Si es posible, coloque un condensador apropiado en el pin de interrupción a tierra.

2) En el software puedes tratar como: (Suponiendo que el rebote puede durar hasta 50 s)

void my_interrupt_handler()
{
 interrupt_time = currentmilliseconds();

 if (interrupt_time - last_interrupt_time > 50) 
 {
   press++;
   last_interrupt_time = interrupt_time;
 }

}

last_interrupt_time tiene 0 valor inicial. El código incrementa el valor de la primera pulsación. Pero no se incrementará durante 50 ms, sin importar cuántas interrupciones de botón se produzcan entre ellas debido al rebote. Esto funcionará de manera eficiente solo si el microcontrolador admite interrupciones dentro de interrupciones, de lo contrario tiene la posibilidad de perder la interrupción por desbordamiento del temporizador.

3) Otro método es simplemente agregar un retraso de 50 ms después de incrementar presionar . Funciona. Pero no es un buen método.

4) Otra idea, mediante el uso de una variable de marca:

void my_interrupt_handler()
    {     
      if (flag == 0)
         { 
          press++;
          flag = 1 
         }
    }
La bandera

es una variable volátil compartida entre main () e ISR. El código se escribe en main () de manera que se reinicializa la marca de nuevo a 0 solo después de contar 50 ms. Así que esto es como desactivar las interrupciones de los botones durante 50 ms. De todos modos, los seres humanos no pueden presionar más rápido que eso.

    
respondido por el MITU RAJ
1

Debes hacer lo que se llama debouncing . Hay muchas maneras, y seguramente hay mucho escrito al respecto.

El método que normalmente utilizo es no considerar un nuevo estado válido hasta que la entrada haya estado en ese estado durante 50 interrupciones de reloj de 1 ms consecutivas. 50 ms es más largo que la mayoría de los conmutadores, pero es instantáneo en el tiempo humano. Dicho de otra manera, un ser humano no notará un retraso de 50 ms entre presionar un botón y la acción que se produce.

En casos raros en los que el sistema tiene que reaccionar más rápido que el tiempo de desmontaje del interruptor mecánico, puede desencadenar el primer cambio de estado, y luego bloquear los nuevos cambios de estado hasta que se resuelva el cambio existente. Esto casi no le otorga latencia, pero hace que el sistema sea susceptible a fallas breves. Tienes que decidir qué es realmente importante.

Nuevamente, tenga en cuenta que los usuarios humanos no notan retrasos de hasta 50 ms.

    
respondido por el Olin Lathrop
0

Es difícil proponer una solución sin saber qué tipo de MCU es esa. ¿Tienes algún temporizador o sys tick?

Tal vez algo como esto:

volatile unsigned long PBStart;

void Handle_PB() // my ISR called by pushbutton press falling edge
{
    if (getSysTickTimer() - PBStart > 50)   // Where 50 is some threshold like 50ms       
    {
        PBStart = 0;
    }

    if (PBStart == 0)   // Is ok to count
    { 
        PBStart = getSysTickTimer();

        pb++;
        if(pb>3)
        {  num1=1;
        }
        if(pb>4)
        {  num2=1;
           pb=0;
        }
    }
} 
    
respondido por el zupazt3

Lea otras preguntas en las etiquetas