☛ 功能說明
使用 Arduino 開發板讀取 DS1302 時鐘晶片應用電路的日期時間及 DHT11 溫濕度感測器的溫濕度數值,以按鍵開關切換八位數七段顯示器顯示日期、時間及溫濕度,以 Serial Monitor 視窗顯示日期時間及調整日期時間。 當七段顯示器顯示日期時,按一下按鍵開關,切換至顯示時間,當七段顯示器顯示時間時,按一下按鍵開關,切換至顯示溫濕度,當七段顯示器顯示溫濕度時,按一下按鍵開關,切換至設定模式,七段顯示器不顯示日期、時間及溫濕度,透過 Serial Monitor 監控視窗顯示並設定時間。
☛ 使用材料
Arduino UNO R3 開發板 × 1、MAX7219 八位數七段顯示器模組、DHT11 溫濕度感測器模組、按鍵開關、電阻 10KΩ × 3、DS1302 時鐘晶片 × 1、32.768kHz 晶振 × 1、DS1302 函式庫 、MAX7219 LED 控制函式庫、DHT11 第三方函式庫 。
☛ 電路圖及麵包板接線圖
☛ 程式碼
#include <stdio.h> #include <string.h> #include <DS1302.h> #include <DHT.h> #include <LedControl.h> uint8_t CE_PIN = 5; // CE(DS1302 pin5) -> Arduino D5 uint8_t IO_PIN = 6; // IO(DS1302 pin6) -> Arduino D6 uint8_t SCLK_PIN = 7; // SCLK(DS1302 pin7) -> Arduino D7 LedControl lc=LedControl(12,11,10,1); char buf[50]; // 日期變數緩存 char day[10]; String comdata = ""; // 序列埠數據緩存 int numdata[7] ={0}, j = 0, mark = 0; char led_Data[8]; // 時間顯示的資料格式 00-00-00 const int sw=8; //按鍵開關連接至數位接腳第 8 腳。 const int debounceDelay=20; //按鍵開關穩定所需的時間 int val; //按鍵開關狀態 int swValue=0; //按鍵開關數值 int humidity; //濕度變數 int temperature; //溫度變數 DS1302 rtc(CE_PIN, IO_PIN, SCLK_PIN); // 創建 DS1302 物件 DHT dht; // 產生一個 dht 物件 void setup() { Serial.begin(9600); //設定序列埠傳輸速率為9600bps pinMode(sw,INPUT_PULLUP); //設定數位第 8 腳為輸入模式 ( 使用內部上拉電阻 )。 rtc.write_protect(false); rtc.halt(false); dht.setup(9); // DHT11 數據接腳連接數位接腳 9 lc.shutdown(0,false); // The MAX72XX is in power-saving mode on startup,we have to do a wakeup call lc.setIntensity(0,8); // Set the brightness to a medium values and clear the display lc.clearDisplay(0); } void loop() { val=digitalRead(sw); //讀取按鍵狀態。 if(val==LOW) //按鍵開關被按下? { swValue++; //按鍵開關數值加一 delay(debounceDelay); //消除按鍵開關的不穩定狀態 ( 機械彈跳 )。 while(digitalRead(sw)==LOW) //按鍵開關已放開? ; //等待放開按鍵開關。 } switch(swValue) { case 0: //七段顯示器顯示日期 getDate(); break; case 1: //七段顯示器顯示時間 getTime(); break; case 2: //七段顯示器顯示溫濕度 delay(dht.getMinimumSamplingPeriod());// 根據溫濕度感測器型號來選取取樣時間 getDHT11(); break; case 3: //進入日期時間設定模式 mode_Setup(); for(int i=7;i>=0;i--) led_Data[i]='-'; print_time(); //序列埠監控視窗顯示日期時間 break; case 4: swValue=0; break; } if(swValue==2) displayDHT11(); else display(); delay(1000); } void mode_Setup() //設定模式,由 USB 監控視窗設定及顯示日期時間 { while (Serial.available() > 0) // 當序列埠有數據的時候,將數據拼接到變數comdata { comdata += char(Serial.read()); delay(2); mark = 1; } // 以逗號分隔分解 comdata 的字串,分解結果變成轉換成數位到numdata[] 陣列 if(mark == 1) { Serial.print("You inputed : "); Serial.println(comdata); for(int i = 0; i < comdata.length() ; i++) { if(comdata[i] == ',' || comdata[i] == 0x10 || comdata[i] == 0x13) { j++; } else { numdata[j] = numdata[j] * 10 + (comdata[i] - '0'); } } // 將轉換好的numdata湊成時間格式,寫入DS1302 Time t(numdata[0], numdata[1], numdata[2], numdata[3], numdata[4], numdata[5], numdata[6]); rtc.time(t); mark = 0;j=0; comdata = String(""); // 清空 comdata 變數,以便等待下一次輸入 /* 清空 numdata */ for(int i = 0; i < 7 ; i++) numdata[i]=0; } } void print_time() { Time t = rtc.time(); // 從 DS1302 獲取當前時間 memset(day, 0, sizeof(day)); // 將星期從數位轉換為名稱 switch (t.day) { case 1: strcpy(day, "Sunday"); break; case 2: strcpy(day, "Monday"); break; case 3: strcpy(day, "Tuesday"); break; case 4: strcpy(day, "Wednesday"); break; case 5: strcpy(day, "Thursday"); break; case 6: strcpy(day, "Friday"); break; case 7: strcpy(day, "Saturday"); break; } // 將日期代碼格式化湊成buf等待輸出 snprintf(buf, sizeof(buf), "%s %04d-%02d-%02d %02d:%02d:%02d", day, t.yr, t.mon, t.date, t.hr, t.min, t.sec); Serial.println(buf); // 輸出日期到序列埠 } char transChar(int number) // 數值轉換成字元函式 { char value; switch(number) { case 0: value='0'; break; case 1: value='1'; break; case 2: value='2'; break; case 3: value='3'; break; case 4: value='4'; break; case 5: value='5'; break; case 6: value='6'; break; case 7: value='7'; break; case 8: value='8'; break; case 9: value='9'; break; } return value; } void getDate() // 取得 DS1302 時鐘晶片的日期,轉換成顯示的日期格式 { Time t = rtc.time(); led_Data[0]=transChar(t.yr/1000); // 西元年 led_Data[1]=transChar(t.yr%1000/100); led_Data[2]=transChar(t.yr%1000%100/10); led_Data[3]=transChar(t.yr%1000%100%10); led_Data[4]=transChar(t.mon/10); // 月 led_Data[5]=transChar(t.mon%10); led_Data[6]=transChar(t.date/10); // 日 led_Data[7]=transChar(t.date%10); } void getTime() // 取得 DS1302 時鐘晶片的時間,轉換成顯示的時間格式 { Time t = rtc.time(); led_Data[0]=transChar(t.hr/10); // 時 led_Data[1]=transChar(t.hr%10); led_Data[2]='-'; led_Data[3]=transChar(t.min/10); // 分 led_Data[4]=transChar(t.min%10); led_Data[5]='-'; led_Data[6]=transChar(t.sec/10); // 秒 led_Data[7]=transChar(t.sec%10); } void getDHT11() // 取得 DHT11 溫濕度,轉換成顯示格式 { humidity = dht.getHumidity(); // 讀取感測器的濕度值 temperature = dht.getTemperature(); // 讀取感測器的溫度值 temperature=temperature*100; humidity=humidity*100; led_Data[0]=transChar(temperature/1000); //將溫度值轉換成七段顯示器顯示格式 led_Data[1]=transChar(temperature%1000/100); led_Data[2]=transChar(temperature%1000%100/10); led_Data[3]='C'; led_Data[4]=transChar(humidity/1000); //將濕度值轉換成七段顯示器顯示格式 led_Data[5]=transChar(humidity%1000/100); led_Data[6]=transChar(humidity%1000%100/10); led_Data[7]='H'; } void display() // 顯示時間函式 { for(int i=7;i>=0;i--) lc.setChar(0,7-i,led_Data[i],false); } void displayDHT11() // 顯示溫度及濕度 { for(int i=7;i>=0;i--) { if(i==1 || i==5) lc.setChar(0,7-i,led_Data[i],true); //七段顯示器顯示帶小數點數位 else lc.setChar(0,7-i,led_Data[i],false); //七段顯示器顯示不帶小數點數位 } }