我有一个例程,可以轮询连接在微控制器ATMega328P上的按钮的状态(在芯片上arduino nano,但代码是用C++编写的),例程代码是这样的:
#include <avr/io.h>
#include <avr/interrupt.h>
bool GPIO::GetPressed()
{
if (bit_is_clear(*this->GetPortOrPin(), this->wichPin))
{
this->confidenceReleased = 0;
++this->confidencePressed;
if (!this->pressed && confidencePressed > thresholdPressed)
{
this->pressed = true;
confidencePressed = 0;
return true;
}
}
else
{
this->confidencePressed = 0;
++this->confidenceReleased;
if (this->pressed && confidenceReleased > thresholdReleased)
{
this->pressed = false;
confidenceReleased = 0;
}
}
return false;
}
如果按下按钮,此方法将返回
true
(这有点复杂,因为存在一些去抖动的情况),否则返回 false
。
*this->GetPortOrPin()
返回感兴趣的 PINX 寄存器。
当我在
main
内部使用此方法时,效果非常好。
如果我尝试在中断服务例程(由按钮本身触发)上使用相同的方法轮询按钮,则此方法始终返回
false
。
中断服务程序我的意思是:
ISR (PCINTX_vect) //X can be 1 2 or 3
{
//i press the button and code makes till this point
if (somebutton.GetPressed() )
{
//never gets inside
}
}
我尝试在 ISR 内部禁用中断,所以如果弹跳效果在引脚更改时触发大量中断,我可以摆脱这个问题,但这不起作用。
buttonpressed方法代码的问题在于,如果您在主函数中递归调用它,则在轮询“时尚”中的每次调用中计数器都会增加,如果您在中断例程中调用它,则该函数将仅执行一次并且由于计数器无法达到阈值,输出将始终评估为 false。