基于Arduino的24小时数码管时钟复位异常问题求助
Arduino四位七段数码管24小时时钟复位异常问题解决
问题根源
你的时钟复位异常主要由两个核心问题导致:
- 变量类型溢出:
startTime被定义为int类型,但millis()返回的是unsigned long(最大值约49天),int的最大值仅为32767,运行几分钟后就会溢出,导致时间计算完全混乱。 - 复位逻辑漏洞:当触发
displayNum > 2359的复位条件时,你直接将now赋值为millis()而非millis() - startTime,且未重新计算sec、minute,导致后续循环的时间计算出现断层,出现跳数、停摆现象。
解决方案
方案一:用取模实现自动24小时循环(推荐)
这种方式无需手动判断复位,通过数学取模自动实现循环,逻辑更简洁可靠,同时修正变量类型避免溢出:
#include "SevSeg.h" SevSeg sevseg; unsigned long startTime = 0; // 改为unsigned long,避免溢出 int sec; int minute; void setup(){ byte numDigits = 4; byte digitPins[] = {10, 11, 12, 13}; byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4}; bool resistorsOnSegments = true; bool updateWithDelaysIn = true; byte hardwareConfig = COMMON_ANODE; sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); sevseg.setBrightness(100); Serial.begin(9600); } void loop(){ sevseg.refreshDisplay(); unsigned long now = millis() - startTime; now /= 50; // 测试加速用,实际场景改为1000 // 计算总测试秒数对应的24小时制时间 unsigned long totalTestSeconds = now; unsigned long totalMinutes = totalTestSeconds / 60; totalMinutes %= 1440; // 24*60=1440分钟,超过自动取模循环 minute = (totalMinutes / 60) * 100; sec = totalTestSeconds % 60; int displayNum = minute + sec; sevseg.setNumber(displayNum, 2); Serial.println(displayNum); }
方案二:修正原复位逻辑
如果你想保留原有的复位判断方式,需要修正变量类型和复位时的计算逻辑:
#include "SevSeg.h" SevSeg sevseg; unsigned long startTime = 0; // 改为unsigned long int sec; int minute; void setup(){ byte numDigits = 4; byte digitPins[] = {10, 11, 12, 13}; byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4}; bool resistorsOnSegments = true; bool updateWithDelaysIn = true; byte hardwareConfig = COMMON_ANODE; sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); sevseg.setBrightness(100); Serial.begin(9600); } void loop(){ sevseg.refreshDisplay(); unsigned long now = millis() - startTime; now /= 50; // 测试加速用 sec = now % 60; minute = 100*(now / 60); int displayNum = sec + minute; if(displayNum > 2359){ startTime = millis(); now = 0; // 重置当前时间差为0 sec = now % 60; minute = 100*(now / 60); displayNum = sec + minute; } sevseg.setNumber(displayNum,2); Serial.println(displayNum); }
修改说明
- 变量类型修正:将
startTime和now改为unsigned long,彻底避免整数溢出问题,这是解决长时间运行后异常的关键。 - 循环逻辑优化:方案一通过对总分钟数取
1440(24小时总分钟数)的模,自动实现24小时循环,无需手动复位,避免了复位时的逻辑错误。 - 复位逻辑修复:方案二中,复位时重新计算
now、sec、minute,确保复位后显示正确的0值,且后续循环的时间计算正常。
内容的提问来源于stack exchange,提问作者Shrimpstone
相关产品推荐
相关产品推荐

