蓝桥杯第十三届省赛(第一次)代码错误总结
错误列表
1.
bit 类型使用 ~ 按位取反导致 LED2 异常
错误代码:
idata bit Control_Mode = 0;
// ❌ 对 bit 类型用 ~ 按位取反!
ucLed[1] = (~Control_Mode);
错误原因:
~ 是按位取反运算符,对 bit 类型操作时会先提升为 int 再取反:
-
Control_Mode = 0→ 提升为0x0000→~得到0xFFFF→ 赋给unsigned char= 0xFF(本意是1) -
Control_Mode = 1→ 提升为0x0001→~得到0xFFFE→ 赋给unsigned char= 0xFE(本意是0)
导致的问题:
-
ucLed[1]永远不是 0 或 1,而是 0xFF 或 0xFE -
在
Led_Disp中被左移后,LED2 永远亮,不随控制模式切换 -
LED2 指示功能完全失效
正确代码:
// ✓ 使用逻辑非 ! ,结果一定是 0 或 1
ucLed[1] = !Control_Mode;
满分代码的统一做法:
| 满分代码 | 写法 | 结果 |
|---|---|---|
| mind | led_buf[1]=(ctr_mode==0); |
0 或 1 ✓ |
| Ꮶ | ucled[1]=(control_mode==0); |
0 或 1 ✓ |
| 白鹭霜华 | ucLed[1] = !work_mode; |
0 或 1 ✓ |
| emo哥 | if(mode==0) ucled|=0x02; else ucled&=(~0x02); |
位操作 ✓ |
关键点:
-
~是按位取反(bitwise NOT):~0x01 = 0xFE -
!是逻辑非(logical NOT):!1 = 0,!0 = 1 -
对 bit/布尔值取反永远用
!,不要用~ -
~只适合对多位数据做掩码操作(如temp_2 &= (~0x40))
记忆规则:
~ 按位取反:给整个字节每一位翻转(用于掩码)
! 逻辑非 :把真变假,假变真(用于布尔判断)
对 0/1 变量取反 → 用 !
对 0xFF 做掩码 → 用 ~
2.
误把LED闪烁间隔看成LED闪烁周期
错误代码:
if((Relay_Flag==1)||(Relay_Temper==1))
{
Time_50ms++;
if(Time_50ms==50) // ❌ 50ms翻转 = 周期0.1s,太快了!
{
Time_50ms=0;
Led3_Flag^=1;
}
}
错误原因:
题目要求"L3 以 0.1s 间隔闪烁"的正确理解:
-
“0.1s 间隔”= 亮 0.1s + 灭 0.1s = 翻转间隔 100ms
-
不是"闪烁周期 0.1s"(那样翻转间隔就是 50ms)
-
用 50ms 翻转,闪烁频率是正确值的两倍,太快了
❌ 你的理解(50ms翻转):
|亮50ms|灭50ms|亮50ms|灭50ms| → 周期0.1s,闪太快
✓ 正确理解(100ms翻转):
|亮100ms|灭100ms|亮100ms|灭100ms| → 0.1s间隔,周期0.2s
4T测评失败点:
序号8 :继电器吸合 → L3发光周期错误 ❌
序号10:继电器吸合 → L3发光周期错误 ❌
序号19:继电器吸合 → L3发光周期错误 ❌
序号26:继电器吸合 → L3发光周期错误 ❌
序号31:继电器吸合 → L3发光周期错误 ❌
序号46:继电器吸合 → L3发光周期错误 ❌
序号49:继电器吸合 → L3发光周期错误 ❌
(共7+个测试点全部因为这一个数字扣分!)
正确代码:
if((Relay_Flag==1)||(Relay_Temper==1))
{
Time_100ms++;
if(Time_100ms==100) // ✓ 100ms翻转 = 0.1s间隔
{
Time_100ms=0;
Led3_Flag^=1;
}
}
四份满分代码全部用 100ms:
| 满分代码 | 翻转判断 | 翻转间隔 |
|---|---|---|
| mind | if(++time_100ms>=100) |
100ms ✓ |
| Ꮶ | if(++timeled_100ms==100) |
100ms ✓ |
| 白鹭霜华 | if(++timer_100ms>=100) |
100ms ✓ |
| emo哥 | if(ms_led3==100) |
100ms ✓ |
关键点:
-
“以 X 间隔闪烁”= 翻转间隔 X = 亮X灭X = 周期2X
-
“0.1s 间隔闪烁” → 翻转 100ms,周期 0.2s
-
中断1ms进一次 → 翻转值填 100,不是 50
记忆规则:
题目说"以 T 间隔闪烁"
→ 翻转间隔 = T
→ 闪烁周期 = 2T
→ 定时器计数值 = T / 中断周期
例:0.1s间隔,1ms中断
→ 计数值 = 0.1s / 1ms = 100
3.
Param 与 Param_Set 双变量设计导致参数修改不即时生效
错误代码:
// ❌ 用了两个变量管理同一个参数!
idata unsigned char Param=23; // 实际控制用
idata unsigned char Param_Set=23; // 界面设置用
// Led_Proc 中控制用 Param:
if(Temperature_10x>(Param*10)) // ❌ 用的是旧的 Param!
// Key_Proc 中设置修改 Param_Set:
case 16:
Param_Set++; // 修改的是 Param_Set,不是 Param!
// 只有按 S12 退出时才同步:
case 12:
if(Seg_Mode==2)
Param=Param_Set; // 退出参数界面才保存
Seg_Mode=(Seg_Mode+1)%3;
break;
错误原因:
双变量设计导致参数修改存在"延迟":
-
在参数设置界面按 S16/S17 修改的是
Param_Set -
但继电器控制用的是
Param -
只有按 S12 退出参数界面时,才执行
Param = Param_Set
测评流程(序号34→36):
1. 在U3界面加参数到26 → Param_Set=26, 但 Param=23(还没退出!)
2. 4T设温度为25 → 温度25 < 参数Param_Set(26) ✓
3. 检查继电器 → Led_Proc 比较的是 Param(23)!
→ 25 > 23 → 继电器吸合!❌
4T期望:参数已经是26,温度25<26,继电器应该断开!
4T测评失败点:
序号36:温度数据低于温度参数值
- 正确结果:继电器断开
- 你的结果:继电器吸合 ❌(因为控制用的还是旧参数23)
序号37:'减少'参数
- 也因状态不一致导致扣分 ❌
正确代码(单变量设计):
// ✓ 只用一个变量,修改即生效!
idata unsigned char Param=23;
// Led_Proc 中直接用 Param:
if(Temperature_10x>(Param*10)) // ✓ 永远是最新值
// Key_Proc 中直接修改 Param:
case 16:
if(Seg_Mode==2)
{
Param++;
Param=(Param==100)?99:Param;
}
break;
// Seg_Proc 中显示也用 Param:
Seg_Buf[6]=Param/10%10;
Seg_Buf[7]=Param%10;
// S12 只需要切换界面,不需要保存/加载:
case 12:
Seg_Mode=(Seg_Mode+1)%3;
break;
四份满分代码全部用单变量:
| 满分代码 | 参数变量 | 设置修改 | 控制比较 |
|---|---|---|---|
| mind | wdcs_show |
wdcs_show+1 |
temper_10x>(wdcs_show*10) |
| Ꮶ | temp_set |
++temp_set |
temp_value>temp_set |
| 白鹭霜华 | temp_para |
++temp_para |
temputure_10x>(temp_para*10) |
| emo哥 | T_val |
T_val+=1 |
T>T_val |
关键点:
-
参数变量只用一个,修改即时生效,不需要"保存"步骤
-
双变量(显示用 / 控制用)设计虽然编程思路上没错,但蓝桥杯题目不要求"取消"功能
-
4T测评会在参数设置界面中直接检查继电器状态,不会先帮你按S12退出
记忆规则:
蓝桥杯参数设置的标准模式:
✓ 一个变量搞定:设置、显示、控制全用它
✗ 不要搞"编辑缓冲区"和"保存确认"的设计
✗ 不要学桌面软件的"确定/取消"模式
原则:改了就生效,简单直接!
总结
最严重的错误(直接导致4T大量扣分):
-
误把LED闪烁间隔看成LED闪烁周期 — 一个数字的错误,导致 7+ 个测试点全部扣分
-
Param 双变量延迟同步 — 参数修改不即时生效,继电器控制异常
中等错误(影响部分功能):
~Control_Mode应为!Control_Mode— LED2 指示功能异常
学到的经验
1. “以 T 间隔闪烁” 的正确翻译
题目描述 → 翻转间隔 → 计数值(1ms中断)
"0.1s 间隔闪烁" → 100ms → 100
"0.2s 间隔闪烁" → 200ms → 200
"0.5s 间隔闪烁" → 500ms → 500
公式:计数值 = 间隔时间(ms) / 中断周期(ms)
注意:间隔 ≠ 周期!周期 = 间隔 × 2
2. ~ 和 ! 的使用场景
~ 按位取反(bitwise NOT):
用途:掩码操作,如 temp &= (~0x40)
结果:每一位都翻转
注意:不要对 bit/布尔变量使用!
! 逻辑非(logical NOT):
用途:布尔取反,如 ucLed[1] = !flag
结果:真→0,假→1
注意:永远用于 0/1 变量的取反!
3. 蓝桥杯参数设置用单变量
✓ 正确做法:一个变量搞定
unsigned char Param = 23;
// 设置时直接改 Param
// 显示时直接用 Param
// 控制时直接用 Param
// 改了就生效!
✗ 错误做法:双变量 + 保存同步
unsigned char Param = 23; // 控制用
unsigned char Param_Set = 23; // 设置用
// 需要按S12才同步 → 设置界面中控制用旧值!
复盘检查清单
在蓝桥杯单片机比赛中,遇到类似题目时,务必检查:
LED闪烁相关:
-
“以 T 间隔闪烁” → 翻转间隔 = T(不是 T/2)
-
间隔和周期不要搞混(周期 = 间隔 × 2)
位操作相关:
-
对 bit/布尔变量取反用
!,不用~ -
对字节做掩码操作才用
~
状态同步相关:
-
参数修改后立即影响控制逻辑(单变量)
-
不要搞"编辑缓冲区"和"保存确认"的双变量设计
生成时间: 2026-02-10
蓝桥杯第十三届省赛(第一次)代码错误总结