终极死刑:一秒钟狂跳 1000 次的“抽风计数器”!
Led_Proc() 函数里,看看你写的这两行:
if((Hot_Flag==1)&&(Close_Flag==1))
{
Relay(1);
Relay_Count++; // 👈 !!!!!!
}
灾难级翻车推演:
宝宝你忘了咱们的 Led_Proc() 是放在调度器里**每 1 毫秒(1ms)**执行一次的吗?!
假设现在温度超了,距离也近了,条件成立!
-
第 1 毫秒进来:继电器吸合,次数 +1。
-
第 2 毫秒进来:条件依然成立!次数又 +1!
-
第 1000 毫秒(仅仅过了 1 秒钟):你的 Relay_Count 已经硬生生地加了 1000 次!
结果: 评委老师只要拿手在超声波前面晃一下,你的数码管统计界面就会像抽风一样,瞬间飙升到 9999 然后爆表!评委老师直接连夜买站票逃跑!![]()
神级抢修:边缘检测大法(最后一次!)
题目要求的是“吸合次数”,也就是只有在“从断开 变成 吸合”的那一瞬间,才允许 +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);
}
死刑宣判一:屡教不改的“失忆局部变量”!
Get_Distance_1s() 函数里,大声把你写的这几行念出来:
unsigned char D_Distance;//距离差
unsigned int temp;
unsigned int temp_old; // 👈 !!!!!
temp=Distance_Value;
// ...
temp_old=temp;
女友崩溃咆哮:
你为什么不加 static !!!你为什么不加 static !!!
这是局部变量呀!1秒钟跑完,temp_old 就被单片机拉去火化了!下一秒进来,它又是一堆乱码垃圾!你的距离差 D_Distance 永远是两个垃圾在相减!
神级保命修复(就加一个单词!):
static unsigned int temp_old = 0; // 🌟 加了 static,它就拥有了不死的记忆!
(其实更好的习惯是直接把它扔到最上面的全局变量区,但加 static 也能完美解决!)
这里用全局变量更好
死刑宣判二: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;
}
}
灾难推演:
如果 Motion_State 是 3(跑动)。
第 100 毫秒,L8_Flag 终于翻转成了 0(灯灭了)。
结果第 101 毫秒进来,因为 Motion_State 还是 3,单片机在第一句话直接又把 L8_Flag 强行按回了 1!
结果就是:你的 L8 根本不会闪!它只会变成一盏刺眼的常亮灯!
神级优化(让定时器做个无情的节拍器!):
把定时器里关于 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; 吗?直接让它去读取这个跳动的心脏,完美实现闪烁!