/**
* 竞赛电子秒表 - HardwareTimer库版
* 功能:使用STM32硬件定时器实现精确1秒计时,双数码管显示时间
*/
#include <Arduino.h> // Arduino核心库
#include <TM1637Display.h> // TM1637数码管驱动库
//代码填空1:
// ==================== 引脚定义 ====================
//代码填空1:
// ===================== 引脚定义 =====================
#define CLK1 PB0 // 左侧数码管时钟引脚(接PB0)
#define DIO1 PB1 // 左侧数码管数据引脚(接PB1)
#define CLK2 PB2 // 右侧数码管时钟引脚(接PB2)
#define DIO2 PB3 // 右侧数码管数据引脚(接PB3)
// ==================== 创建对象 ====================
TM1637Display display1(CLK1, DIO1); // 左侧显示屏(显示时+分)
TM1637Display display2(CLK2, DIO2); // 右侧显示屏(显示秒)
// ==================== 全局变量 ====================
// volatile关键字:告诉编译器这些变量可能被中断修改,禁止优化
volatile unsigned int hours = 12; // 小时(0-23),初始12
volatile unsigned int minutes = 34; // 分钟(0-59),初始34
volatile unsigned int seconds = 56; // 秒数(0-59),初始56
volatile bool colonState = true; // 冒号状态,true=亮,false=灭
volatile bool timeUpdated = false; // 时间更新标志,true=需要刷新显示
// ==================== 定时器对象 ====================
HardwareTimer *MyTimer; // 硬件定时器指针
// ==================== 中断服务函数 ====================
// 每1秒自动调用一次(由TIM3硬件定时器触发)
void timerCallback() {
// 1. 秒数+1
seconds++;
// 2. 进位处理(60进制 -> 24小时制)
if (seconds >= 60) { // 满60秒
seconds = 0; // 秒归零
minutes++; // 分钟+1
if (minutes >= 60) { // 满60分钟
minutes = 0; // 分钟归零
hours++; // 小时+1
if (hours >= 24) { // 满24小时
hours = 0; // 小时归零(第二天)
}
}
}
// 3. 冒号状态翻转(实现每秒闪烁效果)
colonState = !colonState;
// 4. 通知主循环:时间已更新,需要刷新显示
timeUpdated = true;
}
//补充代码2:
// ==================== 初始化函数 ====================
void setup() {
// 设置显示屏亮度(0-7,数值越大越亮)
// 清空显示屏(熄灭所有段)
// 初始化硬件定时器TIM3
// 设置定时器溢出频率为1Hz(即每1秒触发一次中断)
// 绑定中断回调函数(1秒到时自动调用timerCallback)
// 启动定时器(开始计时)
// 初始显示一次(显示12:34 56)
}
// ==================== 主循环 ====================
void loop() {
// 检查时间是否需要更新
if (timeUpdated) {
timeUpdated = false; // 清除标志
updateDisplay(); // 刷新显示
}
// 如果没有更新标志,就什么都不做(等待下次中断)
}
//代码补充3:
// ==================== 显示刷新函数 ====================
void updateDisplay() {
// ----- 临界区保护:读取共享变量时禁止中断 -----
noInterrupts(); // 关中断
unsigned int h = hours; // 读取小时
unsigned int m = minutes; // 读取分钟
unsigned int s = seconds; // 读取秒
bool colon = colonState; // 读取冒号状态
interrupts(); // 开中断
// ----- 左侧显示屏:显示 HH:MM -----
// 将小时和分钟组合成HHMM格式(例如12:34 -> 1234)
// showNumberDecEx参数说明:
// - timeValue: 要显示的数字
// - colon ? 0x80 : 0x00: 控制冒号显示(0x80点亮冒号)
// - true: 前导零显示
// - 4: 显示4位数
// - 0: 从第0位开始显示
// ----- 右侧显示屏:显示 SS(秒)-----
// 构造段码数组(4个数码管的显示数据)
uint8_t data2[] = {
0, // 第1位:不显示
0, // 第2位:不显示
display2.encodeDigit(s / 10), // 第3位:秒的十位
display2.encodeDigit(s % 10) // 第4位:秒的个位
};
// setSegments参数说明:
// - data2: 段码数组
// - 4: 数组长度(4个数码管)
// - 0: 从第0位开始显示
display2.setSegments(data2, 4, 0);
}