Arduino筆記(52):使用 7個GPIO控制2個7段LED顯示器

要控制Arduino 的 I/O Port最常見的方式是使用digitalWrite 和 digitalRead 指令,但這個方法要每個 Port 逐一定義,速度較慢。有另一個比較快速的方法是直接從 Port 暫存器修改接腳的狀態,讓位元直接存入0或1,來表示 Pin腳的輸入或輸出。實做使用7個GPIO接腳,來控制兩個七段顯示器,讓數字從 1跳到 100。


[I/O Ports暫存器] 

Arduino UNO 開發板用的晶片是 ATmega8 或 ATmega168/328 爲主,有3個 8-bit 的 PORTx(x 代表 B, C, D) :

B: 對應 Arduino 的 Digital pin 8 to 13
C: 對應 Arduino 的 Analog input pin 0 to 5
D: 對應 Arduino 的 Digital pins 0 to 7

例如,位於PortB 的 Digital Pin 8 簡稱作 PB0,PortD Digital Pin 0 簡稱作 PD1;位於 PortC 的 Analog Pin 2也可以說是 PC2。
在晶片內是透過暫存器(register)來對腳位進行設定,對於Arduino這種AVR晶片來說,每個Port都受三個暫存器控制,分別是(x可以用B, C, D代替):

DDRx (Data Direction Register):可讀可寫的暫存器,指定輸入/輸出,類似pinMode()。
Portx (Data Register):透過這類暫存器設定電壓為高電位或低電位,類似digitalWrite()。
PINx (Port Input Pins):唯讀,可以知道哪個 Pin 的電壓是高電位或低電位,類似 analogRead()。


來源:arduino.cc 

[材料]

  • Arduino UNO R3 x 1
  • 七段LED顯示器 x 2
  • 麵包板 x 1
  • 連接線 x n



[接線圖]



[程式]

void setup()
{
  // B0-B1(Set as output); DDR-Data Direvction Register 
  // 被用來設定 pin爲input(0) 或 output(1)
  DDRB = 0b00000011;
  //D1-D7(Set as output) 
  DDRD = 0b11111110;
}

void loop()
{
  start();
  for (int i = 0; i < 10; i++)
  {
    for ( int j = 0; j < 10; j++)
    {
      for (int del = 0; del < 10; del++)
      {
        disp(i, j);
      }
    }
  }
}

void start()
{ int i = 2;
  while (i != 0)
  {
    if (i == 2)
    {
      //開啓 PORT B 的 1-Pin 並將其他 Pin 設定成 OFF.
      PORTB = 0b00000010;    
    }
    if (i == 1)
    {
      PORTB = 0b00000001;
    }

    //  以下 PORTD 被註解是共陰型的七段顯示器,
    //  目前程式執行的是共陽式的七段顯示器
    //  PORTD = 0b00000010;
    PORTD = 0b11111101;
    delay(100);
    //  PORTD = 0b00000110;
    PORTD = 0b11111001;
    delay(100);
    //  PORTD = 0b00001110;
    PORTD = 0b11110001;
    delay(100);
    //  PORTD = 0b00011110;
    PORTD = 0b11100001;
    delay(100);
    //  PORTD = 0b00111110;
    PORTD = 0b11000001;
    delay(100);
    //  PORTD = 0b01111110;
    PORTD = 0b10000001;
    delay(100);
    //  PORTD = 0b11111110;
    PORTD = 0b00000001;
    delay(200);
    //  PORTD = 0b01111110;
    PORTD = 0b10000001;
    delay(100);
    //  PORTD = 0b00111110;
    PORTD = 0b11000001;
    delay(100);
    //  PORTD = 0b00011110;
    PORTD = 0b11100001;
    delay(100);
    //  PORTD = 0b00001110;
    PORTD = 0b11110001;
    delay(100);
    //  PORTD = 0b00000110;
    PORTD = 0b11111001;
    delay(100);
    //  PORTD = 0b00000010;
    PORTD = 0b11111101;
    delay(100);
    //  PORTD = 0b00000000;
    PORTD = 0b11111111;
    delay(200);
    i--;
  }
}

void zero()
{
//  PORTD = 0b01111110;
  PORTD = 0b10000001;
}

void one()
{
//  PORTD = 0b00001100;
  PORTD = 0b11110011;
}

void two()
{
//  PORTD = 0b10110110;
  PORTD = 0b01001001;
}

void three()
{
//  PORTD = 0b10011110;
  PORTD = 0b01100001;
}

void four()
{
//  PORTD = 0b11001100;
  PORTD = 0b00110011;
}

void five()
{
//  PORTD = 0b11011010;
  PORTD = 0b00100101;
}

void six()
{
//  PORTD = 0b11111010;
  PORTD = 0b00000101;
}

void seven()
{
//  PORTD = 0b00001110;
    PORTD = 0b11110001;
}

void eight()
{
//  PORTD = 0b11111110;
  PORTD = 0b00000001;
}

void nine()
{
//  PORTD = 0b11001110;
  PORTD = 0b00110001;
}

void digit1(int x)
{
  PORTB = 0b00000001;
  switch (x) {
    case 1: one(); break;
    case 2: two(); break;
    case 3: three(); break;
    case 4: four(); break;
    case 5: five(); break;
    case 6: six(); break;
    case 7: seven(); break;
    case 8: eight(); break;
    case 9: nine(); break;
    case 10: zero(); break;
    case 0: zero(); break;
  }
}

void digit2(int x)
{
  PORTB = 0b000000010;
  switch (x) {
    case 1: one(); break;
    case 2: two(); break;
    case 3: three(); break;
    case 4: four(); break;
    case 5: five(); break;
    case 6: six(); break;
    case 7: seven(); break;
    case 8: eight(); break;
    case 9: nine(); break;
    case 0: zero(); break;
    case 10: zero(); break;
  }
}

void disp(int i, int j)
{
  digit1(i);
  delay(10);
  digit2(j);
  delay(10);
}

[實作結果]



[參考資料]




Post a Comment

較新的 較舊