【第十四届蓝桥杯单片机模拟题2优化版】

本文分享了第十四届蓝桥杯单片机组模拟题2的代码优化版本,重点在于代码的简洁和高效。程序包括数码管显示、ADC电压采集、串口通信以及按键处理等功能。同时,代码中包含了部分来自蓝桥之路作者和小蜜蜂老师的模板。文章提供了完整的工程链接,供读者参考和学习,并祝参赛者取得好成绩。
摘要由CSDN通过智能技术生成

【第十四届蓝桥杯单片机模拟题2优化版】

下面分享的是第十四届蓝桥杯单片机组模拟题2的优化版,相对于之前发布的文章,这次在写法上有了很大不同,主要解决了代码简洁高效的问题,代码中部分模板来自蓝桥之路作者Jack和小蜜蜂老师,当然也有自己的一些编程思路在里面,若有错还望各位大佬指出。

完整工程链接,需要自取

链接:https://pan.baidu.com/s/1_fbVY4zSYFRKMb1_-cvNAg?pwd=97ps
提取码:97ps
–来自百度网盘超级会员V5的分享

在这里插入图片描述

若有帮助,点个赞加关注吧,也可以分享给需要的小伙伴哦

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

===================================祝大家在比赛中都能取得好成绩=============================
#include <STC15F2K60S2.H>
#include "iic.h"
#include "stdio.h"
#include "string.h"
/*============================第十四届模拟题2=========================
@Author:小殷
@Date:2023.4.1
@Note:该程序中按键相关算法及部分模板来自蓝桥之路作者Jack 
======================================================================*/
typedef unsigned char uchar;
typedef unsigned int  uint;

#define Control_Port(x,y) P0 = y;P2 = x;P2 = 0;
//0-9 0xff - U F 
code uchar smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff, 0xc1};
uchar smg_bit[9] ={10,10,10,10,10,10,10,10,10};      //默认关闭数码管
uchar Send_Buf[12] = {0},buf[12] = {0},count = 0;    //串口接收发送标志相关
uchar usart_flag = 0;                                //接收完成标志位
uchar L[9] ,L8_Flag = 0;                             //led
bit L8_Status;                                       //LED8 状态
uint adc_volt;                                       //电压实时值
uint db_value = 0;                                   //数码管显示值
uint db_param = 65;                                  //db参数设置
uchar interface = 1;                                 //界面
uchar key_feq = 0;                                   //按键刷新频率
uchar adc_feq = 0;                                   //adc采集频率
//============================下面为函数相关声明===========================
void Timer2Init(void);		                      //1毫秒@12.000MHz
void smg_display_task(void);                      //数码管显示任务
uchar Read_ADC_Volt(void);                         //ADC采集
void data_tackle_task(void);                      //数据处理任务
uchar Read_Key_Value(void);                       //按键值获取
void Key_Tackle_Task(void);                       //按键处理任务
void SendByte(unsigned char dat);                  //发送一个字节
void SendString(unsigned char *str);               //发送字符串
void UartInit(void);		                       //串口初始化
void Init_System(void);                           //系统初始化
//============================下面为函数功能实现部分=======================
void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

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

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




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 SendByte(unsigned char dat)
{
 	SBUF = dat;
	while(TI == 0); //等待发送完成
	TI = 0;	 //清除标志位
}

//发送一个字符串
void SendString(unsigned char *str)
{
 	//字符串以'\0'为结束标志
	while(*str != '\0')
	{
		SendByte(*str++);
	}
}
void smg_display_task(void)
{
	if(interface == 1)
	{
		smg_bit[1] = 11; //U 1000 0011 0xc1
		smg_bit[2] = interface;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = db_value/100;
		smg_bit[7] = db_value/10%10;	
		smg_bit[8] = db_value%10;
	}
	else if(interface == 2)
	{
		smg_bit[1] = 11; //U 1000 0011 0xc1
		smg_bit[2] = interface;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = 10;
		smg_bit[7] = (db_param > 9) ?(db_param/10%10):(10);
		smg_bit[8] =  db_param%10;
	}

}


uchar Read_ADC_Volt(void)
{
	uchar adc = 0;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x03);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	adc = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
//	volt = adc * (5.0/255) * 100;
	return adc;
}

//下面为数据处理任务
void data_tackle_task(void)
{
	
	if(adc_feq > 20)
	{
		adc_feq = 1;
		adc_volt =  (Read_ADC_Volt() * (5.0/255)) * 100;
		if(adc_volt > 0 && adc_volt <= 500)
		{
			//一次函数变化 y = 18x
			db_value =  18 * adc_volt/10;  //保留一位小数
		}
		else if(adc_volt > 500)
		{
			db_value = 900;
		}
	}
	
	//下面为LED逻辑处理
	L[1] = (interface == 1)?(1):(0);
	L[2] = (interface == 2)?(1):(0);
	if(db_value > db_param * 10)
	{
		L8_Flag = 1;
	}
	else
	{
		L8_Flag = 0;
	}
	if(usart_flag == 1)
	{
		
		usart_flag = 0;
		//if(buf[0] == 'R' && buf[1] == 'e' && buf[2] == 't' && buf[3] == 'u' && buf[4] == 'r' && buf[5] == 'n')
		if(strcmp(buf,"Return") == 0)
		{
			SendString("Noises: ");	
			if(db_value > 99)
			{
				SendByte(db_value/100 + '0');
				SendByte(db_value/10%10 + '0');
				SendByte('.');
				SendByte(db_value%10 + '0');
			}
			else if(db_value > 9)
			{
				SendByte(db_value/10 + '0');
				SendByte('.');
				SendByte(db_value%10 + '0');
			}
			else
			{
			  SendByte(db_value%10 + '0');
			}
			SendString("db\r\n");
			
		}
	}
}

uchar Read_Key_Value(void)
{
	static uchar last_trg = 0,cnt = 0;
	uchar trg = 0,cur = 0,value = 3,key_x = 0,key_y = 0;
	
	//P3 = 0x0f;   P3^0 P3^1 不使用 避免影响串口
	P37 = 0;
	P36 = 0;
	P35 = 0;
	P34 = 0;
	P33 = 1;
	P32 = 1;
	//P31 = 1;
	//P30 = 1;
	P4 = 0x00;
	//if(!P30) key_x = 3;
	//else if(!P31) key_x = 2;
	if(!P32) key_x = 1;
	else if(!P33) key_x = 0;
	P37 = 1;
	P36 = 1;
	P35 = 1;
	P34 = 1;
	P33 = 0;
	P32 = 0;
	//P31 = 0;
	//P30 = 0;
	P4 = 0xff;
	if(!P34) key_y = 4;
	else if(!P35) key_y = 3;
	else if(!P42) key_y = 2;
	else if(!P44) key_y = 1;
	
	cur = key_y^0x00;
	trg = cur ^ cnt & cur;
	cnt = cur;
	if((last_trg^trg&last_trg) && cur)
	{
		value = key_x + key_y * 4;
	}
	
	last_trg = trg;
	return value;
}
void Key_Tackle_Task(void)
{
	uchar key_value = 0;
	if(key_feq > 10)
	{
		key_feq = 1;
		key_value = Read_Key_Value();
	}
	switch(key_value)
	{
		case 12:
			interface = (interface == 1)?(2):(1);
			break;
		case 16:
			if(interface == 2)
			{
				if(db_param < 90)
				{
					db_param += 5;
				}
				else
				{
					db_param = 90;
				}
				 
			}				
			break;
		case 17:
			if(interface == 2)
			{
				if(db_param > 5)
				{
					db_param -= 5;
				}
				else
				{
					db_param = 0;
				}
			}				
			break;
		default:break;
	}
}




void Init_System(void)
{
	Control_Port(0x80,0xff);      //关闭LED
	Control_Port(0xa0,0x00);      //关闭蜂鸣器 继电器
	UartInit();                  //串口初始化
	Delay5ms();                  //延时等待串口初始化完成
	Timer2Init();                //定时器2初始化
}

void main(void)
{
	Init_System();               //系统初始化
	while(1)
	{
		data_tackle_task();      //数据处理任务
		smg_display_task();      //数码管显示任务
		Key_Tackle_Task();       //按键任务
	}
}


//串口中断接收
void Usart_Server() interrupt 4
{
	unsigned char temp =0;
	if(RI)
	{
		RI = 0;
		temp = SBUF;
		if(temp == 0 || temp == '\r' || temp == '\n')   //结束符判断
		{
			usart_flag = 1;   //接收完成标志
			buf[count] = '\0';
			count = 0;       //计数清零等待下一帧数据
		}
		else
		{
			buf[count++] = temp;   //接数据的值存入到buf数组中
		}
	}
}

void Timer2_Server() interrupt 12
{
	static uchar dsp_smg = 1;
	static uchar L8_Count = 0;
	Control_Port(0x80,~(L[1] << 0|L[2] << 1 | L[8] << 7));
	Control_Port(0xc0,0);
	//带小数显示
	if(interface == 1 && dsp_smg == 7)
	{
		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;
	}
	key_feq++;            //按键刷新频率
	adc_feq++;            //adc采集频率
	
	if(L8_Flag)
	{
		if(++L8_Count == 100)
		{
			L8_Count = 1;
			L8_Status = !L8_Status;
			L[8] = L8_Status;
		}
	}
	
}

在这里插入图片描述

补充:

部分小伙伴反应串口点击发送后没有反应,因为在代码串口中断接收部分进行了接收符相关的判断的,所以在串口助手发送时需要勾选上发送结束符,好像题目并没有规定要接受到发送结束符之后再返回PC端数据,应该不进行判断也行,下面为不进行结束符判断补充

在这里插入图片描述

在接收完成的逻辑处理部分进行数组的清除和count清零

在这里插入图片描述

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小殷学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值