蓝桥杯第13届单片机(满分)

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时序保护的重要性

为什么断开指令发了,继电器却吸合?

  1. 你的主循环 while(1) 正在飞速执行 Relay(0) 准备关掉继电器。
  2. Relay(0) 的底层逻辑是:先改变 P0 的值,再打开 P2 锁存器把数据送给继电器。
  3. 就在 P0 刚改完,还没来得及打开锁存器的这 1 微秒里,1ms 的定时器中断突然来了!
  4. 单片机立刻跳去执行中断里的 Led_Disp(ucled)Led_DispP0 改成了控制 LED 的数据(此时因为模式等原因,P0的第4位刚好被置成了高电平 1)。
  5. 中断结束,单片机回到刚才没执行完的 Relay(0),接着打开了继电器的锁存器。
  6. 灾难发生:继电器锁存器抓取到的,是被中断里 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();
			}
}

相关推荐
清风6666662 小时前
基于单片机的正弦波与方波峰峰值与频率测量系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
gihigo19982 小时前
基于51单片机的TB6600步进电机驱动程序
stm32·单片机·51单片机
搁浅小泽2 小时前
变频空调检修完整流程(通用版)
单片机·嵌入式硬件·可靠性工程师
Tanecious.2 小时前
蓝桥杯备赛:Day7- U535982 C-小梦的AB交换
c语言·c++·蓝桥杯
笨笨饿11 小时前
29_Z变换在工程中的实际意义
c语言·开发语言·人工智能·单片机·mcu·算法·机器人
迈巴赫车主13 小时前
蓝桥杯19724食堂
java·数据结构·算法·职场和发展·蓝桥杯
清风66666613 小时前
基于单片机的智能药物盒设计与实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
李永奉14 小时前
杰理芯片SDK-详细讲解AC695N/AC696N芯片SDK中APP模式流程
单片机·嵌入式硬件·物联网·语音识别
季鹏EthanJ14 小时前
VCC上电慢导致STM32无法复位
stm32·单片机·嵌入式硬件·上电复位故障·bor