Es ist eine Anforderung, dass ich die Anzahl der Tastendrücke durch externe oder andere Unterbrechungen zählen sollte.
Wenn ich also den externen Interrupt verwende, um den Zähler um 1 zu erhöhen, wird er manchmal um 2 oder 3 aufgrund von Entprellung erhöht. Kann mir jemand sagen, wie man in diesem Fall genau zählt?
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 ist der Drucktastenzähler. und num1 und num2 sind Flags.
Nach 4-maligem Drücken der Taste möchte ich also eine andere Aufgabe erledigen. Gleich nach 5-maligem Drücken der Taste möchte ich eine andere Aufgabe erledigen. Wichtig ist also, eine genaue Anzahl von Tastendrücken zu zählen. Ich kenne das Entprellprinzip. Aber wo kann ich diesen Entprellverzögerungscode einfügen, da er unterbrechungsgesteuert ist?
1) Es ist besser, wenn Sie das Entprellen in der Hardware selbst erledigen können. Legen Sie, wenn möglich, einen geeigneten Kondensator auf den Interrupt-Pin auf Masse.
2) In Software können Sie wie folgt vorgehen: (Angenommen, das Springen kann bis zu 50 Sekunden dauern)
void my_interrupt_handler()
{
interrupt_time = currentmilliseconds();
if (interrupt_time - last_interrupt_time > 50)
{
press++;
last_interrupt_time = interrupt_time;
}
}
last_interrupt_time hat den Anfangswert 0. Der Code erhöht den Druckwert für den allerersten Druck. Aber es wird nicht für 50 ms inkrementiert, egal wie viele Tasten-Interrupts aufgrund von Prellen dazwischen kommen. Dies funktioniert nur dann effizient, wenn der Mikrocontroller Interrupts innerhalb von Interrupts unterstützt, andernfalls besteht die Möglichkeit, dass der Timer-Überlauf-Interrupt fehlt.
3) Eine andere Methode besteht darin, einfach eine Verzögerung von 50 ms nach dem Erhöhen von press hinzuzufügen . Es klappt. Aber keine gute Methode.
4) Eine andere Idee, indem Sie eine Flag-Variable verwenden:
void my_interrupt_handler()
{
if (flag == 0)
{
press++;
flag = 1
}
}
flag ist eine flüchtige Variable, die von main() und ISR geteilt wird. Der Code ist in main() so geschrieben, dass er das Flag erst wieder auf 0 initialisiert, nachdem 50 ms gezählt wurden. Das ist also wie das Deaktivieren von Tastenunterbrechungen für 50 ms. Wie auch immer, Menschen können nicht schneller drücken.
Sie müssen das tun, was Entprellen genannt wird . Es gibt viele Möglichkeiten, und es gibt sicherlich viel darüber geschrieben.
Die Methode, die ich normalerweise verwende, besteht darin, einen neuen Zustand nicht als gültig zu betrachten, bis der Eingang 50 aufeinanderfolgende 1-ms-Takt-Interrupts in diesem Zustand war. 50 ms sind länger, als die meisten Schalter zurückprallen, sind aber in menschlicher Zeit immer noch augenblicklich. Anders ausgedrückt, ein Mensch wird eine Verzögerung von 50 ms zwischen dem Drücken einer Taste und dem Auftreten einer Aktion nicht bemerken.
In seltenen Fällen, in denen das System schneller als die Entprellzeit des mechanischen Schalters reagieren muss, können Sie die erste Zustandsänderung auslösen und dann neue Zustandsänderungen blockieren, bis sich die vorhandene Änderung eingestellt hat. Dies gibt Ihnen fast keine Latenz, macht das System jedoch anfällig für kurze Störungen. Sie müssen entscheiden, was wirklich wichtig ist.
Denken Sie auch hier daran, dass Verzögerungen von bis zu etwa 50 ms von menschlichen Benutzern unbemerkt bleiben.
Es ist schwierig, eine Lösung vorzuschlagen, ohne zu wissen, um welche Art von MCU es sich handelt. Hast du einen Timer oder Systick?
Vielleicht so etwas:
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;
}
}
}
dirac16
Tyler
DiBosco
litun bls
Bruce Abbott
DiBosco