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