在早期學習 Arduino時,有一篇筆記 Arduino筆記(4):在2x16 LCD上顯示 Hello World訊息,用到 2x16 LCD顯示模組時,需要接十幾條線,覺得有點麻煩。後來發現有一個模組 IIC/I2C/介面的 LCD1602轉接板,這個轉接板只佔用2個 IO ,如改接這個模組,只要 4條線就可以了。本實作就來看看如何連接這個轉接板,並將 RTC 時間顯示在 LCD上。可是筆記(4) 的作法是要先設定好時間,上傳程式,每次開機的日期、時間都一樣。想說再接兩個按鍵,加入時間設定,可以調整日期跟時間,比較方便。以下就看一下實作過程。
[安裝LiquidCrystal_I2C Library]
LiquidCrystal_I2C 程式庫提供顯示 LCD 1602 所需的功能。在 Arduino 選單, [Sketch 草稿碼] →下拉選擇 [Include Library 匯入程式庫] → [Manage Libraries 管理程式庫] 。在搜尋的地方輸入 LiquidCrystal_I2C,選擇以下紅色框線的 Library,按下右方的 [Install],出現 [Installed] 表示安裝完成。
[安裝DS1302 Library]
DS1302 程式庫提供 RTC時鐘所需的功能。在 Arduino 選單, [Sketch 草稿碼] →下拉選擇 [Include Library 匯入程式庫] → [Manage Libraries 管理程式庫] 。在搜尋的地方輸入 DS1302,選擇以下紅色框線的 Library,按下右方的 [Install],出現 [Installed] 表示安裝完成。
[材料]
- Arduino Uno x 1
- 1602 LCD模組 x 1
- DS1302 RTC模組 x 1
- IIC/I2C/介面 LCD1602轉接板 x 1
- 10K 電阻 x 2
- 按鍵 x 2
- 連接線 x 12
- 麵包板 x 1
[線路圖]
| Arduino UNO | I2C 1602轉接板 | RTC1302 | 按鍵 |
|---|---|---|---|
| 5V | VCC | VCC | - |
| GND | GND | - | - |
| A4(SDA) | SDA | - | - |
| A5(SCL) | SCL | - | - |
| Pin2 | - | RST | - |
| Pin3 | - | DAT | - |
| Pin4 | - | CLK | - |
| Pin8 | - | - | 按鍵1 |
| Pin9 | - | - | 按鍵2 |
按鍵1及2 一端VCC,另一端接 Arduino Pin8及Pin9 並連接電阻,電阻另一端接地。
[程式]
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DS1302.h>
uint8_t clock[8] = {0x0,0xe,0x15,0x17,0x11,0xe,0x0};
// DS1302 初始化設定
DS1302 rtc(2, 3, 4);
Time t;
bool adjust = false; // 調整 clock 模式 yes/no
// 調整 hour, minute, day ... mode
bool ahour, aminute, aday, amonth, ayear, rfin = false;
int stareb1, stareb2 = 0; // 按鍵狀態
// 變數 hour, minute, day, month, year
int hh, mm, dd, mo, yy;
const int button1 = 8; // 按鍵執行 設定/下一步/儲存
const int button2 = 9; // 按鍵調整時間日期/不儲存
// 設定 LCD 位址為 0x27,有 16 個字元 2 列
LiquidCrystal_I2C lcd(0x27,16,2);
void setup()
{
// buttons 1 and 2 are set as inputs
pinMode (button1, INPUT);
pinMode (button2, INPUT);
lcd.init(); // 初始化 lcd
lcd.backlight();
lcd.print("Initialising...");
lcd.createChar(2, clock);
Wire.begin();
// 第一次設定寫入 DS1302 RTC時鐘,之後可以加上註解
// rtc.setDOW(SUNDAY); // 設定每週星期幾?
// rtc.setTime(18, 39, 30); // 設定24小時時間 20:16:30
// rtc.setDate(26, 7, 2019); // 設定日期(日, 月, 年)
}
void loop()
{
// 在位置0,0 顯示時間
lcd.setCursor(0,0);
lcd.print("Time: ");
lcd.print(rtc.getTimeStr());
// 在位置0,1 顯示日期
lcd.setCursor(0,1);
lcd.print("Date: ");
lcd.print(rtc.getDateStr());
delay(1000);
// 調整時間日期按鍵1
stareb1 = digitalRead(button1);
if (stareb1 == HIGH)
{
adjust = true; // 調整時間模式開啟
t = rtc.getTime();
hh = t.hour; mm = t.min; dd = t.date;
mo = t.mon; yy = t.year;
int i = 1; // 跳到設定子畫面
delay(1000);
lcd.clear();
while (adjust)
{
// 調整小時
if (i == 1){ // 小時的子畫面為 1
ahour = true;
lcd.clear();
while(ahour) {
lcd.setCursor(0,0);
lcd.print(String("hour: ") + String(hh));
stareb1 = digitalRead(button1);
stareb2 = digitalRead(button2);
// 按鍵 2 用來增加小時數,只到 23
if (stareb2 == HIGH) {
hh++;
if (hh == 24) hh = 0;
delay (1000);
lcd.clear();
}
// 按鍵 1被按下,跳到下一個子畫面
if (stareb1 == HIGH) {
ahour = false;
i++;
delay (1000);
}
}
}
// 調整分鐘
if (i == 2){
aminute = true;
lcd.clear();
while(aminute) {
lcd.setCursor(0,0);
lcd.print(String("MIN: ") + String(mm));
stareb1 = digitalRead(button1);
stareb2 = digitalRead(button2);
if (stareb2 == HIGH) {
mm++;
if (mm == 60) mm = 0;
delay (1000);
lcd.clear();
}
if (stareb1 == HIGH) {
aminute = false;
i++;
delay (1000);
}
}
}
// 調整日期的天
if (i == 3){
aday = true;
lcd.clear();
while(aday) {
lcd.setCursor(0,1);
lcd.print(String("DATA: ") + String(dd));
stareb1 = digitalRead(button1);
stareb2 = digitalRead(button2);
if (stareb2 == HIGH) {
dd++;
if (dd == 32) dd = 1;
delay (1000);
lcd.clear();
}
if (stareb1 == HIGH) {
aday = false;
i++;
delay (1000);
}
}
}
// 調整月份
if (i == 4){
amonth = true;
lcd.clear();
while(amonth) {
lcd.setCursor(0,1);
lcd.print(String("Month: ") + String(mo));
stareb1 = digitalRead(button1);
stareb2 = digitalRead(button2);
if (stareb2 == HIGH) {
mo++;
if (mo == 13) mo = 1;
delay (1000);
lcd.clear();
}
if (stareb1 == HIGH) {
amonth = false;
i++;
delay (1000);
}
}
}
// 調整年份
if (i == 5){
ayear = true;
lcd.clear();
while(ayear) {
lcd.setCursor(0,1);
lcd.print(String("Year: ") + String(yy));
stareb1 = digitalRead(button1);
stareb2 = digitalRead(button2);
if (stareb2 == HIGH) {
yy++;
// 只能設定到 2030 年,回到 2019繼續
if (yy == 2030) yy = 2019;
delay (1000);
}
if (stareb1 == HIGH) {
ayear = false;
i++;
delay (1000);
}
}
}
// 調整結束,儲存設定值
if (i == 6){
rfin = true;
lcd.clear();
while(rfin) {
lcd.setCursor(0,0);
lcd.print("Save values?");
lcd.setCursor(0,1);
// 左邊按鍵 1,右邊按鍵 2
lcd.print(">>>> YES NO <<<<");
stareb1 = digitalRead(button1);
stareb2 = digitalRead(button2);
// 按鍵 2 不修改,回到初始畫面
if (stareb2 == HIGH) {
adjust = false;
rfin = false;
delay (1000);
}
// 按鍵 1 儲存改變值,回到初始畫面
if (stareb1 == HIGH) {
adjust = false;
rfin = false;
rtc.setTime(hh, mm, 0);
rtc.setDate(dd, mo, yy);
lcd.clear();
delay (1000);
}
}
}
}
}
}
[實作結果]
實作前,IIC / I2C轉接板是跟 LCD 分開的,我先找了排針座銲在 LCD模組上,方便轉接板拆卸。設定日期及時間的影片:
[參考資料]
- Instructables:Arduino Clock With DS3231 and LCD1602



大大您好:
回覆刪除調整時間的部分寫得很詳細,真正讚!
可否請教:
在我的電腦裡
#include 要改成
#include 要改成
然後要ThreeWire myWire(6,5,7);
再RtcDS1302 Rtc(myWire);
Time t;這行出錯:
'Time' does not name a type
目前卡在這裡,有空請指導,謝謝!
我覺得是不是沒有安裝正確的函數庫或是少了#include需要時間的函數庫?程式會用到跟時間有關的函數庫是DS1302.h,網路上有其他的DS1302函數庫,您留言的#include看不出來是哪個?您可以再檢查一下。
刪除張貼留言