本文將示範用一個74HC595連接兩個7段顯示器,從00開始,每隔一秒加1顯示0~99。底下的電路圖改自《超圖解Arduino互動設計入門》動手做7-2,新增的七段顯示器與前一個並聯。
本實驗使用「共陰極」七段顯示器,按照上面的電路,若Arduino數位8和9腳都輸出低電位(LOW),則兩個顯示器將同步呈現一致的畫面;若數位9輸出高電位(HIGH)、數位8輸出低電位(LOW),則只有代表「個位數字」的顯示器會點亮,「十位數字」不顯示。
因此,七段顯示器的「共接腳」相當於「晶片選擇」腳;低電位時被選上、高電位時被關閉。
假設要在兩個顯示器顯示“24”,先傳送其中一個數字資料給74HC595,例如,個位數,同時將個位數的顯示器接地,另一個接高電位,維持一小段時間(5ms)之後再傳送另一個數字並切換顯示器。
只要在一秒鐘之內快速切換15次以上,人眼會因為視覺暫留現象而感到所有顯示器同時顯示了數字。
為了在不同的顯示器呈現個別數字,程式需要透過除法和餘除拆解每個數字:
以呈現兩個位數為例,為了方便程式循序操作,筆者把拆解後的數字全都存入digits陣列,選擇七段顯示器的接腳編號則存入SEG_PIN陣列:
如此,底下的敘述將能控制兩個顯示器呈現個別的數字:
本實驗電路的麵包板接線示範如下:
筆者把程式分成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};
趙老師好
我挑戰用兩顆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();
}
非常感謝MIHOXP的分享!
thanks,
jeffrey
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();
}