上升沿中断在STM32 Nucleo上触发多次 [英] Rising edge interrupt triggering multiple times on STM32 Nucleo

查看:79
本文介绍了上升沿中断在STM32 Nucleo上触发多次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用STM32 NUCLEO-F401RE微控制器板.

I am using the STM32 NUCLEO-F401RE microcontroller board.

我有一个扬声器,该扬声器经过编程,可以在上/下推操纵杆时将频率改变一个设定值.我的问题是,有时(通常不是)向上/向下推操纵杆时,频率会多次增加/减少,这意味着ISR正在执行多次.同样,将InterruptIn对象设置为在上升沿触发,但是有时它也在下降沿执行(当操纵杆在上/下推后恢复到空档时).解决这个问题有帮助吗?

I have a speaker programmed to change frequency by a set amount when the joystick is pushed up/down. My issue is that sometimes (more often than not) when the joystick is pushed up/down the frequency increases/decreases multiple times, implying that the ISR is executing multiple times. Also, the InterruptIn object is set to trigger on the rising edge however sometimes it also executes on the falling edge (when the joystick is returend to neutral after pushing up/down). Any help for getting over this?

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){}
}

推荐答案

机械开关弹跳或多或少是所有机械开关的功能.通常有必要实现去抖动"功能.在软件中,尤其是在这种情况下,如果交换机直接驱动中断.

Mechanical switch bounce is a feature of all mechanical switches to a lesser or greater extent. It is often necessary to implement "debouncing" in software especially if the switch is directly driving an interrupt as in this case.

在Google中快速搜索软件谴责技术会产生一些相当糟糕的IMO技术.不幸的是,我看到它执行的次数不尽人意.

A quick Google search for software denounce techniques yields some rather poor techniques IMO. I seen it done poorly more times than well unfortunately.

我建议您在交换机ISR中启动(或在发生反弹"时重新启动)硬件计时器,持续时间约为20毫秒(比交换机的反弹时间长,但比您的时间短)可能会真正释放开关).然后在计时器ISR中,测试开关的状态并相应地更改频率:

I suggest that in the switch ISR you start (or restart in the event of a "bounce") a hardware timer for a period of say 20ms or so (longer than the switch bounce time, but shorter than the time you could possibly to genuinely release the switch). Then in the timer ISR, you test the state of the switch and change the frequency accordingly:

伪代码:

void upISR()
{
    debounceTimerRestart() ;
}

void downISR()
{
    debounceTimerRestart() ;
}

void debounceTimerISR()
{
    debounceTimerStop() ;

    tDirection dir = getJoystickDir() ;
    swithc( dir )
    {
        case UP :
        {
            increaseFrquency() ;
        }
        break ;

        case DN :
        {
            decreaseFrquency() ;
        }
        break ;
    }
}

这是在开关停止弹跳后不久触发计时器中断(反跳时间").注意,计时器是单次"计时器.不是周期性的.

What this does is trigger a timer interrupt shortly ("debounce time") after the switch stops bouncing. Note the timer is "single-shot" not periodic.

下面,我对@BenVoigt的建议(在评论中)进行了增强.我将其分开,以明确说明这是他的工作.上面的方法通常可以使用,但是如果您的开关特别差,则可以用很少的钱解决以下问题,所以您也可以这样做:

Below I present an enhancement at @BenVoigt's suggestion (in comments). I am keeping it separate to make it clear it was his work. The above will generally work, but if you have a particularly poor switch the following would resolve issues, and at little cost, so you may as well:

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 ;
        }
    }
}

这篇关于上升沿中断在STM32 Nucleo上触发多次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆