我正在使用 STM32 NUCLEO-F401RE 微控制器板。
我有一个扬声器,经过编程,当向上/向下推操纵杆时,可以按设定的量改变频率。我的问题是,有时(通常)当向上/向下推动操纵杆时,频率会增加/减少多次,这意味着 ISR 正在执行多次。此外,InterruptIn 对象设置为在上升沿触发,但有时它也会在下降沿执行(当操纵杆在向上/向下推后返回到空档时)。有什么帮助克服这个吗?
void upISR()
{
if (greenLED.getStatus())
{
myTicker.detach();
frequency+=200;
myTicker.attach(callback(&spkr, &Speaker::toggle), 0.5/frequency);
}
}
'
int main()
{
InterruptIn up(A2);
InterruptIn down(A3);
InterruptIn fire(D4);
up.rise(&upISR);
down.rise(&downISR);
fire.rise(&toggleISR);
redLED.on();
while (1){}
}
机械开关弹跳或多或少是所有机械开关的一个特征。通常需要在软件中实现“去抖动”,特别是如果开关直接驱动中断(如本例所示)。
在谷歌上快速搜索软件谴责技术会产生一些在我看来相当糟糕的技术。不幸的是,我看到做得不好的次数多于做得好的次数。
我建议在开关 ISR 中启动(或在发生“反弹”时重新启动)一个硬件计时器,持续大约 20 毫秒(比开关反弹时间长,但比您真正可能的时间短)松开开关)。然后在定时器 ISR 中,测试开关的状态并相应地更改频率:
伪代码:
void upISR()
{
debounceTimerRestart() ;
}
void downISR()
{
debounceTimerRestart() ;
}
void debounceTimerISR()
{
debounceTimerStop() ;
tDirection dir = getJoystickDir() ;
swithc( dir )
{
case UP :
{
increaseFrquency() ;
}
break ;
case DN :
{
decreaseFrquency() ;
}
break ;
}
}
其作用是在切换后不久(“去抖时间”)触发定时器中断stops弹跳。请注意,计时器是“单次”而不是周期性的。
下面我根据@BenVoigt 的建议(在评论中)提出了改进。我将其分开以表明这是他的工作。上述方法通常会起作用,但如果您的开关特别差,以下方法可以解决问题,而且成本很低,所以您也可以:
void debounceTimerISR()
{
debounceTimerStop() ;
static tDirection previous_dir = CENTRE ;
tDirection dir = getJoystickDir() ;
// If the state changed...
if( previous_dir != dir )
{
previous_dir = dir ;
switch( dir )
{
case UP :
{
increaseFrquency() ;
}
break ;
case DN :
{
decreaseFrquency() ;
}
break ;
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)