【第十四届蓝桥杯单片机冲刺版】

【第十四届蓝桥杯单片机冲刺版】

明天就是正式比赛啦,今天可以在把各个模块练习一遍,常考的外设相关代码一定要熟练哦。
比赛时拿到资料包了,检查驱动文件,使用到的驱动文件,自己做相应的修改,确保是能够正常使用(驱动修改相关可看之前的文章)。
下面是自己将常考的外设结合一起的练习,需要完整工程的自取哈

链接:https://pan.baidu.com/s/1yc-GG_hqpqU5qzTsA8UOtA?pwd=l99q 
提取码:l99q 
--来自百度网盘超级会员V5的分享
祝大家都可以取得好成绩,有帮助就给个赞和关注吧

功能说明

下面练习中结合了温度采集、adc采集、时钟显示、超声波、频率测试、独立按键,矩阵按键、串口接收串口发送、长按等相关操作。
按键操作:
S4作为界面和模式切换(温度、电压、时间、距离)
S5 作为长按(第一次长按关闭LED显示第二次长按打开)
S6 作为长按(第一次长按关闭数码管显示第二次打开)
S7 作为向串口发送按键,会将当前界面的数据发送到串口
串口操作:
通过串口中断接收 字符A B C D 分别进行温度、电压、时间、距离界面和模式的切换并将当前界面数据发送到PC

定时器分配:

定时器1:一般用来做串口
定时器2:数码管以及一些频率变量刷新操作
定时器0:超声波或者频率

#include <STC15F2K60S2.H>
#include "iic.h"
#include "onewire.h"
#include "ds1302.h"

/*========================十四届蓝桥杯单片机考前一天冲刺=========================
@Author:小殷
@Date:2023.4.7
================================================================================*/

sbit TX = P1^0;
sbit RX = P1^1;
typedef unsigned char uchar;
typedef unsigned int  uint;
#define Control_Port(x,y)  P0 = y;P2 = x;P2 = 0
//=======================下面为变量定义==========================
uchar smg_data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xc1,0xbf};
uchar smg_bit[9] = {10,10,10,10,10,10,10,10,10};               //数码管初始化全熄灭
uchar L[5];                                                    //LED操作
uchar interface = 1;                                           //界面
static uchar hour = 0,min= 0,sec = 0;                          //时分秒
static uint Temperature = 0;                                   //温度
static uint adc_volt = 0;                                      //电压
static uchar key_feq = 0;                                      //按键刷新频率
static uchar adc_feq = 0;                                      //adc采集频率
static uchar t_feq = 0;                                        //温度刷新频率
static uchar dis_feq = 0;                                      //距离刷新频率
static uchar smg_flag =1;                                      //数码管打开关闭标志
static uchar led_flag =1;                                      //led打开关闭标志
static uchar send_data_flag = 0;                               //按键发送             
static uint distance = 0;                                      //距离
uchar usart_cmd = 0;                                           //串口接收指令缓存

//=======================下面为函数声明===========================
void Timer2Init(void);		                                  //1毫秒@12.0定时器2初始化
void Delay5ms();		                                      //@12.000MHz 5ms延时
void UartInit(void);		                                  //9600bps@12.000MH串口初始化
void Send_Byte(uchar dat);                                    //发送一个字节
void Send_String(uchar *str);                                 //发送字符串
void Delay12us();		                                      //@12.000MHz    12us                        
void Send_Wave(void);                                         //发波8个40khz
uint Get_Distance(void);                                      //获取距离
void Set_DS1302_Timer(uchar hour,uchar min,uchar sec);        //设置ds1302时间
float Read_Temperature(void);                                 //温度获取
uchar Read_Key_Value(void);                                   //键值获取
uchar Read_ADC_Value(uchar addr);                             //ADC获取
void Data_Tackle_Task(void);                                  //数据处理任务
void Key_Tackle_Task(void);                                   //按键处理任务
void SMG_Display_Task(void);                                  //数码管处理任务
void Init_System(void);                                       //系统初始化
void Send_Data(uchar interface);                              //发送数据 串口相关
void Send_Volt(void);                                         //发送电压
void Send_Temperature(void);                                  //发送温度
void Send_Timer(void);                                        //发送时间
void Send_Distance(void);                                     //发送距离
//========================下面为函数实现==========================

void Timer2Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x20;		//设置定时初值
	T2H = 0xD1;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	IE2 |= 0x04;
	EA = 1;
}



void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

void UartInit(void)		//9600bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器时钟1T模式
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0xC7;		//设置定时初始值
	TH1 = 0xFE;		//设置定时初始值
	ET1 = 0;		//禁止定时器%d中断
	TR1 = 1;		//定时器1开始计时
	ES = 1;
	EA = 1;
}


void Send_Byte(uchar dat)
{
	SBUF = dat;
	while(TI == 0);
	TI = 0;
}
void Send_String(uchar *str)
{
	while(*str != '\0')
	{
		Send_Byte(*str++);
	}
}
void Delay12us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}

void Send_Wave(void)
{
	uchar i = 0;
	for(i = 0;i<8;i++)
	{
		TX = 1;
		Delay12us();
		TX = 0;
		Delay12us();
	}
}

uint Get_Distance(void)
{
	uint dis = 0;
	TMOD &= 0xf0;
	TH0 = 0;
	TL0 = 0;
	Send_Wave();
	TR0 = 1;
	while((RX == 1) && (TF0 == 0));
	TR0 = 0;
	if(TF0 == 0)
	{
		dis = (TH0 << 8)|TL0;
		dis *= 0.017;
	}
	else
	{
		TF0 = 0;
		dis = 999;
	}
	return dis;
}

uchar Read_Key_Value(void)
{
	static uchar last_trg = 0,cnt = 0;
	uchar cur = 0,trg = 0,value = 3;
	static uint long_count = 0;
	static bit long_flag = 0;
	cur = (P3 | 0x10)^0xff;
	trg = cur^cnt & cur;
	cnt = cur;	
	if((last_trg ^ trg & last_trg) && cur)
	{
		if(cur & 0x08) value = 4;
		else if(cur & 0x04) value = 5;
		else if(cur & 0x02) value = 6;
		else if(cur & 0x01) value = 7;
	}
	last_trg = trg;
	
	if(cur)
	{
		if((!long_flag) && (++long_count == 100)) //1s
		{
			long_flag = 1;
		   if(cur & 0x04) value = 5 + 100;
			else if(cur & 0x02) value = 6 + 100;

		}
	}
	else
	{
		long_count = 0;
		long_flag = 0;
	}
	return value;
}


uchar Read_ADC_Value(uchar addr)
{
	uchar adc = 0;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CStop();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	adc = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return adc;
}

void Set_DS1302_Timer(uchar hour,uchar min,uchar sec)
{
	Write_Ds1302_Byte(0x8e,0x00);
	Write_Ds1302_Byte(0x80,sec/10*16 + sec%10);
	Write_Ds1302_Byte(0x82,min/10*16 + min%10);
	Write_Ds1302_Byte(0x84,hour/10*16 + hour%10);
	Write_Ds1302_Byte(0x8e,0x80);
}

float Read_Temperature(void)
{
	uchar LSB = 0,MSB = 0;
	float temp = 0.0;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	temp = ((MSB << 8)|LSB) * 0.0625;
	return temp;
}

void Key_Tackle_Task(void)
{
	uchar key_value = 0;
	if(key_feq > 10)
	{
		key_feq = 1;
		key_value = Read_Key_Value();
	}
	if(key_value == 4)
	{
		if(++interface > 4)
		{
			interface = 1;
		}
	}
	
	//长按S5 关闭LED 长按S6 关闭SMG
	else if(key_value == 105)
	{
		led_flag = !led_flag;
	}
	else if(key_value == 106)
	{
		smg_flag = !smg_flag;
	}
	//S7 将电压发送到串口
	if(key_value == 7)
	{
		send_data_flag = 1;
	}

}

//对应界面的数据发送
void Send_Data(uchar interface)
{
	switch(interface)
	{
		case 1:Send_Temperature();break;
		case 2:Send_Volt();break;
		case 3:Send_Timer();break;
		case 4:Send_Distance();break;
	}
}
void Send_Volt(void)
{
	Send_String("Volt:");
	Send_Byte(adc_volt/100+'0');
	Send_Byte('.');
	Send_Byte(adc_volt/10%10+'0');
	Send_Byte(adc_volt%10+'0');
	Send_String("v\r\n");
}
void Send_Temperature(void)
{
	Send_String("Temperature:");
	Send_Byte(Temperature/100+'0');
	Send_Byte(Temperature/10%10+'0');
	Send_Byte('.');
	Send_Byte(Temperature%10+'0');
	Send_String("℃\r\n");
}
void Send_Timer(void)
{
	Send_String("Time:");
	Send_Byte(hour/10+'0');
	Send_Byte(hour%10+'0');
	Send_Byte(':');
	Send_Byte(min/10+'0');
	Send_Byte(min%10+'0');
	Send_Byte(':');
	Send_Byte(sec/10+'0');
	Send_Byte(sec%10+'0');
	Send_String("\r\n");
}

void Send_Distance(void)
{
	Send_String("Dis:");
	if(distance > 99)
	{
		Send_Byte(distance/100+'0');
		Send_Byte(distance/10%10+'0');
		Send_Byte(distance%10+'0');
	}
	else if(distance > 9)
	{
		Send_Byte(distance/10%10+'0');
		Send_Byte(distance%10+'0');
	}
	else
	{
		Send_Byte(distance%10+'0');
	}
	Send_String("cm\r\n");
}
void Data_Tackle_Task(void)
{
	uchar time[3];
	if(T2H < 0xd9)
	{
		if(adc_feq > 150)
		{
			adc_feq = 1;
			adc_volt = Read_ADC_Value(0x03) * (5.0/255) * 100;
		}
		
		if(interface == 3)
		{
			time[0] = Read_Ds1302_Byte(0x81);
			time[1] = Read_Ds1302_Byte(0x83);
			time[2] = Read_Ds1302_Byte(0x85);
			hour = (time[2]/16*10 + time[2]%16);
			min  = (time[1]/16*10 + time[1]%16);
			sec  = (time[0]/16*10 + time[0]%16);
		}
		
		if(t_feq > 150)
		{
			t_feq = 1;
			Temperature = Read_Temperature() * 10;
		}
		
		if(dis_feq > 150)
		{
			dis_feq = 1;
			distance = Get_Distance();
		}
		

	}
	

	

	
	//LED控制
	L[1] = (interface == 1)?(1):(0);
	L[2] = (interface == 2)?(1):(0);
	L[3] = (interface == 3)?(1):(0);
	L[4] = (interface == 4)?(1):(0);
	
	//串口发送
	if(send_data_flag)
	{
		send_data_flag = 0;
		Send_Data(interface);
	}
	
	//串口控制界面切换
	switch(usart_cmd)
	{
		case 'A':interface = 1;Send_Data(interface);break;  //温度
		case 'B':interface = 2;Send_Data(interface);break;  //电压
		case 'C':interface = 3;Send_Data(interface);break;  //时间
		case 'D':interface = 4;Send_Data(interface);break;  //距离
		default:break;
	}
	usart_cmd = 0;
	
}
void SMG_Display_Task(void)
{
	if(interface == 1)
	{
		smg_bit[1] = 11;
		smg_bit[2] = interface;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = Temperature/100;
		smg_bit[7] = Temperature/10%10;
		smg_bit[8] = Temperature%10;
	}
	else if(interface == 2)
	{
		smg_bit[1] = 11;
		smg_bit[2] = interface;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = adc_volt/100;
		smg_bit[7] = adc_volt/10%10;
		smg_bit[8] = adc_volt%10;
	}
	else if(interface == 3)
	{
		smg_bit[1] = hour/10;
		smg_bit[2] = hour%10;
		smg_bit[3] = 12;
		smg_bit[4] = min/10;
		smg_bit[5] = min%10;
		smg_bit[6] = 12;
		smg_bit[7] = sec/10;
		smg_bit[8] = sec%10;
	}
	else if(interface == 4)
	{
		smg_bit[1] = 11;
		smg_bit[2] = interface;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = (distance>99)?(distance/100):(10);
		smg_bit[7] = (distance>9)?(distance/10%10):(10);
		smg_bit[8] = distance%10;
	}
}

void Init_System(void)
{
	Control_Port(0x080,0xff);
	Control_Port(0xa0,0x00);
	Control_Port(0xc0,0x00);
	
	while(t_feq++ < 150)
	{
		Temperature = Read_Temperature() * 10;
	}
	UartInit();
	Delay5ms();
	Timer2Init();
	Set_DS1302_Timer(11,59,50);
	Send_String("Usart Test\r\n");
}

void main(void)
{
	Init_System();
	while(1)
	{
		Data_Tackle_Task();
		Key_Tackle_Task();
		SMG_Display_Task();
	}
}


void Timer2_Server() interrupt 12
{
	static uchar dsp_smg = 1;
	if(led_flag)
	{
		Control_Port(0x80,~(L[1] << 0 | L[2] << 1 | L[3] <<2 | L[4] << 3));
	}
	else
	{
		Control_Port(0x80,0xff);
	}
	Control_Port(0xc0,0x00);
	if(smg_flag)
	{
		if((interface == 1 && dsp_smg == 7) || (interface == 2 && dsp_smg == 6))
		{
			Control_Port(0xe0,smg_data[smg_bit[dsp_smg]] & 0x7f);
		}
		else
		{
			Control_Port(0xe0,smg_data[smg_bit[dsp_smg]]);
		}
		
		Control_Port(0xc0,1 << (dsp_smg - 1));
		if(++dsp_smg > 8)
		{
			dsp_smg = 1;			
		}
	}
	else
	{
		Control_Port(0xc0,0x00);
	}
	key_feq++;
	t_feq++;
	adc_feq++;
	dis_feq++;
}

void Usart_Server() interrupt 4
{
	if(RI)
	{
		RI = 0;
		usart_cmd = SBUF;
	}
}

由于超声波和频率都是用定时器0,上面工程中使用的是超声波,频率部分请看下面哈

//频率测量在定时器2中断中进行 (定时器0)
void Init_Timer0(void)
{
	AUXR = 0x80;
	TMOD = 0x04;
	TH0  = 0;
	TL0  = 0;
	TR0  = 1;
}
void Timer2_Server() interrupt 12
{
	static uchar dsp_smg = 1;
	static uint feq_count;

	if(++feq_count == 500)
	{
		feq_count = 0;
		TR0 = 0
		Feq = ((uint)(TH0 << 8) | TL0) * 2;
		TH0 = TL0 = 0;
		TR0 = 1;
	}

	Control_Port(0xc0,0x00);
	Control_Port(0xe0,smg_data[smg_bit[dsp_smg]]);
	Control_Port(0xc0,1 << (dsp_smg -1));
	if(++dsp_smg > 8)
	{
		dsp_smg = 1;
	}
}

物联沃分享整理
物联沃-IOTWORD物联网 » 【第十四届蓝桥杯单片机冲刺版】

发表评论