蓝桥杯第八届省赛代码错误总结
错误列表
1.
S5按键运算符优先级错误
错误代码:
if(ucRtc[index]==(index==0)?24:60) // ❌ 运算符优先级错误
ucRtc[index]=0;
错误原因:
-
C语言中
==的优先级(7)高于?:的优先级(13) -
编译器会先计算
ucRtc[index]==(index==0),再计算? 24 : 60 -
实际执行的是:
if((ucRtc[index]==(index==0)) ? 24 : 60) -
导致条件判断完全错误,时间无法正常自增
正确代码:
if(ucRtc[index] == ((index==0) ? 24 : 60)) // ✓ 加括号明确优先级
ucRtc[index]=0;
同样的错误也出现在:
-
S5按键时钟设置(第119行)
-
S5按键闹钟设置(第125行)
2.
S7和S6按键逻辑错误
错误代码:
case 7:
Seg_Mode=1;
Time_Mode=0;
if(++index==3) // ❌ index先自增再判断
Time_Mode=0; // ❌ 只设置Time_Mode,没有保存时间和退出设置模式
break;
错误原因:
-
++index是前置自增,先自增再判断 -
第一次按S7时,
index从0变成1,跳过了"时"的设置(应该从index=0开始) -
当
index==3时,只设置了Time_Mode=0,但:-
没有设置
Seg_Mode=0(没有退出设置模式) -
没有调用
Set_Rtc(ucRtc)保存时间到DS1302 -
没有重置
index=0
-
正确代码:
case 7:
if(Seg_Mode==0) // 从时间显示进入时钟设置
{
index=0;
Seg_Mode=1;
Time_Mode=0;
Read_Rtc(ucRtc); // 读取最新时间
}
else if((Seg_Mode==1)&&(Time_Mode==0)) // 在时钟设置模式下
{
index++; // 先自增
if(index==3) // 如果超过2(秒)
{
index=0;
Seg_Mode=0; // ✓ 退出设置模式
Set_Rtc(ucRtc); // ✓ 保存时间到DS1302
}
}
else if((Seg_Mode==1)&&(Time_Mode==1)) // 在闹钟设置模式下按S7
{
index=0;
Seg_Mode=1;
Time_Mode=0;
}
break;
S6按键有同样的逻辑问题。
3.
主函数初始化逻辑完全错误
错误代码:
Read_Rtc(ucRtc); // ❌ 从DS1302读取时间(随机值)覆盖23:59:50
Set_Rtc(ucAlarm); // ❌ 把闹钟时间(00:00:00)写入DS1302作为当前时间!
错误原因:
-
Read_Rtc(ucRtc)会从DS1302芯片读取时间(可能是随机值),覆盖代码中定义的23:59:50 -
Set_Rtc(ucAlarm)会把00:00:00写入DS1302,导致时钟从00:00:00开始走 -
完全搞反了数据流向
正确代码:
Set_Rtc(ucRtc); // ✓ 只需要这一行!把23:59:50写入DS1302作为初始时间
说明:
-
Set_Rtc()= 写入时间到DS1302(内存 → DS1302芯片) -
Read_Rtc()= 从DS1302读取时间(DS1302芯片 → 内存) -
初始化时应该把代码中的23:59:50写入芯片,而不是从芯片读取
4.
S4按键温度显示检测错误
错误代码:
if((Key_Old==4)&&(Seg_Mode==0)) // ❌ 应该用Key_Val,不是Key_Old
{
Seg_Mode=2;
}
错误原因:
-
应该检测当前按键状态
Key_Val,而不是上一次的状态Key_Old -
Key_Old是用来做边沿检测的,不应该直接用来判断按键状态
正确代码:
if((Key_Val==4)&&(Seg_Mode==0)) // ✓ 使用当前按键状态
{
Seg_Mode=2;
}
5.
闹钟检测条件不完善
错误代码:
if((ucRtc[0]==ucAlarm[0])&&(ucRtc[1]==ucAlarm[1])&&(ucRtc[2]==ucAlarm[2]))
{
Alarm_flag=1; // ❌ 缺少条件判断
}
错误原因:
-
没有检查
Seg_Mode==0(应该只在时间显示模式检测闹钟) -
没有检查
Alarm_flag==0(避免重复触发,否则每100ms都会触发一次) -
可能在设置模式下也触发闹钟
建议的正确代码:
if(Seg_Mode==0 && Alarm_flag==0) // 只在时间显示且闹钟未响时检测
{
if((ucRtc[0]==ucAlarm[0])&&(ucRtc[1]==ucAlarm[1])&&(ucRtc[2]==ucAlarm[2]))
{
Alarm_flag=1;
}
}
注意: 虽然题目没有明确要求,但加上条件判断可以避免潜在问题。
6.
Get_Time()读取时间条件错误
错误代码:
if(Seg_Mode==0) // ❌ 时钟设置时也需要读取时间
{
Read_Rtc(ucRtc);
}
错误原因:
-
只在
Seg_Mode==0(时间显示)时读取时间 -
但在时钟设置模式(
Seg_Mode==1, Time_Mode==0)时,DS1302时钟还在走,也需要读取来更新显示 -
只有在温度显示模式(
Seg_Mode==2)时才不需要读取时间
建议的正确代码:
if(Seg_Mode != 2) // 非温度显示模式时都读取
{
Read_Rtc(ucRtc);
}
或者:
if(Seg_Mode==0 || (Seg_Mode==1 && Time_Mode==0))
{
Read_Rtc(ucRtc);
}
注意: 当前代码虽然有缺陷,但不影响基本功能。
7.
Led_Proc()缺少else分支和LED刷新
错误代码:
void Led_Proc()
{
if(Alarm_flag==1)
{
ucLed[0]=(Led_flag==1)?1:0;
Led_Disp(ucLed);
}
// ❌ 缺少else分支!当Alarm_flag==0时,LED不会熄灭
}
错误原因:
-
当闹钟关闭(
Alarm_flag=0)后,Led_Proc()不执行任何操作 -
ucLed[0]保持最后的值(可能是0,也可能是1) -
如果用户在LED亮着时按键关闭闹钟,
ucLed[0]=1不会被清零 -
LED会一直保持亮着,不会熄灭
-
这是一个概率性bug(50%概率出现)
正确代码:
void Led_Proc()
{
if(Alarm_flag==1)
{
ucLed[0]=Led_flag; // 使用Led_flag控制闪烁
}
else
{
ucLed[0]=0; // ✓ 确保闹钟关闭后LED熄灭
}
Led_Disp(ucLed); // ✓ 总是刷新LED显示
}
8.
定时器中断闪烁逻辑混乱
错误代码:
Led_count--;
if(Led_count==4294967295) // ❌ 检测无符号整数下溢,不优雅
{
Led_count=0; // ❌ 多余的语句
Alarm_flag=0;
}
错误原因:
-
虽然能工作,但不清晰
-
4294967295是unsigned int下溢后的值,不易读 -
没有重置
Led_count,导致第二次闹钟会立即关闭
正确代码:
if(Led_count>0) // 避免下溢
{
Led_count--;
if(Led_count==0)
{
Alarm_flag=0; // 5秒后关闭闹钟
Led_flag=0; // 熄灭LED
Led_count=5000; // ✓ 重置计数器,为下次闹钟做准备
}
}
9.
缺少DS1302初始化
错误原因:
-
虽然定义了
ucRtc[3] = {23, 59, 50},但没有写入DS1302芯片 -
DS1302芯片里的时间是随机值或上次的值
正确代码:
void main()
{
System_Init();
Set_Rtc(ucRtc); // ✓ 初始化DS1302为23:59:50
Scheduler_Init();
Timer1_Init();
while(1)
{
Scheduler_Run();
}
}
总结
最严重的错误(会导致功能完全无法工作):
-
S5按键运算符优先级错误 - 时间无法正常自增
-
S7/S6按键逻辑错误 - 设置功能无法使用
-
主函数初始化逻辑错误 - 时间不是23:59:50
-
LED熄灭问题 - LED不会熄灭(概率性bug)
中等错误(功能异常或不完整):
- S4温度显示检测错误 - 按键检测异常
轻微问题(可优化):
-
闹钟检测条件不完善 - 可能重复触发
-
Get_Time()读取条件 - 时钟设置时不更新
-
定时器中断逻辑 - 可读性差
学到的经验
-
运算符优先级很重要 - 复杂表达式一定要加括号
-
状态机逻辑要完整 - 考虑所有分支和退出条件
-
数据流向要清楚 - Read和Set不要搞混
-
LED/外设控制要有else - 确保所有状态都有对应的处理
-
概率性bug最难发现 - 要考虑所有可能的执行路径
-
初始化很关键 - 外设一定要正确初始化
-
按键检测变量要用对 - Key_Val是当前状态,Key_Old是历史状态
生成时间:2026-02-02
蓝桥杯第八届省赛代码调试总结