1错误逻辑
if(time[0]==0&&time[1]==0)//整点
{
fled2=1;
t5000ms_1=0;
}
if(time[0]==0 && time[1]==0),8:00:00时,有1整秒都符合条件
而对于单片机来说,1整秒是很长的
在这 1 秒内,t5000ms_1 = 0; 被疯狂执行,导致5 秒定时器根本没法往前走。等 1 秒结束后,它才开始倒数 5 秒。所以实际上 L1 会亮 6 秒。
2时序保护的重要性
为什么断开指令发了,继电器却吸合?
- 你的主循环
while(1)正在飞速执行Relay(0)准备关掉继电器。 Relay(0)的底层逻辑是:先改变P0的值,再打开P2锁存器把数据送给继电器。- 就在
P0刚改完,还没来得及打开锁存器的这 1 微秒里,1ms 的定时器中断突然来了! - 单片机立刻跳去执行中断里的
Led_Disp(ucled)。Led_Disp把P0改成了控制 LED 的数据(此时因为模式等原因,P0的第4位刚好被置成了高电平 1)。 - 中断结束,单片机回到刚才没执行完的
Relay(0),接着打开了继电器的锁存器。 - 灾难发生:继电器锁存器抓取到的,是被中断里
Led_Disp篡改过的数据(导致继电器引脚被置1)。所以你明明想关继电器,它却被强制吸合了!
3参数要立即生效
在绝大多数蓝桥杯考题中,除非题目明确写了"退出界面后参数才生效",否则所有参数修改都必须是即刻生效的!
我们完全不需要 wcan_seg 这个多余的变量,直接修改 wcan_sta 即可。
4完整代码
#include <STC15F2K60S2.H>
#include <seg.h>
#include <key.h>
#include <init.h>
#include <led.h>
#include <ds18b20.h>
#include <ds1302.h>
unsigned char seg_pos;
unsigned char seg_buf[8]={10,10,10,10,10,10,10,10};
unsigned char seg_point[8]={0,0,0,0,0,0,0,0};
unsigned char ucled[8]={0,0,0,0,0,0,0,0};
unsigned int seg_slow_down;
unsigned char segmode;
unsigned char key_slow_down;
unsigned char key_val,key_down,key_old,key_up;
float tem;//温度
unsigned char time[7]={1,0,0};//teme[0]--秒,time[1]--分
unsigned char wcan_sta=23;
bit mode;//温度控制
bit xian_fm;
unsigned int t5000ms;
unsigned int t5000ms_1;
bit fr,fled2,fled3;
unsigned char t100ms;
void key_proc()
{
if(key_slow_down<10)return ;
key_slow_down=0;
key_val=key_read();
key_down=key_val&(key_old^key_val);
key_up=~key_val&(key_old^key_val);
key_old=key_val;
if(segmode==1)//在时间显示界面下
{
if(key_down==17)
{
xian_fm=1;//s17处于按下的状态,显示分秒
}
if(key_up==17)
{
xian_fm=0;
}
}
switch(key_down)
{
case 12://切换按键
if(++segmode==3)segmode=0;
break;
case 13://切换工作模式
mode^=1;
break;
case 16://++
if(segmode==2)//在参数设置界面下
{
wcan_sta++;
if(wcan_sta==100)wcan_sta=10;
}
break;
case 17://--
if(segmode==2)//在参数设置界面下
{
wcan_sta--;
if(wcan_sta==9)wcan_sta=99;
}
break;
}
}
void led_proc()
{
if(mode==0)//温度控制继电器
{
if(tem>wcan_sta*1.0) //采集的温度数据超过了温度参数值
{
Relay(1);
ucled[2]=fled3;
}
else
{
Relay(0);
ucled[2]=0;
}
}
else//时间控制继电器
{
if(time[0]==0&&time[1]==0)//整点
{
fr=1;
}
if(fr==1)//整点
{
Relay(1);
ucled[2]=fled3;
}
else //过了5s
{
Relay(0);
ucled[2]=0;
}
}
if(time[0]==0&&time[1]==0)//整点
{
fled2=1;
}
if(fled2==1)ucled[0]=1;
else ucled[0]=0;//过了5s
ucled[1]=(mode==0)?1:0;
ucled[3] = ucled[4] = ucled[5] = ucled[6] = ucled[7] = 0;
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1=1;
EA=1;
}
void T1service() interrupt 3
{
seg_slow_down++;
key_slow_down++;
if(++seg_pos==8)seg_pos=0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
Led_Disp(ucled);
if(fr==1)//整点,t5000ms开始++
{
if(++t5000ms==5000)//5s
{
t5000ms=0;
fr=0;
}
}
if(fled2==1)//整点
{
if(++t5000ms_1==5000)//5s
{
t5000ms_1=0;
fled2=0;
}
}
if(++t100ms==100)
{
t100ms=0;
fled3^=1;
}
}
void seg_proc()
{
if(seg_slow_down<500)return;
seg_slow_down=0;
tem=rd_temperature();
read_rtc(time);
switch(segmode)
{
case 0://温度显示界面
seg_point[6]=1;
seg_buf[0]=11;
seg_buf[1]=1;
seg_buf[2]=10;
seg_buf[3]=10;
seg_buf[4]=10;
seg_buf[5]=(unsigned char )tem/10;
seg_buf[6]=(unsigned char )tem%10;
seg_buf[7]=(unsigned int )(tem*10)%10;
break;
case 1://时间显示界面
if(xian_fm==1)//时间界面显示分秒
{
seg_point[6]=0;
seg_buf[0]=11;
seg_buf[1]=2;
seg_buf[2]=10;
seg_buf[3]=time[1]/16;//分
seg_buf[4]=time[1]%16;
seg_buf[5]=15;
seg_buf[6]=time[0]/16;
seg_buf[7]=time[0]%16;
}
else//显示时分
{
seg_point[6]=0;
seg_buf[0]=11;
seg_buf[1]=2;
seg_buf[2]=10;
seg_buf[3]=time[2]/16;
seg_buf[4]=time[2]%16;
seg_buf[5]=15;
seg_buf[6]=time[1]/16;
seg_buf[7]=time[1]%16;
}
break;
case 2://参数设置界面
seg_point[6]=0;
seg_buf[0]=11;
seg_buf[1]=3;
seg_buf[2]=10;
seg_buf[3]=10;
seg_buf[4]=10;
seg_buf[5]=10;
seg_buf[6]=wcan_sta/10;
seg_buf[7]=wcan_sta%10;
break;
}
}
void Delay750ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
Delay750ms();
rd_temperature();//延时一下再解决上电85
sys_init();
Timer1_Init();
set_rtc(time);
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}