如何让Arduino的millis()保持为0?反向秒表开发问题求助
Arduino反向秒表:解决millis()自动计时问题
首先明确:millis()函数从Arduino上电初始化后就会持续计数,无法强制让它在调用前保持为0,但我们可以通过记录起始时间戳的方式实现"按下按钮才开始计时"的需求,同时原代码中的阻塞式循环也需要优化,避免影响按钮响应。
问题分析
millis()的运行机制是硬件层面决定的,上电即启动计数,无法重置,但可以通过计算时间差实现相对计时。- 原代码中
Start()函数的while(n)循环会阻塞主loop(),导致除显示外的其他操作(比如重新触发按钮)无法响应。
修正后的完整代码
#include "SevSeg.h" const int buttonStart = 11; const int button2 = 12; const int button3 = 13; const int countdownValue = 10; // 初始倒计时时长(秒) SevSeg Display; // 计时状态控制变量 bool isCounting = false; unsigned long startTime = 0; int remainingTime = countdownValue; void setup() { Serial.begin(9600); pinMode(buttonStart, INPUT_PULLUP); // 使用内部上拉电阻,避免引脚浮针 byte numDigits = 2; byte digitPins[] = {9, 8}; byte segmentPins[] = {10, 2, 3, 4, 5, 6, 7, 1}; bool resistorsOnSegments = true; bool updateWithDelays = true; byte hardwareConfig = COMMON_ANODE; Display.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments); Display.setBrightness(100); } void loop() { // 处理开始按钮输入,带消抖 if (digitalRead(buttonStart) == LOW) { delay(50); // 简单消抖,避免误触 if (digitalRead(buttonStart) == LOW && !isCounting) { isCounting = true; startTime = millis(); // 记录计时启动的时间戳 remainingTime = countdownValue; } } // 处理倒计时逻辑 if (isCounting) { unsigned long elapsedTime = millis() - startTime; remainingTime = countdownValue - (elapsedTime / 1000); // 倒计时结束后停止计时 if (remainingTime <= 0) { remainingTime = 0; isCounting = false; } } // 持续更新数码管显示 Display.setNumber(remainingTime, 1); Display.refreshDisplay(); }
关键改进点
- 时间差替代直接调用millis():通过
startTime记录按钮按下时的millis()值,每次计算millis() - startTime得到已流逝的时间,实现"按下才开始计时"的效果,完全规避millis()上电就运行的特性。 - 非阻塞式逻辑:移除原代码中的
while循环,所有逻辑在loop()中循环执行,保证按钮输入能被及时响应。 - 按钮优化:使用
INPUT_PULLUP模式简化硬件接线,加入消抖代码避免误触发。 - 状态化管理:用
isCounting标记计时状态,逻辑更清晰,后续可轻松扩展暂停、重置等功能。
内容的提问来源于stack exchange,提问作者Subhan Malik
相关产品推荐
相关产品推荐

