我试图去抖一个按钮在c++的atmega328p微控制器,但似乎没有工作

1szpjjfi  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(122)

我仍然处于C++的初学者水平。我需要使用中断和计时器来消除按钮(PCINT 10)的抖动。我使用的是atmega 328 p微控制器和HW-262屏蔽。目前使用timer 0将时间增加1 ms。
这是我目前为止的代码的一部分:

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

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

w8f9ii69

w8f9ii691#

你不应该把开关放在中断触发的引脚上,因为它会在每次反弹时触发(也会在其他形式的EMI噪声时触发)。
相反,你需要从定时器ISR内部进行去抖动。对于大多数开关,它应该最多每5ms左右触发一次。(你可以通过将电压插入开关并用示波器测量来精确测量反弹。)
因此,丢弃PINC中断并将代码从那里移动到计时器ISR。将当前读取与先前读取进行比较并等待直到两者相同是最简单的去反弹形式,并且在大多数情况下通常足够。
还要注意,ISR和主程序之间共享的所有变量都应该声明为volatile,否则可能会遇到优化编译器生成错误代码的问题。

相关问题