我正在尝试使用引脚更改中断来检测按下的按钮。到目前为止,我从未使用过这类中断并且存在一些问题,所以我想确定这是否是正确的用法。
如果我得到了正确的数据表,则必须执行以下操作才能使用引脚更改中断:
- 在 PCMSK 寄存器中设置要控制的 PIN
- 启用 PIN 寄存器以进行引脚更改中断控制 (PCICR)
- 启用中断
- 使用对应的中断向量
项目:简单的情绪灯,通过 4 个按钮控制颜色。
设置:
- Atmega168A-PU
- 4个迷你按钮开关
- MOSFET 来控制我的 3 瓦 RGB LED
这是我正在使用的代码,它没有按预期工作:
#include <avr/io.h>
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BUTTON1 (1<<PC5)
#define BUTTON2 (1<<PC4)
#define BUTTON3 (1<<PC3)
#define BUTTON4 (1<<PC2)
#define GREEN (1<<PB1)
#define BLUE (1<<PB2)
#define RED (1<<PB3)
void init() {
// enable LED
DDRB |= GREEN;
DDRB |= BLUE;
DDRB |= RED;
// button pullups
PORTC |= BUTTON1;
PORTC |= BUTTON2;
PORTC |= BUTTON3;
PORTC |= BUTTON4;
// pin change interrupts for buttons
PCMSK1 |= PCINT13;
PCMSK1 |= PCINT12;
PCMSK1 |= PCINT11;
PCMSK1 |= PCINT10;
// enable pin change for buttons
PCICR |= PCIE2;
sei();
}
ISR(PCINT2_vect) {
PORTB = BLUE;
}
void ledTest() {
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
_delay_ms(250);
PORTB ^= RED;
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
_delay_ms(250);
PORTB ^= BLUE;
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
_delay_ms(250);
PORTB ^= GREEN;
}
int main() {
init();
ledTest();
_delay_ms(500);
PORTB |= GREEN;
while(1) {
_delay_ms(100);
}
}
注意:按钮应该去抖动。由于我正在逐步尝试此操作,并且不适合打开 LED,因此我在这里忽略了它。
问题:我尝试使用中断的方式是否正确?
我的设置问题:
- Buttons1-3 完全被忽略。
- Button4 正在触发 atmega 的重置
我检查的事情:
- 按钮与重置 PIN 无关
- 如果按下按钮,则正确连接到 GND
- 如果未按下按钮,则未连接到 GND
如果我在没有中断的情况下使用它们,按钮会很好地工作,例如:
if(!(PINC & BUTTON4)) { PORTB ^= 蓝色;}
- 16MHZ外晶/内晶
- 路由中的任何错误
- 我在 atmega 上的 PWR 和 GND 之间使用了一个 100nF 电容器
- VCC(7), GND(8), GND(22), AVCC(20) 已连接(因为我不需要 AREF,所以没有连接)