目录

用Arduino控制旋转编码器

1. 电路连接

2. 代码示例

初始化管脚以及中断服务程序

#include 
#include 
#include 
 
volatile byte seqA = 0;
volatile byte seqB = 0;
volatile byte cnt1 = 0;
volatile byte cnt2 = 0;
volatile boolean right = false;
volatile boolean left = false;
volatile boolean button = false;
boolean backlight = true;
byte menuitem = 1;
byte page = 1;
 
Adafruit_PCD8544 display = Adafruit_PCD8544(13, 12,11, 8, 10);
 
void setup() {
 
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
 
  // Enable internal pull-up resistors
  digitalWrite(A0, HIGH);
  digitalWrite(A1, HIGH);
  digitalWrite(A2, HIGH);
 
  // Turn on LCD backlight
  pinMode(9, OUTPUT);
  digitalWrite(9, HIGH);
 
  PCICR =  0b00000010; // 1. PCIE1: Pin Change Interrupt Enable 1
  PCMSK1 = 0b00000111; // Enable Pin Change Interrupt for A0, A1, A2
 
  // Initialize LCD
  display.setRotation(2); // Set LDC orientation
  display.begin(60);      // Set LCD contrast
  display.clearDisplay(); // Clear display
  display.display();      // Apply changes
 
  sei();
}
 
void loop() {
 
  // Create Menu Pages
  if (page==1) {
 
    display.setTextSize(1);
    display.clearDisplay();
    display.setTextColor(BLACK, WHITE);
    display.setCursor(15, 0);
    display.print("MAIN MENU");
    display.drawFastHLine(0,10,83,BLACK);
    display.setCursor(0, 15);
    if (menuitem==1) { display.setTextColor(WHITE, BLACK);}
    else {display.setTextColor(BLACK, WHITE);}
    display.print(">Contrast: 99%");
    display.setCursor(0, 25);
    if (menuitem==2) { display.setTextColor(WHITE, BLACK);}
    else {display.setTextColor(BLACK, WHITE);}    
    display.print(">Test Encoder");
    if (menuitem==3) { display.setTextColor(WHITE, BLACK);}
    else {display.setTextColor(BLACK, WHITE);}  
    display.setCursor(0, 35);
    display.print(">Backlight:");
    if (backlight) {display.print("ON");}
    else {display.print("OFF");}
    display.display();}
 
  else if (page==2) {
    display.setTextSize(1);
    display.clearDisplay();
    display.setTextColor(BLACK, WHITE);
    display.setCursor(15, 0);
    display.print("ENC. TEST");
    display.drawFastHLine(0,10,83,BLACK);
    display.setCursor(5, 15);
    display.print("LEFT    RIGHT");
    display.setTextSize(2);
    display.setCursor(5, 25);
    display.print(cnt1);
    display.setCursor(55, 25);
    display.print(cnt2);
    display.setTextSize(2);
    display.display();
  }
 
  // Take action if a new command received from the encoder
  if (left) {
    left = false;
    menuitem--;
    if (menuitem==0) {menuitem=3;}      
  }
 
  if (right) {
    right = false;
    menuitem++;
    if (menuitem==4) {menuitem=1;}      
  }
 
  if (button) {
    button = false;
 
    if (page == 1 && menuitem==3) {
      digitalWrite(9, LOW);
      if (backlight) {backlight = false; digitalWrite(9, LOW);}
      else {backlight = true; digitalWrite(9, HIGH);}
      }
 
    else if (page == 1 && menuitem==2) {
      page=2;
      cnt1=0;
      cnt2=0;        
     }
 
    else if (page == 2) {
      page=1;
     }
   }
 
  }
 
 
ISR (PCINT1_vect) {
 
// If interrupt is triggered by the button
  if (!digitalRead(A0)) {
 
    button = true;}
 
// Else if interrupt is triggered by encoder signals
  else {
 
    // Read A and B signals
    boolean A_val = digitalRead(A1);
    boolean B_val = digitalRead(A2);
 
    // Record the A and B signals in seperate sequences
    seqA <<= 1;
    seqA |= A_val;
 
    seqB <<= 1;
    seqB |= B_val;
 
    // Mask the MSB four bits
    seqA &= 0b00001111;
    seqB &= 0b00001111;
 
    // Compare the recorded sequence with the expected sequence
    if (seqA == 0b00001001 && seqB == 0b00000011) {
      cnt1++;
      left = true;
      }
 
    if (seqA == 0b00000011 && seqB == 0b00001001) {
      cnt2++;
      right = true;
      }
  }
 
}

2. 参考技术资料