在〈mBlock & Arduino(17)七段顯示器之 HELLO!〉與〈mBlock & Arduino(17)四位數七段顯示器〉都談過七段顯示器,直接使用 Arduino 來控制七段顯示器的問題在於,它們會佔用到 Arduino 上許多輸出腳位,如果想減少 Arduino 上的腳位佔用,那麼可以使用 4511 或 74HC595 等驅動 IC,或者是選用市面上現成的七段顯示器模組。
74HC595 工作原理
使用 74HC595,你可以使用三個腳位來控制八個輸出,在正式看到 74HC595 腳位之前,可以先這麼想,如果你想要最後八個輸出為 10101101,那麼一開始令 ST_CP 腳位為低電位,然後提供腳位 DS 高電位,如下圖:
接著令 SH_CP 為高電位,將資料推入位移暫存器:
接著令 SH_CP 為低電位,DS 提供 0:
接著再令 SH_CP 為高電位,將資料推入位移暫存器,先前的 1 因此也被推進下一個暫存位置:
重複以上動作,繼續將 101101 推入位移暫存器,成為以下狀態:
此時令 ST_CP 為高電位,下方儲存暫存器會複製位移暫存器的值:
這時儲存暫存器的值就可以作為 Q0 到 Q7 腳位輸出之用,接下來若要繼續提供新的資料給位移暫存器,要令 ST_CP 為低電位,假設接下來又推進一個 1:
那麼原先最左邊的 1 被推至 Q7',一個 74HC595 可以提供八個輸出,如果想要提供 16 或更多輸出,可以串接 74HC595,從上可知,串接方式就是將上一顆 74HC595 的 Q7' 連接至下一顆 74HC595 的 DS。
連接七段顯示器
實際的 74HC595 有 16 個腳位,除了上面談到的 DS、SH_CP、ST_CP、Q0 到 Q7 以及 Q7' 之外,還有 VCC、GND、OE 與 MR 腳位:
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。
知道這些腳位的作用,接下來要連接七段顯示器,就不是難事了,只要小心不要接錯就好了,例如連接一個七段顯示器:
實際上 Q0 到 Q7 腳位要怎麼接,要看你的資料序列如何安排,上面這個電路圖可以搭配以下的程式來依序顯示 H、E、L、L、O:
注意!雖然我們沒有用到七段顯示器的小數點,不過,還是每次將八個數字推入暫存器,只是最後一個推入的數字是 0,以下是實際的效果:
連接多個七段顯示器
如果想要連接多個七段顯示器,方式之一是串接多個 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);
}
底下是實際的執行效果: