蓝桥杯第十四届省赛代码错误总结
错误列表
1.
LED3显示逻辑错误 — Collect_Flag 覆盖了 LED1/2 的模式指示
错误代码:
void Led_Proc()
{
switch(Seg_Mode)
{
case 0:
ucLed[0]=1;
ucLed[1]=0;
ucLed[2]=0;
break;
case 1:
ucLed[0]=0;
ucLed[1]=1;
ucLed[2]=0;
break;
default:
ucLed[0]=0;
ucLed[1]=0;
ucLed[2]=0;
break;
}
// ❌ 问题在这里!采集期间把 LED1/2 强制清零
if(Collect_Flag==1)
{
ucLed[0]=0; // ❌ 把模式指示 LED1 灭了!
ucLed[1]=0; // ❌ 把模式指示 LED2 灭了!
ucLed[2]=1;
}
}
错误原因:
题目要求:
-
LED1 = 当前在时间界面(Seg_Mode==0 时常亮)
-
LED2 = 当前在回显界面(Seg_Mode==1 时常亮)
-
LED3 = 采集显示期间(Collect_Flag==1 时亮)
三者是独立关系,不应相互覆盖。采集显示的3秒内,用户依然在某个界面,LED1/2不应被清零。
参考代码(82.4分版)的正确逻辑:
void led_proc()
{
// ✓ LED1/2 始终独立反映当前模式
ucLed[0]=(seg_mode_disp==0);
ucLed[1]=(seg_mode_disp==1);
// ✓ LED3 独立反映采集显示状态
ucLed[2]=display_flag;
// ...
}
正确代码:
void Led_Proc()
{
switch(Seg_Mode)
{
case 0:
ucLed[0]=1;
ucLed[1]=0;
ucLed[2]=0;
break;
case 1:
ucLed[0]=0;
ucLed[1]=1;
ucLed[2]=0;
break;
default:
ucLed[0]=0;
ucLed[1]=0;
ucLed[2]=0;
break;
}
// ✓ 只更新 LED3,不影响 LED1/2
ucLed[2]=Collect_Flag;
ucLed[3]=Led4_Flag;
ucLed[4]=Error_Flag;
// ...
}
关键点:
-
LED1/2 和 LED3 各管各的,互不干扰
-
Collect_Flag只控制ucLed[2],不得触碰ucLed[0]和ucLed[1] -
采集3秒显示期间,模式指示灯应保持正常
2.
S9按键逻辑错误 — 参数-1 放在了 Key_Down,且 Key_Up 条件过严
错误代码:
void Key_Proc()
{
// ...
// ❌ 只有 Key_Flag==1(即曾在时间回显界面按下S9)才处理S9抬起
if(Key_Up == 9 && Key_Flag == 1)
{
if(Count_2000ms >= 2000)
{
// 长按复位...
}
// ❌ 短按在参数界面的 Param-- 完全没有处理!
Key_Flag = 0;
Count_2000ms = 0;
}
if(Collect_Flag == 0)
{
switch(Key_Down)
{
// ...
case 9:
// ❌ 在 Key_Down 时就立即减参数!
if(Seg_Mode == 2)
{
if(--Param >= 200) Param = 99;
}
// ❌ 问题:长按S9试图复位时,Param 会先减1再复位,行为不一致
if(Seg_Mode == 1 && Show_Mode == 2)
{
Key_Flag = 1;
}
break;
}
}
}
错误原因:
参考代码(82.4分版)的设计逻辑是:
-
S9 按下时:仅当在"时间回显界面"时才启动长按计时(其他界面什么都不做)
-
S9 抬起时:统一判断 → 若长按(≥2s)则全量复位;否则若在参数界面则 Param–
这样设计的好处:
-
防止误减:在时间回显界面长按S9准备复位时,不会同时减少参数
-
逻辑统一:所有 S9 的实际执行效果都在抬起时决定,符合"抬起生效"的设计习惯
错误代码的问题:
-
在参数界面按下S9立即减1,用户还没抬起就已经生效
-
Key_Up的条件&& Key_Flag == 1使得参数界面的S9抬起完全不被处理
正确代码:
void Key_Proc()
{
// ...
// ✓ 始终检测S9抬起
if(Key_Up == 9)
{
if(Count_2000ms >= 2000)
{
// ✓ 长按:全量复位
Collect_Count = 0;
Humidity_100x = Humidity_100x_Current = Humidity_100x_Last
= Humidity_100xMAX = Humidity_100x_Average = 0;
Temperature_10x = Temperature_10x_Current = Temperature_10x_Last
= Temperature_10xMAX = Temperature_10x_Average = 0;
Param = 30; // ✓ 参数复位到默认值30
Collect_Time[0] = 0; // ✓ 最后采集时间清零
Collect_Time[1] = 0;
}
else if(Seg_Mode == 2)
// ✓ 短按:在参数界面才减参数(且在抬起时生效)
Param = (Param == 0) ? 0 : Param - 1;
Key_Flag = 0;
Count_2000ms = 0;
Led_Proc();
}
if(Collect_Flag == 0)
{
switch(Key_Down)
{
// ...
case 9:
// ✓ 按下时只启动长按计时,不做任何减参数操作
if(Seg_Mode == 1 && Show_Mode == 2)
{
Key_Flag = 1;
}
Led_Proc();
break;
}
}
}
对比表:
| 场景 | ||
|---|---|---|
| 参数界面按下S9 | 立即 Param– | 什么都不做,等待抬起 |
| 参数界面抬起S9(短按) | 无响应(Key_Flag==0 跳过) | Param-- 生效 |
| 时间回显界面长按S9 | Param-- 先执行(如果在参数界面) | 仅启动计时,抬起后复位 |
| 复位时 Param 是否归30 |
3.
复位逻辑不完整 — 漏掉 Param=30 和 Collect_Time 清零
错误代码:
// 长按复位块
Collect_Count = 0;
Humidity_100x = Humidity_100x_Current = Humidity_100x_Last
= Humidity_100xMAX = Humidity_100x_Average = 0;
Temperature_10x = Temperature_10x_Current = Temperature_10x_Last
= Temperature_10xMAX = Temperature_10x_Average = 0;
// ❌ 没有重置 Param 回默认值30
// ❌ 没有清零 Collect_Time(最后一次采集时间)
错误原因:
参考代码(82.4分版)中,长按S9复位时明确重置了 temperature_para=30 和 ctrlRtc 两个字段。这是完整复位的一部分:
-
Param=30:温度参数应回到初始默认值30℃ -
Collect_Time:显示的"最后采集时刻"时间戳应清零,否则还会显示上次采集时刻
正确代码:
// ✓ 完整复位
Collect_Count = 0;
Humidity_100x = Humidity_100x_Current = Humidity_100x_Last
= Humidity_100xMAX = Humidity_100x_Average = 0;
Temperature_10x = Temperature_10x_Current = Temperature_10x_Last
= Temperature_10xMAX = Temperature_10x_Average = 0;
Param = 30; // ✓ 恢复默认参数值
Collect_Time[0] = 0; // ✓ 清除最后采集时刻(小时)
Collect_Time[1] = 0; // ✓ 清除最后采集时刻(分钟)
4.
亮度触发采集无滞回 — 上下阈值相同导致不稳定
错误代码:
void AD_DA()
{
Ad_Read(0x41);
AD_1_Data_100x = (float)Ad_Read(0x41) / 51.0f * 100;
if(AD_1_Data_100x > 200) // 上阈值:亮度>200时置标志
Light_Flag = 1;
// ❌ 下阈值也是200!上下阈值相同,没有滞回区间
if(AD_1_Data_100x < 200 && Light_Flag == 1 && Assist_Flag == 1)
{
Collect_Flag = 1;
// ...
}
}
错误原因:
题目逻辑:亮度先亮后暗时触发一次采集。正确实现需要滞回(Hysteresis):
亮度值: ... 暗 ... [超过上阈] 亮 亮 亮 [低于下阈] 暗 ... → 触发!
↑置Light_Flag=1 ↑实际触发
若上下阈值相同(都是200),在亮度值徘徊在200附近时会发生:
-
略高于200 → 置
Light_Flag=1 -
略低于200 → 立即触发采集(连
Assist_Flag都来不及阻止多次触发的边缘情况)
参考代码(82.4分版)使用原始 ADC 值:
-
上阈值:
brightness > 100(原始ADC)≈ 换算后AD_1_Data_100x > 196 -
下阈值:
brightness < 50(原始ADC)≈ 换算后AD_1_Data_100x < 98
有约100个单位的滞回区间,确保稳定触发。
正确代码:
void AD_DA()
{
Ad_Read(0x41);
AD_1_Data_100x = (float)Ad_Read(0x41) / 51.0f * 100;
if(AD_1_Data_100x > 200) // 上阈值:检测"变亮"事件
Light_Flag = 1;
// ✓ 下阈值改为100,与上阈值200形成滞回区间,稳定触发
if(AD_1_Data_100x < 100 && Light_Flag == 1 && Assist_Flag == 1)
{
Collect_Flag = 1;
// ...
}
}
滞回区间示意图:
AD_1_Data_100x:
300 |
200 |-------- 上阈值(超过此值置 Light_Flag=1)
| ←滞回区间(处于100~200之间时,什么都不触发)
100 |-------- 下阈值(低于此值 + Light_Flag=1 → 触发采集)
0 |
总结
最严重的错误(逻辑完全错误):
- S9 参数-1 放在 Key_Down — 行为与参考代码完全相反,导致用户长按复位时Param被误减,短按时无响应
中等错误(部分功能失效):
-
LED3 覆盖 LED1/2 — 采集期间模式指示灯熄灭,与题目要求不符
-
亮度触发无滞回 — 阈值边缘可能出现异常触发
轻微错误(细节缺失):
- 复位漏掉 Param=30 和 Collect_Time — 复位后参数不归默认,时间戳不清零
学到的经验
1. LED 多灯独立控制原则
规则:每个LED只由其对应的状态变量控制,不允许互相覆盖
// ✅ 正确:各自独立
ucLed[0] = (Seg_Mode == 0); // LED1:时间界面指示
ucLed[1] = (Seg_Mode == 1); // LED2:回显界面指示
ucLed[2] = Collect_Flag; // LED3:采集显示指示
ucLed[3] = Led4_Flag; // LED4:温度超限闪烁
ucLed[4] = Error_Flag; // LED5:湿度无效指示
ucLed[5] = Led6_Flag; // LED6:温湿度同时上升
// ❌ 错误:用一个状态覆盖其他状态
if(Collect_Flag==1)
{
ucLed[0]=0; // ❌ 不能在这里清LED1
ucLed[1]=0; // ❌ 不能在这里清LED2
ucLed[2]=1;
}
2. 长按/短按按键的标准模式
核心原则:按键实际效果统一在 Key_Up(抬起)时生效
// ① 按下时:仅记录意图(启动计时)
if(Key_Down == S9键号)
{
if(处于长按检测界面)
Key_Flag = 1; // 只在特定界面才开始计时
// 其他界面:什么都不做,等待抬起
}
// ② 抬起时:统一判断执行
if(Key_Up == S9键号)
{
if(Count_2000ms >= 2000)
{
// 长按:复位(含Param、Collect_Time等所有相关变量)
}
else if(当前界面 == 参数界面)
{
// 短按:在参数界面才减参数
Param--;
}
Key_Flag = 0;
Count_2000ms = 0;
}
为什么不在 Key_Down 减参数:
-
用户按下S9后可能保持按下准备长按复位
-
Key_Down 时就减参数 → 用户还没松手参数就变了
-
然后用户松手时又触发复位,行为混乱
3. 传感器触发的滞回设计
规则:凡是"先超过阈值A,后低于阈值B才触发"的逻辑,A 必须 > B
// 通用模板
if(value > HIGH_THRESHOLD) // 检测"变高"事件
flag = 1;
if(value < LOW_THRESHOLD && flag == 1) // 检测"变低"事件
{
// 触发逻辑
flag = 0;
}
// 确保 HIGH_THRESHOLD > LOW_THRESHOLD,形成稳定的滞回区间
本题中建议值:
-
上阈值:
> 200(AD_1_Data_100x 单位,对应原始 ADC ≈ 102) -
下阈值:
< 100(AD_1_Data_100x 单位,对应原始 ADC ≈ 51)
复盘检查清单
比赛中遇到光敏+采集类题目时,务必检查:
LED 逻辑相关:
-
每个 LED 只由对应状态变量控制,不互相覆盖
-
有无 if 块强制清零了不该清零的 LED
-
各 LED 语义是否与题目要求一一对应
S9 按键长按/短按相关:
-
参数-1 是否在 Key_Up(抬起)时执行,而非 Key_Down
-
Key_Up 的检测条件是否覆盖了所有需要处理的场景
-
长按时不会误执行短按效果
-
按下时仅启动计时,不立即修改变量
复位逻辑相关:
-
复位是否包含了所有统计变量(温度/湿度 当前/最大/平均/求和)
-
复位是否恢复了参数到默认值(如 Param=30)
-
复位是否清零了时间戳(如 Collect_Time)
亮度触发采集相关:
-
上下阈值是否不同(HIGH > LOW,形成滞回)
-
有无防重复触发机制(如 Assist_Flag)
-
Assist_Flag 在采集结束后是否正确恢复为 1
修改前后对比(本次4处修正)
| 位置 | 修改前 | 修改后 | 影响 |
|---|---|---|---|
Led_Proc |
Collect_Flag==1 时清零 LED1/2 |
只设置 ucLed[2]=Collect_Flag |
LED1/2 采集期间保持正常 |
Key_Up 条件 |
Key_Up==9 && Key_Flag==1 |
Key_Up==9 |
参数界面S9短按得到响应 |
Key_Down case 9 |
立即执行 Param-- |
删除,只保留长按计时 | 与抬起生效的设计一致 |
Key_Up 长按复位 |
漏掉 Param=30 和 Collect_Time |
补充完整 | 复位后状态完全干净 |
AD_DA 下阈值 |
< 200(无滞回) |
< 100(有100单位滞回) |
亮度触发更稳定 |
生成时间: 2026-03-01
蓝桥杯第十四届省赛代码错误总结