基于DS3231 RTC的Arduino报警系统:RTC显示与菜单接入故障排查
Arduino DS3231 RTC报警系统:按键进入菜单后自动返回实时显示的问题解决
问题核心原因
你的代码在loop()中无条件执行displayRTCValues()——哪怕已经切换到菜单页面(CurrentPage = ROOT_MENU),下一次循环依然会先调用实时显示函数,直接覆盖菜单内容,导致菜单仅短暂显示就被刷新。另外,按键状态变量btn_Accept_WasDown没有在按键处理后更新,可能导致重复触发或误判按键状态。
修复方案
- 给实时显示状态设置默认页面标识,仅当处于该状态时才执行RTC数据获取和实时显示。
- 完善按键状态跟踪,确保按键按下/释放的状态被正确记录。
- 调整代码执行顺序,优先处理页面逻辑,避免实时显示覆盖菜单。
修改后的完整loop()代码
// 先确保你已经定义了这些页面常量 #define DEFAULT_PAGE 0 #define ROOT_MENU 1 #define RTC_SETUP 2 void loop() { // 仅在默认页面时,才获取RTC数据并显示实时时间 if (CurrentPage == DEFAULT_PAGE) { t = rtc.getTime(); Day = rtc.getDOWStr(1); // 修复错误的赋值语法:原代码的逗号运算符无法实现十进制转换,直接赋值即可(库返回的已是十进制值) hh = t.hour; mm = t.min; ss = t.sec; dd = t.date; bb = t.mon; yy = t.year; displayRTCValues(); } // 处理按键输入,完善状态跟踪 bool acceptBtnState = btnIsUp(BTN_ACCEPT); if (acceptBtnState && !btn_Accept_WasDown) { // 等待按键释放,避免重复触发 while (btnIsUp(BTN_ACCEPT)) { delay(50); } // 切换到根菜单 CurrentPage = ROOT_MENU; lcd.clear(); // 更新按键状态,防止重复触发 btn_Accept_WasDown = true; } else if (!acceptBtnState && btn_Accept_WasDown) { // 按键释放后重置状态 btn_Accept_WasDown = false; } // 根据当前页面执行对应逻辑 switch (CurrentPage) { case ROOT_MENU: page_RootMenu(); break; case RTC_SETUP: page_RtcSetup(); break; // 其他页面请自行补充 } delay(500); }
关键修改点说明
- 条件执行实时显示:把RTC数据获取和
displayRTCValues()放到CurrentPage == DEFAULT_PAGE分支里,进入菜单后不再执行这部分代码,菜单内容不会被覆盖。 - 修复赋值语法:原代码的
hh = t.hour,DEC;是错误用法,DS3231库返回的时间参数本身就是十进制数值,直接赋值即可。 - 完善按键状态跟踪:添加按键释放后的状态重置,避免一次按键触发多次页面切换。
- 初始值设置:确保
CurrentPage的初始值为DEFAULT_PAGE,程序启动后默认进入实时显示状态。
额外提示
在菜单页面函数(比如page_RootMenu())中,需要添加退出菜单的逻辑(比如再次按下ACCEPT键时将CurrentPage设回DEFAULT_PAGE),这样才能从菜单回到实时显示状态。
内容的提问来源于stack exchange,提问作者magic stream jls
相关产品推荐
相关产品推荐

