蓝桥杯第十一届单片机国赛真题(CT107D——IAP15F2K61S2)

文章目录

  • 前言
  • 一、代码相关定义、声明
    • 1.头文件声明
    • 2.变量声明
    • 3.函数声明
  • 二、主要函数
    • 1.main函数
    • 2.按键扫描
    • 3.数码管显示
    • 4.LED指示功能
    • 5.定时器中断
    • 6.消除85°C显示


前言

相关说明:

开发板:CT107D (IAP15F2K61S2)
开发环境:Keil5
涉及题目:第十一届蓝桥杯单片机国赛真题
蓝桥杯第十一届单片机国赛真题(CT107D——IAP15F2K61S2)_第1张图片


主要函数代码及说明:

一、代码相关定义、声明

1.头文件声明

#include "stdio.h"
#include "Timer.h"
#include "bsp_init.h"
#include "bsp_key.h"
#include "bsp_seg.h"
#include "bsp_led.h"
#include "bsp_onewire.h"
#include "bsp_iic.h"
#include "bsp_ds1302.h"

2.变量声明

//--定时器滴答变量
unsigned long ms_Tick = 0;

//--定时器滴答变量
xdata unsigned long ms_Tick = 0;
xdata unsigned long ms_Tick_LED_Liang = 0;
xdata unsigned long ms_Tick_LED_An = 0;

//--定时器减速变量
unsigned int Key_Slow_Down;
unsigned int Seg_Slow_Down;
unsigned int Led_Slow_Down;

//--按键专用变量
unsigned char Key_Value;
unsigned char Key_Old, Key_Down;

//--数码管专用变量
unsigned char seg_string[10];
unsigned char seg_buf[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char pos;

//--LED专用变量
unsigned char ucLed = 0x00;

//00-数据界面时间显示;01-数据界面温度显示;02-数据界面亮暗状态显示;
//10-参数界面时间显示;11-参数界面温度显示;12-参数界面指示灯显示
unsigned char Disp_Flag = 0x00;

unsigned char Hour_P = 17;//小时参数,00-23
unsigned char Temp_P = 25;//温度参数,00-99
unsigned char LED_P = 4;//指示灯参数,4-8

unsigned char Hour_P_Ctrl = 17;//起作用-小时参数,00-23
unsigned char Temp_P_Ctrl = 25;//起作用-温度参数,00-99
unsigned char LED_P_Ctrl = 4;//起作用-指示灯参数,4-8

float Temp_Num;//测量的温度数据
float Photo_R_Voltage_Num;//光敏电阻电压数值
bit Liang_An_Flag;//0-亮,1-暗
bit Liang_An_Flag_Over_3_Sec;//亮暗超过3秒标志
bit Liang_First_Time;//是否第一次触发亮三秒标志
bit An_First_Time;//是否第一次触发暗三秒标志

3.函数声明

void Key_Proc(void);
void Seg_Proc(void);
void Led_Proc(void);
void Delay750ms();		//@12.000MHz

二、主要函数

1.main函数

void main(void)
{

	Cls_Peripheral();//关闭LED/继电器/蜂鸣器
	Timer1Init();//定时器1初始化
	EA = 1;//打开总中断
	rd_temperature();
	Delay750ms();//用于消除上电显示85°C的影响
	while(1)
	{
		Key_Proc();
		Seg_Proc();
		Led_Proc();
	}
}

2.按键扫描

void	Key_Proc(void)
{
	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 4://界面切换,数据界面和参数界面
			if((Disp_Flag>>4) == 0)
				Disp_Flag = 0x10;
			else if((Disp_Flag>>4) == 1)
			{
				Disp_Flag = 0x00;
				Hour_P_Ctrl = Hour_P;
				Temp_P_Ctrl = Temp_P;
				LED_P_Ctrl = LED_P;
			}
		break;
		
		case 5://子界面切换,数据界面和参数界面完成三个子界面切换
			if((Disp_Flag>>4) == 0)
			{
				if(++Disp_Flag == 0x03) 
					Disp_Flag = 0x00;
			}
				else if((Disp_Flag>>4) == 1)
			{
				if(++Disp_Flag == 0x13) 
					Disp_Flag = 0x10;	
			}
		break;		
		
		case 9://+
			if(Disp_Flag == 0x10)
			{if(++Hour_P == 24) Hour_P = 23;}	
			else if(Disp_Flag == 0x11)
			{if(++Temp_P == 100) Temp_P = 99;}
			else if(Disp_Flag == 0x12)
			{if(++LED_P == 9) LED_P = 8;}
		break;
		
		case 8://-
			if(Disp_Flag == 0x10)
			{if(--Hour_P== 255) Hour_P = 0;}	
			else if(Disp_Flag == 0x11)
			{if(--Temp_P == 255) Temp_P = 0;}	
			else if(Disp_Flag == 0x12)
			{if(--LED_P == 3) LED_P = 4;}			
		break;
	}
}

3.数码管显示

void Seg_Proc(void)
{
	if(Seg_Slow_Down) return;
	Seg_Slow_Down = 1;
	
	Read_Rtc(Rtc);
	Temp_Num = rd_temperature()/16.0;
	Photo_R_Voltage_Num = Pcf8591_Adc(Photo_Res_Channel)/51.0;
	if(Photo_R_Voltage_Num < 0.5)
	{
		Liang_An_Flag = 1;//暗
		
		if(An_First_Time == 0)
		{
			ms_Tick_LED_An = ms_Tick;
			An_First_Time = 1;
			Liang_First_Time = 0;
		}
		if((ms_Tick - ms_Tick_LED_An)>=3000)
			Liang_An_Flag_Over_3_Sec = 1;
	}		
	else 
	{
		Liang_An_Flag = 0;//亮
		
		if(Liang_First_Time == 0)
		{
			ms_Tick_LED_Liang = ms_Tick;
			Liang_First_Time = 1;
			An_First_Time = 0;
		}		
		if((ms_Tick - ms_Tick_LED_Liang)>=3000)
			Liang_An_Flag_Over_3_Sec = 0;	
	}
	
	switch(Disp_Flag)
	{
		case 0x00:
			sprintf(seg_string,"%02d-%02d-%02d",(unsigned int)Rtc[0],(unsigned int)Rtc[1],(unsigned int)Rtc[2]);			
		break;
		
		case 0x01:
			sprintf(seg_string,"C    %4.1f",Temp_Num);	
		break;
		
		case 0x02:
			sprintf(seg_string,"E %4.2f  %d",Photo_R_Voltage_Num,(unsigned int)Liang_An_Flag);	
		break;	
		
		case 0x10:
			sprintf(seg_string,"P1    %02d",(unsigned int)Hour_P);	
		break;		
	
		case 0x11:
			sprintf(seg_string,"P2    %02d",(unsigned int)Temp_P);	
		break;		
	
		case 0x12:
			sprintf(seg_string,"P3     %1d",(unsigned int)LED_P);	
		break;	
	}
	
	Seg_Tran(seg_string, seg_buf);
}

4.LED指示功能

void	Led_Proc(void)
{
	if(Led_Slow_Down) return;
	Led_Slow_Down = 1;
		
 	if(Hour_P_Ctrl < 8)
	{
		if((Rtc[0] < 8)&&(Rtc[0] >= Hour_P_Ctrl))
			ucLed |= 0x01;//L1点亮 
		else 
			ucLed &= (~0x01);//L1熄灭 
	}
	else if(Hour_P_Ctrl >= 8)
	{
		if((Rtc[0] >= 8)&&(Rtc[0] < Hour_P_Ctrl))
			ucLed &= (~0x01);//L1熄灭 
		else 
			ucLed |= 0x01;//L1点亮 				
	}
	
	if(Temp_Num < Temp_P_Ctrl)
      ucLed |= 0x02;//L2点亮
	else
			ucLed &= (~0x02);//L2熄灭 		
 	
	if(Liang_An_Flag_Over_3_Sec == 1)
      ucLed |= 0x04;//L3点亮	
	else 
			ucLed &= (~0x04);//L3熄灭 		

	if(Liang_An_Flag == 1)//暗状态,点亮指定的LED灯
	{
		ucLed &= (~0xF8);//所有灯全部熄灭 		
		switch (LED_P_Ctrl)
		{
			case 4:
      ucLed |= 0x08;//L4点亮					
			break;
			case 5:
      ucLed |= 0x10;//L5点亮						
			break;			
			case 6:
      ucLed |= 0x20;//L6点亮					
			break;			
			case 7:
      ucLed |= 0x40;//L7点亮						
			break;		
			case 8:
      ucLed |= 0x80;//L8点亮				
			break;		
		}
	}
	else 
		ucLed &= (~0xF8);//所有灯全部熄灭			
}

5.定时器中断

void tm1_isr() interrupt 3
{
	ms_Tick++;//滴答定时器,能记录的数据长达29天

	if(++Key_Slow_Down == 10) Key_Slow_Down = 0;//减速变量区,控制子函数的刷新频率
	if(++Seg_Slow_Down == 500) Seg_Slow_Down = 0;	
	if(++Led_Slow_Down == 100) Led_Slow_Down = 0;	
	
    Seg_Disp(seg_buf, pos);//用于数码管显示
	if(++pos == 8) pos = 0;
	
	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);
}

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