【第十四届蓝桥杯单片机模拟题3】
下面这套题应该也是第十四届的模拟题,具体是那套不清楚了,同样也有串口相关的功能,这一届考串口不出意外应该是必不可少了,对应串口的接收和发送还不同会的小伙伴可以看看哦,(同样也欢迎指出错误以及分享更好的实现方式)。
若有帮助请给小殷一个关注和赞赞吧,你们的支持也是我前进的重要动力鸭
下面是完成的工程链接,有需自提哈
链接:https://pan.baidu.com/s/1c-iNZTHcy8PQcbrkgfPgPw?pwd=i55a
提取码:i55a
–来自百度网盘超级会员V5的分享
距第十四届蓝桥杯还剩最后两天时间,祝各位小伙伴都可以取得好成绩,加油鸭 别忘记点赞关注哦
注意:
在题目中有串口和矩阵键盘的功能,注意避开串口引脚的操作哦,不然串口发送会有问题,数码管也会受到影响
#include <STC15F2K60S2.H>
#include "iic.h"
#include "onewire.h"
/*======================第十四届蓝桥杯单片机模拟题===================
@Author:小殷
@Date:2023.4.5
=====================================================================*/
typedef unsigned char uchar;
typedef unsigned int uint;
#define Control_Port(x,y) P0 = y;P2 = x;P2 = 0
uchar smg_bit[9] = {10,10,10,10,10,10,10,10,10}; //设置为10对应着0xff 关闭数码管初始化
//数码管段码 0-9 shut-off -
uchar smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xc1,0xbf,0xc6,0x8c,0x88};
uchar L[4]; //LED
uchar interface = 1; //界面
uint Temperature = 0; //温度
uint adc_volt = 0; //电压
uchar key_feq = 0; //按键刷新周期
uchar adc_feq = 0; //adc读取周期
uchar temperature_feq = 0; //温度读取周期
uchar relay = 0,buzzer = 0; //继电器和蜂鸣器
uchar usart_cmd = 0; //串口接收缓存
uchar lock_flag = 0,usart_flag = 0;//锁定状态和串口发送状态
//=========================下面为相关函数声明=================================
void Delay5ms(); //@12.000MHz
void Timer2Init(void); //1毫秒@12.000MHz
void UartInit(void); //9600bps@12.000MHz
void Send_Byte(uchar dat); //发送字节
void Send_String(uchar *str); //发送字符串
float Read_Temperature(void); //读取温度
void Data_Tackle_Task(void); //数据处理任务
void SMG_Dispaly_Task(void); //数码管显示任务
uchar Read_Key_Value(void); //按键值获取
void Key_Tackle_Task(void); //按键处理任务
uchar Read_ADC_Value(uchar dat); //ADC值读取
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 Send_Byte(uchar dat)
{
SBUF = dat;
while(TI == 0);
TI = 0;
}
void Send_String(uchar *str)
{
while(*str != '\0')
{
Send_Byte(*str++);
}
}
float Read_Temperature(void)
{
uchar LSB = 0,MSB = 0;
float temp = 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 Data_Tackle_Task(void)
{
if(temperature_feq > 150)
{
temperature_feq = 1;
Temperature = Read_Temperature() * 10;
}
if(adc_feq > 150)
{
adc_feq = 1;
adc_volt = Read_ADC_Value(0x03) *(5.0/255) * 100;
}
//下面为LED控制逻辑处理
L[1] = (interface == 1)?(1):(0);
L[2] = (interface == 2)?(1):(0);
//下面为继电器和蜂鸣器控制逻辑处理
relay = (Temperature/10 >= 28)?(1):(0);
buzzer = (adc_volt > 360)?(1):(0);
//下面为串口功能处理
if(usart_flag)
{
usart_flag = 0;
if(interface == 1)
{
Send_String("TEMP:");
Send_Byte(Temperature/100 + '0');
Send_Byte(Temperature/10%10 + '0');
Send_Byte('.');
Send_Byte(Temperature%10 + '0');
Send_String("℃\r\n");
}
else if(interface == 2)
{
Send_String("Voltage:");
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");
}
}
if(lock_flag)
{
if(usart_cmd == 'A')
{
interface = 1;
Send_String("TEMP:");
Send_Byte(Temperature/100 + '0');
Send_Byte(Temperature/10%10 + '0');
Send_Byte('.');
Send_Byte(Temperature%10 + '0');
Send_String("℃\r\n");
}
else if(usart_cmd == 'B')
{
interface = 2;
Send_String("Voltage:");
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");
}
usart_cmd = 0; //清除等待下一次
}
}
void SMG_Dispaly_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;
}
}
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;P4 = 0x00;
P4 = 0x00;
//P30 = 1;
//P31 = 1;
P32 = 1;
P33 = 1;
P34 = 0;
P35 = 0;
P36 = 0;
P37 = 0;
//if(!P30) key_x = 3;
//else if(!P31) key_x = 2;
if(!P32) key_x = 1;
else if(!P33) key_x = 0;
//P3 = 0xf0;P4 = 0xff;
P4 = 0xff;
//P30 = 0;
//P31 = 0;
P32 = 0;
P33 = 0;
P34 = 1;
P35 = 1;
P36 = 1;
P37 = 1;
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();
}
if(key_value == 4)
{
lock_flag = 0; //只要按下S4即为锁定状态
interface = (interface == 1)?(2):(1);
}
if(key_value == 5)
{
if(lock_flag == 0) //锁定状态下才有效
{
lock_flag = 1; //解锁状态
}
}
if(key_value == 12) //通过按键进行串口发送
{
usart_flag = 1;
}
}
uchar Read_ADC_Value(uchar dat)
{
uchar adc = 0;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
adc = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return adc;
}
void Init_System(void)
{
Control_Port(0x80,0xff); //关闭LED
Control_Port(0xa0,0x00); //关闭蜂鸣器和继电器
Control_Port(0xc0,0x00); //关闭数码管
while(++temperature_feq < 150) //上电时代温度稳定后再读取可以避免出现错误值
{
Temperature = Read_Temperature()*10;
}
UartInit(); //串口初始化
Delay5ms(); //等待串口初始化完成
Timer2Init(); //定时器2初始化
//Send_String("Usart Test\r\n");
}
void main(void)
{
Init_System();
while(1)
{
Data_Tackle_Task();
SMG_Dispaly_Task();
Key_Tackle_Task();
}
}
void Timer2_Server() interrupt 12
{
static uchar dsp_smg = 1;
static uchar l3_count = 0;
//下面为LED控制
Control_Port(0x80,~(L[1] << 0 | L[2] << 1 | L[3] << 2));
//下面为蜂鸣器和继电器控制
Control_Port(0xa0,relay << 4 | buzzer << 6);
//下面为数码管控制
Control_Port(0xc0,0x00);
//小数显示
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;
}
//锁定状态
if(lock_flag == 0)
{
if(l3_count++ == 100)
{
l3_count = 0;
L[3] = !L[3];
}
}
//下面为相关数据刷新频率
temperature_feq++;
key_feq++;
adc_feq++;
}
void Usart_Server() interrupt 4
{
if(RI)
{
RI = 0; //清除中断标志位
usart_cmd = SBUF; //将接收指令缓存到usart_cmd
}
}