I'm trying to debounce a button in c++ for an atmega 328p microcontroller but nothing seems to be working

huangapple go评论63阅读模式
英文:

I'm trying to debounce a button in c++ for an atmega 328p microcontroller but nothing seems to be working

问题

以下是翻译好的代码部分:

我在C++中仍处于初学者水平。我需要使用中断和定时器来去抖动一个按钮(PCINT10)。我正在使用atmega328p微控制器和HW-262扩展板。目前正在使用timer0来每1毫秒增加时间

这是我目前的代码的一部分:

ISR(TIMER0_COMPA_vect) {
    now++; //每1毫秒增加
}
//中断设置
PCICR = 0b00000010;
PCIFR = 0b00000010;
PCMSK1 = 0b00000100;// 在PCINT10上触发中断

//全局变量
uint8_t A2 = 0b00000100;
uint32_t A2_time = 0;
uint32_t buttons;
uint32_t oldb = 0;
uint32_t newb;

//中断服务程序(ISR)
ISR(PCINT1_vect) {
    newb = PINC;
    int changed = oldb ^ newb; // changed为1表示按钮已更改
    if (changed & A2) {
        if ((now - A2_time) > 10) { // 10毫秒去抖动
            // 新的S1_A1按下
            A2_time = now;
            if ((oldb & ~newb) & A2) {
                buttons |= A2;
            }
        }
    }
}

//调用按钮以更改状态(不是ISR的一部分)
if ((PINC & A2) == 0) { //如果A2被按下
    current_state = Pause;
}

ISR对按钮没有产生影响,仍然检测到多次按钮按下。

英文:

I'm still at a beginner level in C++. I need to debounce a button (PCINT10) using an interrupt and a timer. I'm using an atmega328p microcontroller and a HW-262 shield. Currently using timer0 to increment time by 1ms.

This is part of my code so far:

ISR(TIMER0_COMPA_vect) {
    now++; //increment by 1ms
}
//interrupt setup
    PCICR = 0b00000010; 
    PCIFR = 0b00000010;
    PCMSK1 = 0b00000100;// interrupt on PCINT10

//global variables
uint8_t A2 = 0b00000100;
uint32_t A2_time = 0;
uint32_t buttons;
uint32_t oldb = 0;
uint32_t newb;

//ISR
ISR(PCINT1_vect) {
    newb = PINC;
    int changed = oldb ^ newb; // changed is 1 for buttons that have changed
    if (changed & A2) {
        if ((now - A2_time) > 10) { // 10 ms debounce
            // new S1_A1 press
            A2_time = now;
            if ((oldb & ~newb) & A2) {
                buttons |= A2;
            }
        }
    }
}

//calling button to change states (not part of the ISR)
if (((PINC & A2) == 0)) { //if A2 pressed
                    current_state = Pause;
                }

The ISR has had no effect on the button. Still detecting multiple button presses.

答案1

得分: 3

不应将开关放在中断触发的引脚上,因为它将在每次抖动时触发(以及其他形式的电磁干扰噪音)。

相反,您需要在定时器ISR内进行去抖动。对于大多数开关,它应该最多每5毫秒触发一次。 (您可以通过插入电压到开关并使用示波器测量来精确测量抖动。)

因此,取消PIN C中断,并将代码从那里移至定时器ISR。将当前读取与之前的读取进行比较,并等待两者相同时,是去抖动的最简单形式,在大多数情况下通常足够。

还请注意,所有在ISR和主程序之间共享的变量应声明为“volatile”,否则可能会遇到优化编译器生成不正确代码的问题。

英文:

You shouldn't place the switch on an interrrupt-triggered pin, because it will trigger for each bounce (and on other forms of EMI noise as well).

Instead you need to do the debouncing from inside the timer ISR. And for most switches it should trigger at most once every 5ms or so. (You can measure the bounce exactly by plugging in a voltage to the switch and measure with an oscilloscope.)

So drop the PINC interrupt and move the code from there to the timer ISR. Comparing the current read with the previous and waiting until both are the same is the simplest form of de-bouncing and usually sufficient in most cases.

Also note that all variables shared between an ISR and the main program should be declared volatile or you might run into problems with an optimizing compiler generating incorrect code.

huangapple
  • 本文由 发表于 2023年3月31日 17:53:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75897133.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定