一個74HC595連接多個七段顯示器

本文將示範用一個74HC595連接兩個7段顯示器,從00開始,每隔一秒加1顯示0~99。底下的電路圖改自《超圖解Arduino互動設計入門》動手做7-2,新增的七段顯示器與前一個並聯。

74HC595電路圖

本實驗使用「共陰極」七段顯示器,按照上面的電路,若Arduino數位8和9腳都輸出低電位(LOW),則兩個顯示器將同步呈現一致的畫面;若數位9輸出高電位(HIGH)數位8輸出低電位(LOW),則只有代表「個位數字」的顯示器會點亮,「十位數字」不顯示。

因此,七段顯示器的「共接腳」相當於「晶片選擇」腳;低電位時被選上、高電位時被關閉。

假設要在兩個顯示器顯示“24”,先傳送其中一個數字資料給74HC595,例如,個位數,同時將個位數的顯示器接地,另一個接高電位,維持一小段時間(5ms)之後再傳送另一個數字並切換顯示器。

74HC595連接兩個七段顯示器

只要在一秒鐘之內快速切換15次以上,人眼會因為視覺暫留現象而感到所有顯示器同時顯示了數字。

為了在不同的顯示器呈現個別數字,程式需要透過除法和餘除拆解每個數字:

拆解數字

以呈現兩個位數為例,為了方便程式循序操作,筆者把拆解後的數字全都存入digits陣列,選擇七段顯示器的接腳編號則存入SEG_PIN陣列:

陣列定義

如此,底下的敘述將能控制兩個顯示器呈現個別的數字:

控制七段顯示器

本實驗電路的麵包板接線示範如下:

74HC595麵包板電路

筆者把程式分成counter(資料處理、計數)display(控制顯示器)兩個函式:

程式的主要函式

完整的程式碼如下:

const byte SEG_PIN[2]={8, 9};            // 7段顯示器的控制接腳
const byte NUM_OF_SEG = sizeof(SEG_PIN); // 7段顯示器的數量
int number=0;
byte digits[2] = {0, 0};

const byte dataPin = 2;    // 74HC595序列輸入
const byte latchPin = 3;   // 74HC595暫存器時脈」
const byte clockPin = 4;   // 74HC595序列時脈

unsigned long previousMillis = 0;
const long interval = 1000; 

const byte LEDs[10] = {
  0x7E, 0x30, 0x6D, 0x79, 0x33,
  0x5B, 0x5F, 0x70, 0x7F, 0x73
};

// 每隔一秒數字加1並拆解數字
void counter() {
  unsigned long currentMillis = millis();
  
  // 每隔1秒執行一次底下的條件式內容
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    
    if (++number > 99) {  // number先加1,再比較
      number = 0;            // 若超過99則歸零
    }
    
    digits[0]= number % 10 ;       // 儲存個位數字
    digits[1]= number / 10 % 10 ;  // 十位數字
  }
}

void display(){
  byte num;

  // 逐一設定每個七段顯示器
  for (byte i=0; i<NUM_OF_SEG; i++){
    num = digits[i];

    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, LEDs[num]);
    digitalWrite(latchPin, HIGH);
    
    digitalWrite(SEG_PIN[i], LOW);     // 點亮此顯示器
    delay(5);
    
    for (byte j=0; j<NUM_OF_SEG; j++) {
      digitalWrite(SEG_PIN[j], HIGH);  // 關閉所有顯示器
    }
  }
}

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  for (byte i=0; i<NUM_OF_SEG; i++) {
    pinMode(SEG_PIN[i], OUTPUT);
    digitalWrite(SEG_PIN[i], HIGH);
  }
}

void loop() {
  counter();
  display();
}

補充說明,控制顯示器的display()函式中,使用一個for迴圈逐一控制每個七段顯示器,是為了方便擴充顯示器的數量。電路每增加一個顯示器,就要多加一條控制線,假設總共有4個七段顯示器,控制線分別接在8, 9, 10和11腳,程式開頭的兩個陣列值需要修改,其餘不變:

const byte SEG_PIN[4]={8, 9, 10, 11};
byte digits[4] = {0, 0, 0, 0};
Posts created 470

3 thoughts on “一個74HC595連接多個七段顯示器

  1. 趙老師好

    我挑戰用兩顆74HC595顯示4位數,一顆74HC595控制八位元腳位,第二顆控制4個顯示器腳位。
    剛開始挑戰時候遇到很多問題,顯示亂碼、想不出如何控制這兩顆…參考其他範例程式到底什麼運作…
    再回頭看趙老師的書寫的程式碼。
    最後做出來了…

    程式如下

    const byte SEG_PIN[4] = {0x01, 0x02, 0x04, 0x08}; // 7段顯示器的控制接腳
    const byte NUM_OF_SEG = sizeof(SEG_PIN); // 7段顯示器的數量
    int number = 0;
    byte digits[4] = {0, 0, 0, 0};

    int clockPin = 4;
    int latchPin = 3;
    int dataPin = 2;

    unsigned long previousMillis = 0;
    const long interval = 1000;
    unsigned char LEDs[] = {0xC0, //”0″ 1100 0000
    0xF9, //”1″ 1111 1001
    0xA4, //”2″ 1010 0100
    0xB0, //”3″ 1011 0000
    0x99, //”4″ 1001 1001
    0x92, //”5″ 1001 0010
    0x82, //”6″ 1000 0010
    0xF8, //”7″ 1111 1000
    0x80, //”8″ 1000 0000
    0x90 //”9″ 1001 0000
    };
    void setup() {
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);
    // for (byte i = 0; i = interval) {
    previousMillis = currentMillis;

    if (++number > 99) { // number先加1,再比較
    number = 0; // 若超過99則歸零
    }

    digits[0] = number % 10 ; // 儲存個位數字
    digits[1] = number / 10 % 10 ; // 十位數字
    }
    }

    void display() {
    byte num;

    // 逐一設定每個七段顯示器
    for (byte i = 0; i < NUM_OF_SEG; i++) {
    num = digits[i];

    digitalWrite(latchPin, HIGH);
    shiftOut(dataPin, clockPin, MSBFIRST, LEDs[num]);
    shiftOut(dataPin, clockPin, MSBFIRST, SEG_PIN[i]);
    digitalWrite(latchPin, LOW);

    //SEG_PIN[2]; // 點亮此顯示器
    delay(5);

    for (byte j = 0; j < NUM_OF_SEG; j++) {
    //SEG_PIN[1]; // 關閉所有顯示器
    }
    }
    }
    void loop() {
    counter();
    display();
    }

  2. const byte SEG_PIN[2]={8, 9};
    const byte NUM_OF_SEG = sizeof(SEG_PIN);
    int number=0;
    byte digits[2] = {0, 0};

    const byte dataPin = 2;
    const byte latchPin = 3;
    const byte clockPin = 4;

    unsigned long previousMillis = 0;
    const long interval = 1000;

    const byte LEDs[10] = {
    0x7E, 0x30, 0x6D, 0x79, 0x33,
    0x5B, 0x5F, 0x70, 0x7F, 0x73
    };

    void counter() {
    unsigned long currentMillis = millis();

    if (currentMillis – previousMillis >= interval) {
    previousMillis = currentMillis;

    if (++number > 99) {
    number = 0;
    }

    digits[0]= number % 10 ;
    digits[1]= number / 10 % 10 ;
    }
    }

    void display(){
    byte num;
    for (byte i=0; i<NUM_OF_SEG; i++){
    num = digits[i];

    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, LSBFIRST, LEDs[num]);
    digitalWrite(latchPin, HIGH);

    digitalWrite(SEG_PIN[i], LOW);
    delay(5);

    for (byte j=0; j<NUM_OF_SEG; j++) {
    digitalWrite(SEG_PIN[j], HIGH);
    }
    }
    }

    void setup() {
    pinMode(latchPin, OUTPUT);
    pinMode(clockPin, OUTPUT);
    pinMode(dataPin, OUTPUT);

    for (byte i=0; i<NUM_OF_SEG; i++) {
    pinMode(SEG_PIN[i], OUTPUT);
    digitalWrite(SEG_PIN[i], HIGH);
    }
    }

    void loop() {
    counter();
    display();
    }

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top