Arduino Uno的pin change中断在哪里?如何配置非2、3引脚的CHANGE中断
Arduino 非2/3引脚配置CHANGE类型引脚变化中断方案
基础说明
你使用的「30 Days Lost in Space」套件默认搭载ATmega328P核心的Arduino Uno R3,该芯片除2、3引脚对应的2路外部中断外,额外支持3组引脚变化中断(Pin Change Interrupt),所有数字/模拟输入引脚均可配置为电平变化(CHANGE)触发,不受digitalPinToInterrupt()接口返回值限制。
配置逻辑
- 引脚变化中断按端口分为3个独立组别:
- PCINT0组:对应D8~D13引脚
- PCINT1组:对应A0~A5引脚
- PCINT2组:对应D0~D7引脚
- 配置需完成三步操作:
- 配置目标引脚为输入模式(推荐上拉输入避免信号漂移)
- 操作
PCICR寄存器开启对应组别的中断总开关 - 操作对应组的
PCMSKx(x=0/1/2)寄存器开启组内指定引脚的中断触发权限 - 编写对应组的中断服务函数
ISR(PCINTx_vect)处理触发逻辑
注:引脚变化中断固定为电平变化触发,天然适配编码器的检测需求,触发后需自行读取引脚电平判断变化方向
示例代码(编码器接D4、D5引脚)
// 编码器引脚定义 #define ENC_A 4 #define ENC_B 5 // 编码器状态变量(中断内使用的变量必须加volatile修饰) volatile int encoderPos = 0; volatile byte lastEncA, lastEncB; void setup() { Serial.begin(9600); // 配置编码器引脚为上拉输入 pinMode(ENC_A, INPUT_PULLUP); pinMode(ENC_B, INPUT_PULLUP); // 读取初始电平 lastEncA = digitalRead(ENC_A); lastEncB = digitalRead(ENC_B); // 开启PCINT2组(对应D0~D7)总中断 PCICR |= 0b00000100; // 开启D4、D5对应的引脚中断掩码 PCMSK2 |= 0b00011000; } // PCINT2组中断服务函数,组内任意引脚电平变化都会触发 ISR(PCINT2_vect) { byte currA = digitalRead(ENC_A); byte currB = digitalRead(ENC_B); // 编码器正交解码逻辑 if (currA != lastEncA) { encoderPos += (currB != currA) ? 1 : -1; lastEncA = currA; lastEncB = currB; } } void loop() { // 串口输出编码器位置 static int lastOutputPos = 0; if (encoderPos != lastOutputPos) { Serial.print("Encoder Pos: "); Serial.println(encoderPos); lastOutputPos = encoderPos; } }
其他引脚配置参考
- 若使用D8~D13引脚:设置
PCICR |= 0b00000001,修改PCMSK0寄存器对应位 - 若使用A0~A5引脚:设置
PCICR |= 0b00000010,修改PCMSK1寄存器对应位
内容的提问来源于stack exchange,提问作者RufusVS
相关产品推荐
相关产品推荐

