演示代码:

// 引脚定义
#define CLK 2
#define DT  3
#define SW  4

int counter = 0;        // 计数值
int lastCLK;            // 上一次CLK电平

void setup() {
  Serial.begin(9600);
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP); // 内部上拉,按键低电平触发
  lastCLK = digitalRead(CLK);
}

void loop() {
  int currentCLK = digitalRead(CLK);

  // CLK电平发生变化时判断旋转
  if (currentCLK != lastCLK) {
    // DT高=顺时针 +1;DT低=逆时针 -1
    if (digitalRead(DT) != currentCLK) {
      counter++;
    } else {
      counter--;
    }
    Serial.print("数值:");
    Serial.println(counter);
  }
  lastCLK = currentCLK;

  // 检测编码器按键
  if (digitalRead(SW) == LOW) {
    delay(200); // 消抖
    Serial.println("编码器按键按下");
    counter = 0; // 按下清零
  }
}

中断版:

#define CLK 2  // 中断0
#define DT  3
#define SW  4

volatile int count = 0; // 中断变量必须加volatile
int lastDT;

void setup() {
  Serial.begin(9600);
  pinMode(CLK, INPUT);
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP);

  // 绑定中断,CLK电平变化触发
  attachInterrupt(digitalPinToInterrupt(CLK), encoderISR, CHANGE);
}

// 中断服务函数(尽量简短,不Serial打印)
void encoderISR(){
  int clkVal = digitalRead(CLK);
  int dtVal = digitalRead(DT);
  if(dtVal != clkVal){
    count++;
  }else{
    count--;
  }
}

void loop() {
  // 拷贝中断数值,避免读写冲突
  int val;
  noInterrupts();
  val = count;
  interrupts();

  Serial.println(val);

  // 按键清零
  if(digitalRead(SW) == LOW){
    delay(200);
    noInterrupts();
    count = 0;
    interrupts();
  }
  delay(50);
}

参考资料:

标签: none

评论已关闭