【蓝桥杯单片机第十一届国赛真题】
前言
有幸进入国赛,为自己大学最后一个比赛画上完满的句号^@^
下面为蓝桥杯单片机第十一届国赛程序部分,功能差不多都实现了,可能存在小bug,望大佬指正,总体来说这届难度并不是很大,有需完整工程的小伙伴可自行下载。
工程链接
链接: https://pan.baidu.com/s/1XA6F3sJ3PpSrtIL6gN3vAg?pwd=w4cv 提取码: w4cv 复制这段内容后打开百度网盘手机App,操作更方便哦
--来自百度网盘超级会员v5的分享
一、真题
二、源码
在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/*==============================================第九届国赛=====================================
@Author:小殷同学
@Date:2023.6.3
===============================================================================================*/
/*===============================================第十一届国赛===========================================
@Author:小殷同学
@Date:2023.6.3
=======================================================================================================*/
#include "public.h" //公共函数部分
#include "ds1302.h" //ds1302时钟相关
#include "iic.h" //iic adc eeprom相关
#include "onewire.h" //温度相关
/*==========================================下面为宏和变量相关定义====================================*/
//数码管段码(0~9、shut-off、"-"、)
code uchar smg_data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,
0xbf,0xc6,0x86, 0x8C};
//初始化,使所有数码管熄灭(必须是9个元素)
uchar L[9]; //LED
xdata uchar smg_bit[11] = {10,10,10,10,10,10,10,10,10}; //数码管位
xdata uchar hour = 16,min = 59,sec = 50; //时分秒
xdata uint temperature = 0; //温度
uchar light_mode = 0; //光敏亮暗模式 1暗 0亮
uchar l1_flag = 0; //LED1 标志
uchar l3_flag = 0,l3_flag2 = 0; //LED3 亮标志 暗标志
uchar adc_value = 0,last_adc = 0; //adc值和上一次adc值
xdata uint adc_volt = 0; //adc 电压
uchar interface_mode = 1; //界面模式(数据、参数)
uchar data_interface = 1; //数据界面索引
uchar param_interface = 4; //参数界面索引
uchar set_hour = 17,set_t = 25,set_led = 4; //时间参数 温度参数(00-99) led参数(4-8)
uchar param_set_hour = 17,param_set_t = 25,param_set_led = 4; //该变量为参数界面设置时生效
uchar valid_flag = 0; //是否生效 参数界面退出时生效
uchar time_feq = 0; //时间刷新周期
uchar key_feq = 0; //按键刷新周期
uchar t_feq = 0; //温度刷新周期
uchar adc_feq = 0; //adc电压采集周期
/*=================================================下面为函数声明========================================*/
void data_task(void); //数据采集任务
void logical_task(void); //逻辑处理任务
void smg_task(void); //数码管实现任务
void key_task(void); //按键任务
void Init_System(void); //系统初始化
/*================================================下面为函数功能实现=====================================*/
void data_task(void)
{
uchar time[3];
if(T2H < 0xd9)
{
if(time_feq > 200)
{
time_feq = 1;
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(adc_feq > 150)
{
adc_feq = 1;
last_adc = adc_value;
adc_value = Read_ADC(0x41);
adc_volt = adc_value * (5.0/255) *100;
}
}
}
void logical_task(void)
{
//下面为设置参数生效
if(valid_flag == 1)
{
set_hour = param_set_hour;
set_t = param_set_t;
set_led = param_set_led;
}
//下面为光敏亮暗状态的判断
if((adc_value < 60) && (last_adc > (adc_value + 6)))
{
light_mode = 1; //暗状态
}
else if(adc_value > 60)
{
light_mode = 0; //亮状态
}
if(light_mode == 1 && l3_flag == 1)
{
L[3] = 1;
l3_flag2 = 0;
}
else if(light_mode == 0 && l3_flag2 == 1)
{
L[3] = 0;
l3_flag = 0;
}
//下面为时间判断 处于小时参数整点至下一个8点之间 L1亮
if((hour > 8 && hour < set_hour) || (hour < 8 &&hour > set_hour))
{
l1_flag = 1;
}
else
{
l1_flag = 0;
}
//下面为LED逻辑处理
L[1] = (l1_flag == 1)?(1):(0);
L[2] = (temperature < set_t * 10)?(1):(0);
//在暗状态下L4-L8可被指定亮
if(light_mode == 1)
{
L[4] = (set_led == 4)?(1):(0);
L[5] = (set_led == 5)?(1):(0);
L[6] = (set_led == 6)?(1):(0);
L[7] = (set_led == 7)?(1):(0);
L[8] = (set_led == 8)?(1):(0);
}
else
{
L[4] = 0;L[5] = 0;L[6] = 0;L[7] = 0;L[8] = 0;
}
}
void smg_task(void)
{
//数据界面
if(interface_mode == 1)
{
if(data_interface == 1)
{
smg_bit[1] = hour/10;
smg_bit[2] = hour%10;
smg_bit[3] = 11;
smg_bit[4] = min/10;
smg_bit[5] = min%10;
smg_bit[6] = 11;
smg_bit[7] = sec/10;
smg_bit[8] = sec%10;
}
else if(data_interface == 2)
{
smg_bit[1] = 12; //C 0110 0011 0xc6
smg_bit[2] = 10;
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(data_interface == 3)
{
smg_bit[1] = 13; //E 0110 0001 0x86
smg_bit[2] = 10;
smg_bit[3] = adc_value/100;
smg_bit[4] = adc_value/10%10;
smg_bit[5] = adc_value%10;
smg_bit[6] = 10;
smg_bit[7] = 10;
smg_bit[8] = light_mode%10;
}
}
//参数界面
else if(interface_mode == 2)
{
//小时参数界面
if(param_interface == 4)
{
smg_bit[1] = 14; //P 0011 0001 0X8C
smg_bit[2] = param_interface;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = (param_set_hour>9)?(param_set_hour/10%10):(10);
smg_bit[8] = param_set_hour%10;
}
//温度参数界面
else if(param_interface == 5)
{
smg_bit[1] = 14; //P 0011 0001 0X8C
smg_bit[2] = param_interface;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = (param_set_t > 9)?(param_set_t/10%10):(10);
smg_bit[8] = param_set_t%10;
}
//LED参数界面
else if(param_interface == 6)
{
smg_bit[1] = 14; //P 0011 0001 0X8C
smg_bit[2] = param_interface;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = 10;
smg_bit[8] = param_set_led%10;
}
}
}
void key_task(void)
{
uchar key_value = 0;
if(key_feq > 20)
{
key_feq = 1;
key_value = read_key();
}
switch(key_value)
{
case 4: //数据界面和参数界面切换
if(interface_mode == 1)
{
interface_mode = 2;
param_interface = 4;
valid_flag= 0;
}
else if(interface_mode == 2)
{
interface_mode = 1;
data_interface = 1;
valid_flag = 1;
}
break;
case 5: //数据界面下各界面切换 参数界面下各界面切换
if(interface_mode == 1)
{
if(++data_interface > 3)
{
data_interface = 1;
}
}
else if(interface_mode == 2)
{
if(++param_interface > 6)
{
param_interface = 4;
}
}
break;
case 8: //在任意参数界面 参数值减1
if(interface_mode == 2)
{
//此时设置为无效状态
if(valid_flag == 0)
{
if(param_interface == 4)
{
if(param_set_hour > 0)
{
param_set_hour--;
}
else
{
param_set_hour = 0;
}
}
else if(param_interface == 5)
{
if(param_set_t > 0)
{
param_set_t--;
}
else
{
param_set_t = 0;
}
}
else if(param_interface == 6)
{
if(param_set_led > 4)
{
param_set_led--;
}
else
{
param_set_led = 4;
}
}
}
}
break;
case 9: //在任意参数界面 参数值加1
if(interface_mode == 2)
{
if(valid_flag == 0)
{
if(param_interface == 4)
{
if(param_set_hour < 23)
{
param_set_hour++;
}
else
{
param_set_hour = 23;
}
}
else if(param_interface == 5)
{
if(param_set_t < 99)
{
param_set_t++;
}
else
{
param_set_t = 99;
}
}
else if(param_interface == 6)
{
if(param_set_led < 8)
{
param_set_led++;
}
else
{
param_set_led = 8;
}
}
}
}
break;
default:break;
}
}
void Init_System(void)
{
uchar times = 0;
Control_IO(0x80,0xff);
Control_IO(0xa0,0x00);
Control_IO(0xc0,0x00);
while(times++ < 10)
{
adc_value = Read_ADC(0x01);
}
times = 0;
while(times++ < 150)
{
temperature = Read_Temperature() * 10;
}
Timer2Init();
Write_DS1320_Init(hour,min,sec);
}
void main(void)
{
Init_System();
while(1)
{
data_task();
logical_task();
smg_task();
key_task();
}
}
/*==============================================下面为中断处理==============================================*/
void Timer2_Server() interrupt 12
{
static uchar dsp_smg = 1;
static uint t = 0,t1 = 0;
//下面为LED操作
Control_IO(0x80,~(L[1] << 0 | L[2] <<1 | L[3] <<2 |L[4] <<3 | L[5] <<4 | L[6] << 5|L[7] << 6 | L[8] << 7));
//下面为数码管操作
Control_IO(0xc0,0x00);
if((interface_mode == 1 && data_interface == 2 && dsp_smg == 7)
||(interface_mode == 1 && data_interface == 3 && dsp_smg == 3))
{
Control_IO(0xe0,smg_data[smg_bit[dsp_smg]] & 0x7f);
}
else
{
Control_IO(0xe0,smg_data[smg_bit[dsp_smg]]);
}
Control_IO(0xc0,1 << (dsp_smg - 1));
if(++dsp_smg > 8)
{
dsp_smg = 1;
}
if(light_mode == 1)
{
t1 = 0;
if(t++ > 3000) //大于3s
{
l3_flag = 1;
}
}
if(light_mode == 0)
{
t = 0;
if(t1++ > 3000)
{
l3_flag2 = 1;
}
}
//周期刷新变量
time_feq++;
key_feq++;
t_feq++;
adc_feq++;
}