蓝桥杯单片机第三周学习笔记
本周核心围绕电子钟程序实现展开,复现过程中遇到多个典型问题,同时掌握并巩固了单片机开发的关键基础逻辑,以下为问题复盘与核心知识点总结:
一、复现程序遇到的问题及解决方法
问题 1:按键 5/6 位数加减,三目运算符逻辑卡顿
按键 5 实现位数加、按键 6 实现位数减,核心是通过三目运算符判断小时 / 分钟的边界值(小时 0-23、分钟 0-59),复现时遗忘三目运算书写逻辑,需重点记忆。
case 5: // 位数加,Seg_Mode1=时钟设置,Seg_Mode2=闹钟设置
if (Seg_Mode == 1) {
Clock_Set[Clock_Set_Index]++;
// 索引0=小时(边界24),非0=分钟(边界60),达到边界置0
if(Clock_Set[Clock_Set_Index] == (Clock_Set_Index == 0?24:60)) Clock_Set[Clock_Set_Index] = 0;
}
if (Seg_Mode == 2) {
Alarm[Clock_Set_Index]++;
if(Alarm[Clock_Set_Index] == (Clock_Set_Index == 0?24:60)) Alarm[Clock_Set_Index] = 0;
}
break;
case 6: // 位数减,unsigned char减到0再减为255,以此为判断条件
if(Seg_Mode == 1) {
Clock_Set[Clock_Set_Index]--;
if(Clock_Set[Clock_Set_Index] == 255) Clock_Set[Clock_Set_Index] = (Clock_Set_Index == 0?23:59);
}
if (Seg_Mode == 2) {
Alarm[Clock_Set_Index]--;
if(Alarm[Clock_Set_Index] == 255) Alarm[Clock_Set_Index] = (Clock_Set_Index == 0?23:59);
}
break;
问题 2:闹钟响铃 LED1s 周期闪烁,LED_Proc 与时间函数联动缺失
需通过中间变量(Alarm_Ring/LED) 实现两个函数的联动,复现时没想到中间变量的桥梁作用,解决后逻辑清晰:先通过标志位判断闹钟是否响铃,再由时间函数控制中间变量实现闪烁。
void LED_Proc() {
// 时钟时间与闹钟时间完全匹配,置响铃标志位
if (Clock_Seg[0] == Alarm_Set[0] && Clock_Seg[1] == Alarm_Set[1] && Clock_Seg[2] == Alarm_Set[2]) {
Alarm_Ring = 1;
}
if (Alarm_Ring == 1) { // 响铃时控制LED闪烁
P2_3 = 0; // 开启LED控制
P1 = LED; // 中间变量LED由时间函数控制,实现闪烁
} else { // 未响铃时关闭所有LED
P2_3 = 1;
P1 = 0xff;
}
}
问题 3:闹钟响铃段位闪烁,多余条件导致 bug + 异或逻辑遗忘
问题点:
-
多余添加
Alarm_Ring == 1判断,导致非目标段位常亮; -
没想到通过异或赋值实现段位闪烁(0x0f 控制低四位、0xf0 控制高四位)。
核心逻辑:
根据小时是否≥12,分别控制前四位 / 后四位闪烁,依托 500ms 定时器实现 1s 周期(两次 500ms 异或完成一次亮灭)。
if (++Timer_500ms == 500) {
Timer_500ms = 0;
Seg_Flag ^= 1;
if (Clock_Seg[0] < 12) {
LED ^= 0x0f; // 小时<12,低四位(后四位)闪烁
} else if(Clock_Seg[0] >= 12) {
LED ^= 0xf0; // 小时≥12,高四位(前四位)闪烁
}
}
二、已掌握需重点巩固的核心逻辑
1. 1s 周期执行语句实现(时间函数核心)
定义毫秒级定时器变量,自增到 1000 时置 0,后续紧跟需执行的语句,即可实现非阻塞 1s 周期执行,是定时操作的基础方法。
if (++Timer_1000ms == 1000) {
Timer_1000ms = 0;
// 此处添加1s周期需要执行的代码
}
2. 按键 / 数码管非阻塞性减速(防抖动 / 降刷新)
通过减速标志位 + 时间函数计数实现非阻塞延时,避免程序卡死,可灵活调整延时时间,提升按键响应与显示屏稳定性。
步骤 1:在 Proc 函数中添加减速判断
void Seg_Proc() {
if(Seg_Slow_Down) return; // 未到延时时间,直接返回
Seg_Slow_Down = 1; // 到延时时间,执行后续逻辑并置1
// 数码管刷新核心代码
}
void Key_Proc() {
if(Key_Slow_Down) return;
Key_Slow_Down = 1;
// 按键扫描核心代码
}
步骤 2:在时间函数中添加计数清零语句
// 按键10ms减速(防抖动),数码管500ms减速(降刷新)
if (++Key_Slow_Down == 10) Key_Slow_Down = 0;
if (++Seg_Slow_Down == 500) Seg_Slow_Down = 0;
关键技巧:
修改==后的数值,即可调整延时毫秒数,数值越小,响应 / 刷新速度越快。
3. 多模式开发核心原则
不同模式需定义独立变量,禁止共用!
若多个模式(如时钟模式 / 闹钟模式 / 设置模式)共用同一变量,修改一个模式的变量值会直接影响其他模式的逻辑运行,导致程序混乱,需谨记并养成习惯。