使用 74HC595 驅動七段顯示器
Last updated
Last updated
七段顯示器是一種具有 8 顆 LED 的顯示元件,其中 7 顆 LED 用來顯示阿拉伯數字中不同部位的筆畫 (下圖 A 到 G 的部分),而另外一顆 LED 則用來當作小數點顯示使用 (如下圖所示的 DP)。
取決於模組是共陽極或共陰極的架構,對應的電路圖如下:
共陽極七段顯示器
或者是
共陰極七段顯示器
因此,最直接的七段顯示器操作方法,是使用八隻 GPIO 接腳連接至顯示器的 A、B、C、D、E、F、G 和 DP 的八隻訊號腳,並如同平常點亮 LED 的方式,獨立控制各訊號的開關,如此就能使七段顯示器亮起各種線段組合的結果。
使用 P7 ~ P14 連接共陽極七段顯示器的接線方式
七段顯示器畫面的各種組合 (不含 DP)
在上面的範例中,需使用 8 根 GPIO 接腳才能驅動一組七段顯示器,雖是直接易懂的做法,但卻很耗費 GPIO 接腳數目。舉例來說,以此作法驅動一組四位數的顯示器,則需要 32 根 GPIO (每位數 8 根 x 四位數) 才能實現。一般很少有開發板能提供 32 隻 GPIO 讓開發者使用,而且在使用如此多 GPIO 的狀況下,電路接線也會變得非常複雜。為了解決這個問題,可使用 shift register 晶片以減少所需的 GPIO 數量。接下來的教學,將以 74HC595 作為 shift register 的範例,介紹如何使用三根 GPIO 驅動一組七段顯示器,並以此為基礎,進一步擴充至使用單一 shift register 控制四位數七段顯示器。
為了減少控制七段顯示器所需的 GPIO 數目,可使用 shift register 以序列轉並列的資料傳送方式,將所需的訊號送至顯示器。其運作原理是,利用單一隻訊號輸入腳位,依序地送 8 個位元的資料 (即七段顯示器的八個筆畫) 進去 shift register。待全部資料都送進去後,shift register 即可將該 8 個位元的資料同時輸出至本身的 8 根輸出腳位,使七段顯示器顯示開發者所需的字樣。
操縱 74HC595 時,會使用到的腳位如下 (腳位名稱請參考 datasheet 上的定義):
輸入腳位
資料輸入訊號 (DS)
輸入資料的時脈訊號 (SHCP)
輸出資料的時脈訊號 (STCP)
輸出腳位
資料輸出訊號 x8 (Q0 ~ Q7)
控制腳位
啟動開關 (OE)
資料重置訊號 (MR)
接下來將說明如何接線使用 shift register。
下圖的麵包板接線示範了如何將 LinkIt 7697 連接到 74HC595,其中橘色線為輸入訊號、藍色線為輸出訊號。
使用下列的 sketch 程式碼可讓此例中的共陽極七段顯示器反覆顯示十六位元數字 (0 ~ 9 以及 A ~ F):
//
// Use one 74HC595 to control a common-anode seven-segment display
//
// pin 11 of 74HC595 (SHCP)
const int bit_clock_pin = 16;
// pin 12 of 74HC595 (STCP)
const int digit_clock_pin = 15;
// pin 14 of 74HC595 (DS)
const int data_pin = 14;
// digit pattern for a 7-segment display
const byte digit_pattern[16] =
{
B00111111, // 0
B00000110, // 1
B01011011, // 2
B01001111, // 3
B01100110, // 4
B01101101, // 5
B01111101, // 6
B00000111, // 7
B01111111, // 8
B01101111, // 9
B01110111, // A
B01111100, // b
B00111001, // C
B01011110, // d
B01111001, // E
B01110001 // F
};
unsigned int counter = 0;
void setup()
{
pinMode(data_pin, OUTPUT);
pinMode(bit_clock_pin, OUTPUT);
pinMode(digit_clock_pin, OUTPUT);
}
void update_one_digit(int data)
{
int i;
byte pattern;
// get the digit pattern to be updated
pattern = digit_pattern[data];
// turn off the output of 74HC595
digitalWrite(digit_clock_pin, LOW);
// update data pattern to be outputed from 74HC595
// because it's a common anode LED, the pattern needs to be inverted
shiftOut(data_pin, bit_clock_pin, MSBFIRST, ~pattern);
// turn on the output of 74HC595
digitalWrite(digit_clock_pin, HIGH);
}
void loop()
{
int i;
unsigned int digit_base;
counter++;
digit_base = 16;
// get the value to be displayed and update one digit
update_one_digit(counter % digit_base);
delay(500);
}
範例說明
構成每個數字筆畫的資訊被定義在 digit_pattern 陣列中。
呼叫 shiftOut() API 將筆畫資訊送至 shift register 裡。注意:由於此範例使用共陽極七段顯示器、開發板控制的是負極 (接地端) 訊號,所以 digit_pattern 中的資料需經反相 (~pattern) 處理後送至 shift register 才能正確地控制筆畫明滅。反之,若使用共陰極七段顯示器、開發板控制的是陽極端訊號,那麼 digit_pattern 與筆畫明滅的狀態就會一致,不需要額外做反相運算。
digit_clock_pin 是用來控制 74HC595 STCP 腳位的訊號,負責開/關 shift register 的輸出。
透過使用 shift register,此範例從原本需要 8 根 GPIO 才能控制單一個七段顯示器、減少為只需要三根 GPIO 即可完成。也就是說,用這個方法驅動 N 位數七段顯示器,就需要 N 個 shift register、3N 根 GPIO 訊號配合控制。接下來的章節將介紹另一個範例,說明如何做到使用單一 shift register 即能達成驅動四位數七段顯示器的方法。
當要顯示的數字超過個位數時,就需要搭配更多的七段顯示器。從上面的範例得知,要驅動 N 位數字就需要 N 個 shift register 以及 3N 隻訊號腳。接下來將介紹另一種可節省訊號腳的方式,達成使用單個 74HC595 即能驅動四位數七段顯示器。此例中將使用常見的四位數七段顯示器模組作為示範元件。
該顯示器模組的電路圖表示如下:
此為四位數共陽極七段顯示器,與 LinkIt 7697 的接線方式為:
與上個例子相似,從 LinkIt 7697 連至 74HC595 的輸入訊號為橘色線、輸出訊號為藍色線。此外,還需要額外的四根控制訊號 (黃色線) 用來開關模組上的各個顯示器。本範例使用下面的 sketch 程式碼驅動顯示器,並會如影片中的裝置持續累加顯示數字:
Sketch 程式碼
//
// Use one 74HC595 to control a 12-pin common-anode 4-digit seven-segment display with fast scanning
// the display: http://www.icshop.com.tw/product_info.php/products_id/19357
//
#define DELAY_FACTOR (100)
#define NUM_OF_DIGITS (4)
// 4 display on/off pin (for the common anode/cathode)
const int control_pins[NUM_OF_DIGITS] = {17, 5, 4, 3};
// pin 11 of 74HC595 (SHCP)
const int bit_clock_pin = 16;
// pin 12 of 74HC595 (STCP)
const int digit_clock_pin = 15;
// pin 14 of 74HC595 (DS)
const int data_pin = 14;
// digit pattern for a 7-segment display
const byte digit_pattern[16] =
{
B00111111, // 0
B00000110, // 1
B01011011, // 2
B01001111, // 3
B01100110, // 4
B01101101, // 5
B01111101, // 6
B00000111, // 7
B01111111, // 8
B01101111, // 9
B01110111, // A
B01111100, // b
B00111001, // C
B01011110, // d
B01111001, // E
B01110001 // F
};
int digit_data[NUM_OF_DIGITS] = {0};
int scan_position = 0;
unsigned int counter = 0;
void setup()
{
int i;
// set related pins as output pins
for (i = 0; i < NUM_OF_DIGITS; i++)
{
pinMode(control_pins[i], OUTPUT);
}
pinMode(data_pin, OUTPUT);
pinMode(bit_clock_pin, OUTPUT);
pinMode(digit_clock_pin, OUTPUT);
}
void update_one_digit()
{
int i;
byte pattern;
// turn off all digit
for (i = 0; i < NUM_OF_DIGITS; i++)
{
digitalWrite(control_pins[i], LOW);
}
// get the digit pattern of the position to be updated
pattern = digit_pattern[digit_data[scan_position]];
// turn off the output of 74HC595
digitalWrite(digit_clock_pin, LOW);
// update data pattern to be outputed from 74HC595
// because it's a common anode LED, the pattern needs to be inverted
shiftOut(data_pin, bit_clock_pin, MSBFIRST, ~pattern);
// turn on the output of 74HC595
digitalWrite(digit_clock_pin, HIGH);
// turn on the digit to be updated in this round
digitalWrite(control_pins[scan_position], HIGH);
// go to next update position
scan_position++;
if (scan_position >= NUM_OF_DIGITS)
{
scan_position = 0;
}
}
void loop()
{
int i;
unsigned int number;
unsigned int digit_base;
counter++;
// get the value to be displayed
number = counter / DELAY_FACTOR;
digit_base = 10;
// get every values in each position of those 4 digits based on "digit_base"
//
// digit_base should be <= 16
//
// for example, if digit_base := 2, binary values will be shown. If digit_base := 16, hexidecimal values will be shown
//
for (i = 0; i < NUM_OF_DIGITS; i++)
{
digit_data[i] = number % digit_base;
number /= digit_base;
}
// update one digit
update_one_digit();
delay(4);
}
範例說明
如何僅使用一個 shift register 來驅動四個顯示器?此例使用視覺暫留的特性,利用 sketch 的 loop() 函式快速更新顯示器上的各個位數。
各個位數的狀態開/關透過 control_pins 陣列進行控制。
當數字筆畫資訊送達至 shift register 後,sketch 即透過將 control_pins[scan_position] 訊號設成 HIGH 以開啟對應的七段顯示器。
由於每次的 loop() 函式僅會更新一個位數,為了達成視覺暫留效果,loop() 函式必須頻繁地不斷執行。
綜合以上要點,開發者即可使用單個 shift register 控制四位數顯示器。相較於原本「8 根 GPIO 才能控制一個七段顯示器」的做法,此範例僅需 LinkIt 7697 的 7 根控制訊號即能驅動四位數顯示器 (而非 32 根訊號),達到減少訊號腳使用量及降低電路佈線複雜度的效果。
在與使用者互動的各式場景中,七段顯示器是最為常用的顯示裝置之一,如何正確且有效率地使用七段顯示器也因此變得重要。在本教學中介紹了三種驅動七段顯示器的方法:
單純的 LED 開關機制。
使用單個 shift register 驅動單個七段顯示器。
透過視覺暫留,使用單一 shift register 驅動四個七段顯示器。
經由操作這三種方式的過程,可瞭解到七段顯示器的驅動原理、使用 shift register 作序列轉並列資料轉換的方式、以及視覺暫留特性的實際應用。在下一篇教學裡,將示範如何讓 LinkIt 7697 搭配七段顯示器專用驅動晶片 MAX7219 操作八位數七段顯示器模組。