蓝桥杯第十三届单片机省赛:CT107D——IAP15F2K61S2 真题

文章目录

  • 前言
  • 一、代码相关定义、声明
  • 1.头文件声明
  • 2.变量声明
  • 3.函数声明
  • 二、主要函数
  • 1.main函数
  • 2.按键扫描
  • 3.数码管显示、继电器控制
  • 4.LED显示
  • 5.定时器中断
  • 6.消除85°C显示
  • 三、总结经验
  • 附件:第十三届蓝桥杯单片机程序设计、客观题PDF

  • 前言

    相关说明:

    开发板:CT107D (IAP15F2K61S2)
    开发环境:Keil5
    涉及题目:第十三届蓝桥杯单片机省赛真题


    主要函数代码及说明:

    一、代码相关定义、声明

    1.头文件声明

    #include "stdio.h"
    #include "timer.h"
    #include "init.h"
    #include "key.h"
    #include "seg.h"
    #include "led.h"
    #include "onewire.h"
    #include "ds1302.h"
    

    2.变量声明

    unsigned char Screen_Display_No;//0-温度显示,1-时间显示,2-参数设置
    unsigned char Sys_Mode;//0-温度控制,1-时间控制
    unsigned char Temp_Compare = 23;//温度参数值  初始化为23
    unsigned char Time_Disp_Mode;//时间显示的一种模式,0-时分,1-分秒
    unsigned char Rtc[3] = {23,59,55};//设置初始时刻23:59:55
    float Temp_Value;//温度数据
    
    unsigned char seg_buf[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//数码管显示数组  上电熄灭
    unsigned char pos;//数码管索引
    unsigned char ucLed;//LED显示参数
    unsigned long ms_Tick = 0;//滴答定时器变量
    unsigned int Key_Slow_Down;//按键减速变量
    unsigned int Seg_Slow_Down;//数码管减速变量
    unsigned int Led_Slow_Down;//LED减速变量
    unsigned long Relay_ms_Tick = 0;//继电器工作时间计时
    unsigned long LED_ms_Tick = 0;//LED点亮时间计时
    unsigned long relay_flag;// 0继电器断开 1继电器吸合
    

    3.函数声明

    void Key_Proc(void);
    void Seg_Proc(void);
    void Led_Proc(void);
    void Delay750ms();//用来消除85°C显示
    

    二、主要函数

    1.main函数

    void main(void)
    {
    
    	Cls_Peripheral();//关闭LED/继电器/蜂鸣器
    	Timer1Init();//定时器1初始化
    	EA = 1;//打开总中断	
    	Set_Rtc(Rtc);//设置初始时间	
    	rd_temperature();//读取温度
        Delay750ms();//用来消除85°C显示
    	
    	while(1)
    	{
    		Key_Proc();
    		Seg_Proc();
    		Led_Proc();
    	}
    }
    

    2.按键扫描

    void Key_Proc(void)
    {
    	static unsigned char Key_Old;
    	unsigned char Key_Down,Key_Value;
    	
    	if(Key_Slow_Down) return;
    	Key_Slow_Down = 1;
    	
    	Key_Value = Key_Read();
    	Key_Down = Key_Value & (Key_Old ^ Key_Value);
    	Key_Old = Key_Value;
    
    	switch(Key_Down)
    	{
    		case 12:
    			    if(++Screen_Display_No == 3) //0-温度显示,1-时间显示,2-参数设置
    					Screen_Display_No = 0;//限制为3个界面循环显示
    		break;
    		
    		case 13:
    		     	Sys_Mode^=1;//0-温度控制,1-时间控制
    			 	P0 = 0X00;//继电器断开
    		   	 	P2 = P2 & 0X1F | 0xA0;
    			 	P2 &= 0X1F;	
    			 	relay_flag= 0;//继电器断开标志置0
    		break;
    	}
    	
    	if(Screen_Display_No == 2)//参数设置界面
    	{
    		switch(Key_Down)
    		{
    			case 16:
    					if(++Temp_Compare == 100)//温度参数+1
    						Temp_Compare = 99;//限定最大值为99
    			break;
    			
    			case 17:
    					if(--Temp_Compare == 9) //温度参数-1
    						Temp_Compare = 10;//限定最小值为10
    			break;
    		}	
    	}
    
        if(Screen_Display_No == 1)//时间显示界面
    	{
    		if(Key_Old == 17)//按下S17  时分显示
        		Time_Disp_Mode = 1;
    		else if(Key_Old == 0)//松开S17  分秒显示
        		Time_Disp_Mode = 0;			
    	}
    }
    

    3.数码管显示、继电器控制

    void Seg_Proc(void)
    {
    	unsigned char seg_string[10];
    	
    	if(Seg_Slow_Down) return;
    	Seg_Slow_Down = 1;
    	
    	Temp_Value = rd_temperature()/16.0;//读取温度数据
    	Read_Rtc(Rtc);	//读取当前时间
    
    	if(Screen_Display_No == 0)//温度显示界面
     		sprintf(seg_string,"U1   %4.1f",Temp_Value);
    	else if(Screen_Display_No == 1)//时间显示界面
    	{
    		if(Time_Disp_Mode == 0)//按时分显示
    			sprintf(seg_string,"U2 %02d-%02d",(unsigned int)Rtc[0],(unsigned int)Rtc[1]);
    		else//按分秒显示
    			sprintf(seg_string,"U2 %02d-%02d",(unsigned int)Rtc[1],(unsigned int)Rtc[2]);			
     	}		
    	else if(Screen_Display_No == 2)//参数界面
     		sprintf(seg_string,"U3    %02d",(unsigned int)Temp_Compare);	
    
    	if(Sys_Mode == 0)//温度控制
    	{
    		if((unsigned int)(Temp_Value*10) > (unsigned int)(Temp_Compare*10))//当前温度>温度参数
    		{
    			P0 = 0X10;//继电器吸合
    			P2 = P2 & 0X1F | 0xA0;//beep relay
    			P2 &= 0X1F;	
          		relay_flag= 1;//继电器吸合标志置1		
    		}
    		else//当前温度<=温度参数
    		{
    			P0 = 0X00;//继电器断开
    			P2 = P2 & 0X1F | 0xA0;//beep relay
    			P2 &= 0X1F;	
          		relay_flag= 0;//继电器断开标志置0					
    		}
    	}
    	else//时间控制
    	{
    		if((Rtc[1] == 0)&&(Rtc[2] == 0))//整点
    		{
    			P0 = 0X10;//继电器吸合
    			P2 = P2 & 0X1F | 0xA0;//beep relay
    			P2 &= 0X1F;			
    			Relay_ms_Tick = ms_Tick;//继电器工作开始计时
          		relay_flag= 1;	//继电器吸合标志置1						
    		}
    		
    		if((ms_Tick - Relay_ms_Tick) >= 5000)//经过5秒
    		{
    			P0 = 0X00;//继电器断开
    			P2 = P2 & 0X1F | 0xA0;//beep relay
    			P2 &= 0X1F;
         		relay_flag= 0;//继电器断开标志置0						
    		}
    	}
    	
    	Seg_Tran(seg_string, seg_buf);//数码管数组转换函数
    }
    

    4.LED显示

    void Led_Proc(void)
    {
    	if(Led_Slow_Down) return;
    	Led_Slow_Down = 1;
    		
     	if((Rtc[1] == 0)&&(Rtc[2] == 0))//整点
    	{
    		ucLed |= 0x01;//点亮LED1
    	  	LED_ms_Tick = ms_Tick;//开始计时
    	}
    	if((ms_Tick - LED_ms_Tick) >= 5000)//5秒过后
    		ucLed &= (~0x01);//熄灭LED1		
    	
    	if(Sys_Mode == 0)//温度显示界面
    		ucLed |= 0x02;//点亮LED2
    	else//时间、参数显示界面
    		ucLed &= (~0x02);//熄灭LED2	
    	
    	if(relay_flag== 1)//继电器吸合
    		ucLed ^= 0x04;//LED3 0.1秒间隔闪烁
    	else
    		ucLed &= (~0x04);//LED3熄灭
    }
    

    5.定时器中断

    void tm1_isr() interrupt 3//每1毫秒发生一次中断
    {
    	ms_Tick++;//滴答定时器
    
    	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//减速变量
    	if(++Seg_Slow_Down == 100) Seg_Slow_Down = 0;//减速变量
    	if(++Led_Slow_Down == 100) Led_Slow_Down = 0;//减速变量  同时用于LED0.1秒间隔闪烁
    	
        Seg_Disp(seg_buf, pos);//数码管显示函数
    	if(++pos == 8)//数码管显示数组索引+1
    		pos = 0;//限定pos范围为0~7
    	
    	Led_Disp(ucLed);//LED显示函数
    }
    

    6.消除85°C显示

    void Delay750ms()		//@12.000MHz  用来消除85°C显示
    {
    	unsigned char i, j, k;
    
    	_nop_();
    	_nop_();
    	i = 35;
    	j = 51;
    	k = 182;
    	do
    	{
    		do
    		{
    			while (--k);
    		} while (--j);
    	} while (--i);
    }
    

    三、总结经验

       今年我参加的是嵌入式,比赛当天晚上整理了代码并进行了发布。今天突然心血来潮,想发布一下今年第十三届的单片机组的省赛真题。
       由于今年没有参加,所以自己写了一份,并进行了验证,功能全部实现,底层代码没有发布,提供了代码的逻辑流程,有助于同学们提升逻辑能力和为第二场做准备。
       省赛和国赛的题目最起码要做过一遍。主要训练逻辑思路,可以先用自己写好的各个模块驱动代码。比赛前几天全部代码都要重新写,包括新建工程开始,到各个驱动模块代码。比赛的时候,我是先写好大模板和各个模块的代码,然后才开始做按要求去实现功能的,功能由简单到难。


    附件:第十三届蓝桥杯单片机程序设计、客观题PDF

    [https://pan.baidu.com/s/1Ltli7XGM45BI-M85FDPBpQ?pwd=whto]

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯第十三届单片机省赛:CT107D——IAP15F2K61S2 真题

    发表评论