蓝桥杯第十三届省赛(第一次)代码错误总结

蓝桥杯第十三届省赛(第一次)代码错误总结

错误列表

1. :cross_mark: 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. :cross_mark: 误把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. :cross_mark: 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大量扣分):

  1. 误把LED闪烁间隔看成LED闪烁周期 — 一个数字的错误,导致 7+ 个测试点全部扣分

  2. Param 双变量延迟同步 — 参数修改不即时生效,继电器控制异常

中等错误(影响部分功能):

  1. ~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
蓝桥杯第十三届省赛(第一次)代码错误总结

1 个赞