mBlock & Arduino(18)74HC595 與七段顯示器


在〈mBlock & Arduino(17)七段顯示器之 HELLO!〉與〈mBlock & Arduino(17)四位數七段顯示器〉都談過七段顯示器,直接使用 Arduino 來控制七段顯示器的問題在於,它們會佔用到 Arduino 上許多輸出腳位,如果想減少 Arduino 上的腳位佔用,那麼可以使用 4511 或 74HC595 等驅動 IC,或者是選用市面上現成的七段顯示器模組。

74HC595 工作原理

使用 74HC595,你可以使用三個腳位來控制八個輸出,在正式看到 74HC595 腳位之前,可以先這麼想,如果你想要最後八個輸出為 10101101,那麼一開始令 ST_CP 腳位為低電位,然後提供腳位 DS 高電位,如下圖:

74HC595

接著令 SH_CP 為高電位,將資料推入位移暫存器:

74HC595

接著令 SH_CP 為低電位,DS 提供 0:

74HC595

接著再令 SH_CP 為高電位,將資料推入位移暫存器,先前的 1 因此也被推進下一個暫存位置:

74HC595

重複以上動作,繼續將 101101 推入位移暫存器,成為以下狀態:

74HC595

此時令 ST_CP 為高電位,下方儲存暫存器會複製位移暫存器的值:

74HC595

這時儲存暫存器的值就可以作為 Q0 到 Q7 腳位輸出之用,接下來若要繼續提供新的資料給位移暫存器,要令 ST_CP 為低電位,假設接下來又推進一個 1:

74HC595

那麼原先最左邊的 1 被推至 Q7',一個 74HC595 可以提供八個輸出,如果想要提供 16 或更多輸出,可以串接 74HC595,從上可知,串接方式就是將上一顆 74HC595 的 Q7' 連接至下一顆 74HC595 的 DS。

連接七段顯示器

實際的 74HC595 有 16 個腳位,除了上面談到的 DS、SH_CP、ST_CP、Q0 到 Q7 以及 Q7' 之外,還有 VCC、GND、OE 與 MR 腳位:

74HC595

OE 是指 Output Enable,設置為低電位時表示允許輸出,因此在連接七段顯示器時,可以直接與 GND 相連;MR 是指 Master Reset,設定為低電位時,表示清除暫存器所有資料。

之前談到的 DS 表示 Serial data input;SH_CP 表示 SHift register clock pin,又稱為 Clock Pin;ST_CP 表示 STorage register clock pin,又稱為 Latch Pin。

知道這些腳位的作用,接下來要連接七段顯示器,就不是難事了,只要小心不要接錯就好了,例如連接一個七段顯示器:

74HC595

實際上 Q0 到 Q7 腳位要怎麼接,要看你的資料序列如何安排,上面這個電路圖可以搭配以下的程式來依序顯示 H、E、L、L、O:

74HC595

注意!雖然我們沒有用到七段顯示器的小數點,不過,還是每次將八個數字推入暫存器,只是最後一個推入的數字是 0,以下是實際的效果:

影片示範

連接多個七段顯示器

如果想要連接多個七段顯示器,方式之一是串接多個 74HC595,每一次都準備好足夠數量的位數,例如兩個七段顯示器可以如下連接線路:

74HC595

如此,你可以維持三個輸入腳位,但可控制十六個輸出;另一個方式是 74HC595 結合多合一七段顯示器,例如:

74HC595

這樣的話,只需要一個 74HC595,不過為了控制數字的輪流顯示,需要多一個腳位,像上頭四個數字,就需要再用到四個腳位,不過還是比不使用 74HC595 少了五個腳位了,下面這個程式可用來控制上頭的七段顯示器:

74HC595

同樣要記得,雖然沒有使用到七段顯示器的小數點,我們還是一樣一次推入八個數字:

74HC595

底下是實際的執行效果:

影片示範

當然,速度不夠快,來寫個在 Arduino IDE 中類似的程式:

#include <Arduino.h>

void set7Seg(int number, int pos);

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

const int pinState[9][8] = {
  {0, 1, 1, 0, 0, 0, 0, 0}, // 1
  {1, 1, 0, 1, 1, 0, 1, 0}, // 2
  {1, 1, 1, 1, 1, 0, 1, 0}, // 3
  {0, 1, 1, 0, 0, 1, 1, 0}, // 4
  {1, 0, 1, 1, 0, 1, 1, 0}, // 5
  {1, 0, 1, 1, 1, 1, 1, 0}, // 6
  {1, 1, 1, 0, 0, 0, 0, 0}, // 7
  {1, 1, 1, 1, 1, 1, 1, 0}, // 8
  {1, 1, 1, 1, 1, 1, 0, 0}  // 9
};

void setup() {
    for(int i = 2; i < 9; i++) {
        pinMode(i, OUTPUT);
    } 
}

void loop() {
    set7Seg(8, 4); 
    set7Seg(7, 3); 
    set7Seg(6, 2);
    set7Seg(5, 1);
}

void set7Seg(int number, int pos) {
    for(int i = 5; i < 9; i++) {
        digitalWrite(i, 1);
    }

    digitalWrite(latchPin, 0);
    for(int i = 0;i < 8; i++) {
        digitalWrite(dataPin, pinState[number - 1][i]);
        digitalWrite(clockPin, 1);
        digitalWrite(clockPin, 0);
    }
    digitalWrite(latchPin, 1);

    digitalWrite(pos + 4, 0);
    delay(5);
}

底下是實際的執行效果:

影片示範