Arduino提高篇24—摇杆调节时钟时间
生活随笔
收集整理的這篇文章主要介紹了
Arduino提高篇24—摇杆调节时钟时间
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
對于電子時鐘而言,雖然我們可以在程序中對RTC芯片寫入初始時間數據,但按鍵調時功能也是必不可少的,它可以讓我們更加靈活的進行時間調節校準。本篇我們使用搖桿按鍵來調節時間數據,采用多級菜單的思路進行設計,關于多級菜單的介紹可以參考之前的文章Arduino提高篇15—搖桿操作OLED多級菜單。
1. 菜單顯示結構
本實驗中顯示菜單結構如下圖所示:
其中menu00是首頁正常的時間日期顯示界面,然后通過搖桿按鍵切換頁面,進行日期調節和時間調節選擇,然后對應跳轉年月日和時分秒的調節頁面。
根據結構圖,結合多級菜單思路,很容易得到搖桿按鍵與界面對應的相關數據。
//定義按鍵操作數據 KEY_TABLE table[9] = {{0, 0, 0, 0, 1, (*menu00)},{1, 1, 2, 0, 3, (*menu11)},{2, 1, 2, 0, 6, (*menu12)},{3, 3, 4, 1, 3, (*menu21)},{4, 3, 5, 1, 4, (*menu22)},{5, 4, 5, 1, 5, (*menu23)},{6, 6, 7, 2, 6, (*menu24)},{7, 6, 8, 2, 7, (*menu25)},{8, 7, 8, 2, 8, (*menu26)}, };2. 實驗材料
- Uno R3開發板
- 配套USB數據線
- 公對母杜邦線
- 面包板及配套連接線
- OLED顯示屏
- DS1302模塊
- 雙軸按鍵搖桿模塊
3. 實驗步驟
1. 根據原理圖搭建電路圖。
DS1302模塊的VCC和GND連接Uno開發板的3.3V和GND。DS1302模塊的CLK、DAT、RST對應連接Uno開發板的4、3、2引腳。OLED的VCC和GND分別連接開發板的3.3V和GND,OLED的SDA、SCL分別連接開發板的A4、A5引腳。雙軸按鍵搖桿模塊的VCC、GND分別連接開發板的5V、GND,模塊的X軸輸出、Y軸輸出分別連接開發板的模擬引腳A0、A1。
實驗原理圖如下圖所示:
實物連接圖如下圖所示:
2. 新建sketch,拷貝如下代碼替換自動生成的代碼并進行保存。
#include <DS1302.h> #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>Adafruit_SSD1306 oled(128, 64, &Wire, -1); DS1302 rtc(2, 3, 4); //對應DS1302的RST,DAT,CLK//搖桿相關變量 #define pinX A0 #define pinY A1int valueX = 0; int valueY = 0; unsigned char keyValue = 0;unsigned char menu = 0;int sec_temp; Time set_temp(2020, 4, 25, 21, 50, 50, 7);//用于存儲正在修改的時間數據//多級菜單相關變量 //定義按鍵結構體 typedef struct {unsigned char index;unsigned char up;unsigned char down;unsigned char left;unsigned char right;void (*operation)(void); } KEY_TABLE;unsigned char funIndex = 0; void (*current)(void); void menu00(void); void menu11(void); void menu12(void); void menu21(void); void menu22(void); void menu23(void); void menu24(void); void menu25(void); void menu26(void);//定義按鍵操作數據 KEY_TABLE table[9] = {{0, 0, 0, 0, 1, (*menu00)},{1, 1, 2, 0, 3, (*menu11)},{2, 1, 2, 0, 6, (*menu12)},{3, 3, 4, 1, 3, (*menu21)},{4, 3, 5, 1, 4, (*menu22)},{5, 4, 5, 1, 5, (*menu23)},{6, 6, 7, 2, 6, (*menu24)},{7, 6, 8, 2, 7, (*menu25)},{8, 7, 8, 2, 8, (*menu26)}, };void menu00(void) {if (menu == 1)//從調時界面退出后將調節后的時間數據寫入DS1302{initRTCTime(set_temp);menu = 0;}updatTime(); }void menu11(void) {menu = 1;//進入調時界面oled.clearDisplay();//清屏oled.setCursor(15, 2);//設置顯示位置oled.println("-Set Dat-");oled.setCursor(2, 25);//設置顯示位置oled.println("->1.Dat");oled.setCursor(2, 50);//設置顯示位置oled.println(" 2.Tim");oled.display(); // 開顯示 }void menu12(void) {oled.clearDisplay();//清屏oled.setCursor(15, 2);//設置顯示位置oled.println("-Set Tim-");oled.setCursor(2, 25);//設置顯示位置oled.println(" 1.Dat");oled.setCursor(2, 50);//設置顯示位置oled.println("->2.Tim");oled.display(); // 開顯示 }void menu21(void) {set_temp.yr++;oled.clearDisplay();//清屏oled.setCursor(2, 2);//設置顯示位置oled.print("->Yer:");oled.println(set_temp.yr);oled.setCursor(2, 25);//設置顯示位置oled.print(" Mon: ");oled.println(set_temp.mon);oled.setCursor(2, 48);//設置顯示位置oled.print(" Day: ");oled.println(set_temp.date);oled.display(); // 開顯示if (set_temp.yr >= 2030){set_temp.yr = 2019;} }void menu22(void) {set_temp.mon++;oled.clearDisplay();//清屏oled.setCursor(2, 2);//設置顯示位置oled.print(" Yer:");oled.println(set_temp.yr);oled.setCursor(2, 25);//設置顯示位置oled.print("->Mon: ");oled.println(set_temp.mon);oled.setCursor(2, 48);//設置顯示位置oled.print(" Day: ");oled.println(set_temp.date);oled.display(); // 開顯示if (set_temp.mon >= 12){set_temp.mon = 0;} }void menu23(void) {set_temp.date++;oled.clearDisplay();//清屏oled.setCursor(2, 2);//設置顯示位置oled.print(" Yer:");oled.println(set_temp.yr);oled.setCursor(2, 25);//設置顯示位置oled.print(" Mon: ");oled.println(set_temp.mon);oled.setCursor(2, 48);//設置顯示位置oled.print("->Day: ");oled.println(set_temp.date);oled.display(); // 開顯示if (set_temp.date >= 31){set_temp.date = 0;} }void menu24(void) {set_temp.hr++;oled.clearDisplay();//清屏oled.setCursor(2, 2);//設置顯示位置oled.print("->Hor: ");oled.println(set_temp.hr);oled.setCursor(2, 25);//設置顯示位置oled.print(" Min: ");oled.println(set_temp.min);oled.setCursor(2, 48);//設置顯示位置oled.print(" Sec: ");oled.println(set_temp.sec);oled.display(); // 開顯示if (set_temp.hr >= 24){set_temp.hr = 0;} }void menu25(void) {set_temp.min++;oled.clearDisplay();//清屏oled.setCursor(2, 2);//設置顯示位置oled.print(" Hor: ");oled.println(set_temp.hr);oled.setCursor(2, 25);//設置顯示位置oled.print("->Min: ");oled.println(set_temp.min);oled.setCursor(2, 48);//設置顯示位置oled.print(" Sec: ");oled.println(set_temp.sec);oled.display(); // 開顯示if (set_temp.min >= 60){set_temp.min = 0;} }void menu26(void) {set_temp.sec++;oled.clearDisplay();//清屏oled.setCursor(2, 2);//設置顯示位置oled.print(" Hor: ");oled.println(set_temp.hr);oled.setCursor(2, 25);//設置顯示位置oled.print(" Min: ");oled.println(set_temp.min);oled.setCursor(2, 48);//設置顯示位置oled.print("->Sec: ");oled.println(set_temp.sec);oled.display(); // 開顯示if (set_temp.sec >= 60){set_temp.sec = 0;} }//按鍵掃描函數 unsigned char keyScan(void) {static unsigned char keyUp = 1;valueX = analogRead(pinX);valueY = analogRead(pinY);if (keyUp && ((valueX <= 10) || (valueX >= 1010) || (valueY <= 10) || (valueY >= 1010))){delay(10);keyUp = 0;if (valueX <= 10)return 1;else if (valueX >= 1010)return 2;else if (valueY <= 10)return 3;else if (valueY >= 1010)return 4;} else if ((valueX > 10) && (valueX < 1010) && (valueY > 10) && (valueY < 1010))keyUp = 1;return 0; }void initRTCTime(Time t)//初始化RTC時鐘 {rtc.writeProtect(false); //關閉寫保護rtc.halt(false); //清除時鐘停止標志rtc.time(t);//向DS1302設置時間數據 }void show_time(Time tim) {char date[20];char timer[20];snprintf(date, sizeof(date), "%04d-%02d-%02d",tim.yr, tim.mon, tim.date);snprintf(timer, sizeof(timer), "%02d:%02d:%02d",tim.hr, tim.min, tim.sec);oled.clearDisplay();//清屏oled.setCursor(15, 2);//設置顯示位置oled.println("--CLOCK--");oled.setCursor(4, 25);//設置顯示位置oled.println(date);oled.setCursor(18, 50);//設置顯示位置oled.println(timer);oled.display(); // 開顯示 }void updatTime()//更新時間數據 {Time tim = rtc.time(); //從DS1302獲取時間數據set_temp = tim;//獲取時間數據已備調節if (tim.sec != sec_temp) { //一秒刷新一次show_time(tim);}sec_temp = tim.sec; }void setup() {oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);oled.setTextColor(WHITE);//開像素點發光oled.clearDisplay();//清屏oled.setTextSize(2); //設置字體大小 }void loop() {keyValue = keyScan();if (keyValue != 0) //每發生一次有效按鍵就根據按鍵功能獲取對應函數并執行{switch (keyValue)//獲取按鍵對應序號{case 1: funIndex = table[funIndex].right; break;case 2: funIndex = table[funIndex].left; break;case 3: funIndex = table[funIndex].down; break;case 4: funIndex = table[funIndex].up; break;}current = table[funIndex].operation;//根據需要獲取對應需要執行的函數(*current)();//執行獲取到的函數}if (menu == 0)//只有在首頁才進行時間刷新{updatTime();} }3. 連接開發板,設置好對應端口號和開發板類型,進行程序下載。
4. 實驗現象
搖桿操作調節時間,效果如下:
關注公眾號「TonyCode」,更多精彩內容分享。
回復「1024」獲取1000G學習資料。
個人博客
總結
以上是生活随笔為你收集整理的Arduino提高篇24—摇杆调节时钟时间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 上网行为管理设备的介绍,部署与使用
- 下一篇: 钓鱼网站原理实验