You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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引脚
  • 配置需完成三步操作:
    1. 配置目标引脚为输入模式(推荐上拉输入避免信号漂移)
    2. 操作PCICR寄存器开启对应组别的中断总开关
    3. 操作对应组的PCMSKx(x=0/1/2)寄存器开启组内指定引脚的中断触发权限
    4. 编写对应组的中断服务函数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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:57:01