蓝桥杯第十三届单片机省赛真题(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]

你可能感兴趣的:(蓝桥杯真题,蓝桥杯,51单片机)