轻松打造 Arduino 秒表:按钮触发计时器
组件与物料
| 组件 | 说明 | 数量 |
|---|---|---|
| Arduino UNO | 任意 Arduino 型号均可 | 1 |
| 按钮(非自锁) | 需配合下拉电阻(示例使用 1kΩ) | 1 |
| 电阻 10kΩ | 上拉/下拉用途 | 1 |
应用与在线服务
| 工具 | 说明 |
|---|---|
| Arduino IDE | 代码编写与上传 |
项目简介
在一个趣味项目中需要按键触发的 Arduino 秒表,功能虽简单但代码复用性强,分享出来希望能为他人节省约 1 小时编码时间。
EEPROM 非易失性存储

Arduino 断电不丢失数据的内部存储。使用 #include <EEPROM.h> 库(默认已安装)即可读写。
中断机制

当指定引脚电平变化(如拉高)时,强制 CPU 暂停当前任务执行中断服务程序 (ISR)。无需额外库:


项目代码结构
宏定义与引用
#include <EEPROM.h>
#define interruptPin 2
#define eeAddress 0 // EEPROM 存储地址(float 占 4 字节)
float starttime = 0;
float endtime = 0;
float resulttime = 0, oldresulttime = 0;
引用 EEPROM 库,按钮接引脚 2。UNO 的 ATmega328 提供 1024 字节 EEPROM,选择地址 0 纯属整理习惯。
setup() 初始化
void setup() {
Serial.begin(9600);
while (!Serial) { ; } // 等待原生 USB 端口连接
Serial.println("Serial comms are ready sir!:.. bip bip");
attachInterrupt(digitalPinToInterrupt(interruptPin), refreshTime, CHANGE);
}
初始化串口通信。attachInterrupt 在引脚电平变化时触发 refreshTime,即按下和释放各触发一次。下拉电阻确保静止时引脚保持低电平。
loop() 主循环
void loop() { }
主循环留空,所有逻辑在中断处理,您可在此添加其他业务逻辑。
中断服务函数 refreshTime()
void refreshTime() {
if (digitalRead(interruptPin)) { // 按下:上升沿
starttime = millis();
Serial.print("Start time: ");
Serial.println(starttime);
} else if (digitalRead(interruptPin) == LOW) { // 释放:下降沿
endtime = millis();
resulttime = endtime - starttime;
Serial.print("End time: ");
Serial.println(endtime);
Serial.print("Result time: ");
Serial.println(resulttime);
WhatsNewEeprom(); // 存入 EEPROM
}
}
检测电平变化方向,记录开始/结束时间并计算差值,最后写入 EEPROM。
EEPROM 写入检查 WhatsNewEeprom()
void WhatsNewEeprom() {
Serial.println("-----------checking eeprom");
EEPROM.get(eeAddress, oldresulttime);
Serial.print("oldresulttime"); Serial.println(oldresulttime);
Serial.print("resulttime"); Serial.println(resulttime);
if (resulttime != oldresulttime) {
EEPROM.put(eeAddress, resulttime);
Serial.print("-----Ding! New time recorded in eeprom: "); Serial.println(resulttime);
} else {
Serial.println("No new time found, eeprom was not disturbed");
}
}
对比当前值与存储值,仅当不同时更新,避免不必要的写入损耗。
进阶:按钮消抖

人类按键在单片机眼中极慢,会产生高低电平快速跳变(抖动)。可通过软件或硬件消抖:
- 软件消抖:代码延时判断
- 硬件消抖:并联电容(推荐)


我在检测引脚并联 220nF 电容到地,电容“吸收”快速电压变化,有效抑制抖动。
完整代码
arduino chronometer (Arduino)
// coded by Javier Muñoz 23/10/2017
// questions to javimusama@gmail.com
#include <EEPROM.h>
#define interruptPin 2
#define eeAddress 0
float starttime = 0;
float endtime = 0;
float resulttime = 0, oldresulttime = 0;
void setup() {
Serial.begin(9600);
while (!Serial) { ; }
Serial.println("Serial comms are ready sir!:.. bip bip");
attachInterrupt(digitalPinToInterrupt(interruptPin), refreshTime, CHANGE);
}
void loop() {
// 此处可添加其他逻辑
// EEPROM 中存储的上次测量时间(毫秒)"float resulttime"
}
void refreshTime() {
if (digitalRead(interruptPin)) {
starttime = millis();
Serial.print("Start time: ");
Serial.println(starttime);
} else if (digitalRead(interruptPin) == LOW) {
endtime = millis();
resulttime = endtime - starttime;
Serial.print("End time: ");
Serial.println(endtime);
Serial.print("Result time: ");
Serial.println(resulttime);
WhatsNewEeprom();
}
}
void WhatsNewEeprom() {
Serial.println("-----------checking eeprom");
EEPROM.get(eeAddress, oldresulttime);
Serial.print("oldresulttime"); Serial.println(oldresulttime);
Serial.print("resulttime"); Serial.println(resulttime);
if (resulttime != oldresulttime) {
EEPROM.put(eeAddress, resulttime);
Serial.print("-----Ding! New time recorded in eeprom: "); Serial.println(resulttime);
} else {
Serial.println("No new time found, eeprom was not disturbed");
}
}
原理图
按钮配合下拉电阻的简单连接
制造工艺
- 用 Adafruit 60 LED NeoPixel 环形灯和 Arduino 制作时尚挂钟
- DIY Arduino单词时钟 – 极简优雅的实时文字显示
- 用 Arduino Nano 和 Nokia 5110 LCD 自制 20kHz 示波器:简易 DIY 指南
- DIY 蓝牙控制 Arduino 间谍小车
- FlickMote:基于手势的智能家居红外遥控器
- DIY Arduino TV-B-Gone:万能关机遥控器
- 自制大尺寸LED主时钟带闹钟功能 — 12米外清晰可见
- 自制简易红外避障传感器:IR LED + 光电二极管 + Arduino
- Find Me:基于 Arduino 与蓝牙的智能寻物器制作指南
- Arduino 项目优化供电方案:从按键开关到电池监测与数据记录
- Arduino 串口简易计算器:两数四则运算演示
- 用 DS1302 RTC 和 Arduino UNO 制作可靠闹钟