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

:police_car_light: 终极死刑:一秒钟狂跳 1000 次的“抽风计数器”!

Led_Proc() 函数里,看看你写的这两行:

if((Hot_Flag==1)&&(Close_Flag==1))
{
    Relay(1);
    Relay_Count++; // 👈 !!!!!!
}

:collision: 灾难级翻车推演:
宝宝你忘了咱们的 Led_Proc() 是放在调度器里**每 1 毫秒(1ms)**执行一次的吗?!
假设现在温度超了,距离也近了,条件成立!

  • 第 1 毫秒进来:继电器吸合,次数 +1。

  • 第 2 毫秒进来:条件依然成立!次数又 +1!

  • 第 1000 毫秒(仅仅过了 1 秒钟):你的 Relay_Count 已经硬生生地加了 1000 次

结果: 评委老师只要拿手在超声波前面晃一下,你的数码管统计界面就会像抽风一样,瞬间飙升到 9999 然后爆表!评委老师直接连夜买站票逃跑!:cross_mark:


:shield: 神级抢修:边缘检测大法(最后一次!)

题目要求的是“吸合次数”,也就是只有在“从断开 变成 吸合”的那一瞬间,才允许 +1!

快!在 Led_Proc() 前面定义一个历史状态变量,把它改成标准的“上升沿检测”!

// 1. 在外面定义一个全局变量(或者在这个文件最上面)
idata bit Relay_Old_State = 0; 

void Led_Proc()
{
    if(Relay_Led_Lock==0) // 处于解锁状态下
    {
        // ... (前面的 LED 逻辑保持不变) ...
        
        // 🌟 核心修复:算出当前应该是什么状态
        bit Relay_Target = (Hot_Flag==1 && Close_Flag==1);
        
        // 🌟 捕捉“从断开(0)变成吸合(1)”的瞬间!
        if (Relay_Target == 1 && Relay_Old_State == 0)
        {
            Relay_Count++; // 只有瞬间触发一次!绝对不会狂飙!
        }
        
        Relay_Old_State = Relay_Target; // 更新旧状态
        Relay(Relay_Target);            // 真实控制硬件
    }
    Led_Disp(ucLed);
}

:police_car_light: 死刑宣判一:屡教不改的“失忆局部变量”!

Get_Distance_1s() 函数里,大声把你写的这几行念出来:

unsigned char D_Distance;//距离差
unsigned int temp;
unsigned int temp_old;  // 👈 !!!!!
temp=Distance_Value;
// ...
temp_old=temp;

:collision: 女友崩溃咆哮:
你为什么不加 static !!!你为什么不加 static !!!
这是局部变量呀!1秒钟跑完,temp_old 就被单片机拉去火化了!下一秒进来,它又是一堆乱码垃圾!你的距离差 D_Distance 永远是两个垃圾在相减!

:backhand_index_pointing_right: 神级保命修复(就加一个单词!):

static unsigned int temp_old = 0; // 🌟 加了 static,它就拥有了不死的记忆!

(其实更好的习惯是直接把它扔到最上面的全局变量区,但加 static 也能完美解决!)

这里用全局变量更好


:police_car_light: 死刑宣判二:L8 的“强行常亮”窒息操作

宝宝,看你在 Timer1_Isr 中断里写的 L8 闪烁逻辑:

if(Motion_State==3)
    L8_Flag=1;      // 👈 致命操作!

if(L8_Flag==1)
{
    if(++L8_100ms==100)
    {
        L8_Flag^=1; // 这里刚变成 0
        L8_100ms=0;
    }
}

:collision: 灾难推演:
如果 Motion_State 是 3(跑动)。
第 100 毫秒,L8_Flag 终于翻转成了 0(灯灭了)。
结果第 101 毫秒进来,因为 Motion_State 还是 3,单片机在第一句话直接又把 L8_Flag 强行按回了 1!
结果就是:你的 L8 根本不会闪!它只会变成一盏刺眼的常亮灯!

:backhand_index_pointing_right: 神级优化(让定时器做个无情的节拍器!):
把定时器里关于 Motion_State 和 if(L8_Flag==1) 的判断全删了!让标志位永远跳动!

// Timer1_Isr 里面只需要这几行!它就是一个永不停歇的 0.1s 心脏!
if(++L8_100ms >= 100)
{
    L8_100ms = 0;
    L8_Flag ^= 1; 
}

然后在 Led_Proc 里,你不是已经写了 else //运动 ucLed[7]=L8_Flag; 吗?直接让它去读取这个跳动的心脏,完美实现闪烁!