我正在尝试在 c++ 中为 atmega 328p 微控制器解跳一个按钮,但似乎没有任何效果



我仍然是c++的初学者。我需要使用中断和计时器来拆除按钮(PCINT10)。我使用的是atmega328p微控制器和HW-262屏蔽。

当前使用timer0将时间增加1ms。这是目前为止我的代码的一部分:

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对按钮没有影响。仍然检测到多次按键。

你不应该把开关放在中断触发引脚上,因为它会触发每次反弹(以及其他形式的EMI噪声)。

相反,您需要从计时器ISR内部执行退出操作。对于大多数开关来说,它应该最多每5毫秒左右触发一次。(您可以通过在开关上插入电压并使用示波器测量来精确测量反弹)

因此,放弃PINC中断并将代码从那里移动到计时器ISR。比较当前读取的数据和之前读取的数据,并等待直到两者相同,这是最简单的反弹跳形式,在大多数情况下通常是足够的。

还应注意,ISR和主程序之间共享的所有变量都应声明为volatile,否则您可能会遇到优化编译器生成错误代码的问题。

相关内容

最新更新