在STM32 Nucleo上多次触发上升沿中断

Rising edge interrupt triggering multiple times on STM32 Nucleo(在STM32 Nucleo上多次触发上升沿中断)

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

问题描述

I am using the STM32 NUCLEO-F401RE microcontroller board.

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.

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

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:

Pseudocode:

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.

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上多次触发上升沿中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:在STM32 Nucleo上多次触发上升沿中断

基础教程推荐