【蓝桥杯单片机第七届国赛真题】
前言

有幸进入国赛,为自己大学最后一个比赛画上完满的句号^@^
下面为蓝桥杯单片机第七届国赛程序部分,功能差不多都实现了,可能存在小bug,望大佬指正,总体来说这届难度并不是很大,有需完整工程的小伙伴可自行下载。

工程链接
链接: https://pan.baidu.com/s/18DnHscfYJXg6tY8JWauVIg?pwd=uhh6 提取码: uhh6 复制这段内容后打开百度网盘手机App,操作更方便哦
--来自百度网盘超级会员v5的分享
一、真题








二、源码
在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/************************************************第七届国赛蓝桥杯单片机*********************************************
@Author:小殷同学
@Date:2023.6.2
********************************************************************************************************************/
#include "public.h"
#include "ds1302.h"
#include "iic.h"
/*==============================================下面为宏和变量定义=================================================*/
uchar smg_bit[9] = {10,10,10,10,10,10,10,10,10};
//数码管段码 0-9 shut-off -
uchar smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff,0xbf};
uchar interface_index = 1; //界面索引
uchar hour = 23,min = 59,sec = 55; //时、分、秒
uchar set_bit = 0,s4_flag = 0,s4_flag2 = 0,s4_flag3 = 0,s4_flag4 = 0,set_bit_volt = 0; //设置时分秒位标志 和S4按下
bit set_bit_flash = 0; //时分秒闪烁标志
uchar number = 0; //编号
uint volt = 0; //adc 电压
uint max_volt = 2000,min_volt = 1000; //电压上限和下限值
uchar event = 0,e_hour = 0,e_min = 0,e_sec = 0; //事件类型和查询时间
uint feq = 0,t = 0; //频率和周期
uchar key_feq = 0; //按键刷新频率
uchar adc_feq = 0; //adc刷新
/*===================================================下面为函数声明+===============================================*/
void smg_task(void); //数码管显示任务
void data_task(void); //数据处理任务
void logical_task(void); //逻辑处理任务
void key_task(void); //按键任务
void Save_Data(void); //AT24C02数据保存
/*=====================================================下面为函数实现==============================================*/
void smg_task(void)
{
//显示时间
if(interface_index == 1 && s4_flag == 0)
{
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(interface_index == 1 && s4_flag == 1)
{
if(set_bit == 1)
{
if(set_bit_flash)
{
smg_bit[1] = hour/10;
smg_bit[2] = hour%10;
}
else
{
smg_bit[1] = 10;
smg_bit[2] = 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(set_bit == 2)
{
if(set_bit_flash)
{
smg_bit[4] = min/10;
smg_bit[5] = min%10;
}
else
{
smg_bit[4] = 10;
smg_bit[5] = 10;
}
smg_bit[1] = hour/10;
smg_bit[2] = hour%10;
smg_bit[3] = 11;
smg_bit[6] = 11;
smg_bit[7] = sec/10;
smg_bit[8] = sec%10;
}
else if(set_bit == 3)
{
if(set_bit_flash)
{
smg_bit[7] = sec/10;
smg_bit[8] = sec%10;
}
else
{
smg_bit[7] = 10;
smg_bit[8] = 10;
}
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;
}
}
//显示电压
else if(interface_index == 2 && s4_flag2 == 0)
{
smg_bit[1] = 11;
smg_bit[2] = number;
smg_bit[3] = 11;
smg_bit[4] = 10;
smg_bit[5] = volt/1000;
smg_bit[6] = volt/100%10;
smg_bit[7] = volt/10%10;
smg_bit[8] = volt%10;
}
else if(interface_index == 2 && s4_flag2 == 1)
{
if(set_bit_volt == 1)
{
//上限
if(set_bit_flash)
{
smg_bit[1] = max_volt/1000;
smg_bit[2] = max_volt/100%10;
smg_bit[3] = max_volt/10%10;
smg_bit[4] = max_volt%10;
}
else
{
smg_bit[1] = 10;
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = 10;
}
smg_bit[5] = min_volt/1000;
smg_bit[6] = min_volt/100%10;
smg_bit[7] = min_volt/10%10;
smg_bit[8] = min_volt%10;
}
else if(set_bit_volt == 2)
{
if(set_bit_flash)
{
smg_bit[5] = min_volt/1000;
smg_bit[6] = min_volt/100%10;
smg_bit[7] = min_volt/10%10;
smg_bit[8] = min_volt%10;
}
else
{
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = 10;
smg_bit[8] = 10;
}
smg_bit[1] = max_volt/1000;
smg_bit[2] = max_volt/100%10;
smg_bit[3] = max_volt/10%10;
smg_bit[4] = max_volt%10;
}
}
//频率和周期
else if(interface_index == 3 && s4_flag3 == 0)
{
smg_bit[1] = 11;
smg_bit[2] = number;
smg_bit[3] = 11;
smg_bit[4] = feq/10000;
smg_bit[5] = feq/1000%10;
smg_bit[6] = feq/100%10;
smg_bit[7] = feq/10%10;
smg_bit[8] = feq%10;
}
else if(interface_index == 3 && s4_flag3 == 1)
{
smg_bit[1] = 11;
smg_bit[2] = number;
smg_bit[3] = 11;
smg_bit[4] = t/10000;
smg_bit[5] = t/1000%10;
smg_bit[6] = t/100%10;
smg_bit[7] = t/10%10;
smg_bit[8] = t%10;
}
//查询显示
else if(interface_index == 4 && s4_flag4 == 0)
{
smg_bit[1] = 10;
smg_bit[2] = 10;
smg_bit[3] = 1;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = event/10;
smg_bit[8] = event%10;
}
else if(interface_index == 4 && s4_flag4 == 1)
{
smg_bit[1] = e_hour/10;
smg_bit[2] = e_hour%10;
smg_bit[3] = 11;
smg_bit[4] = e_min/10;
smg_bit[5] = e_min%10;
smg_bit[6] = 11;
smg_bit[7] = e_sec/10;
smg_bit[8] = e_sec%10;
}
}
void data_task(void)
{
uchar time[3];
if(T2H < 0xd9)
{
if(s4_flag == 0) //s4_flag == 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(adc_feq > 120)
{
adc_feq = 1;
volt = read_adc() * (5.0/255) * 1000; //v-->mv
}
}
}
void logical_task(void)
{
if(volt < min_volt)
{
event = 0;
Write_AT24C02(6,event);
Delay10ms();
Write_AT24C02(7,hour);
Delay10ms();
Write_AT24C02(8,min);
Delay10ms();
Write_AT24C02(9,sec);
Delay10ms();
}
else if(volt > max_volt)
{
event = 1;
Write_AT24C02(6,event);
Delay10ms();
Write_AT24C02(7,hour);
Delay10ms();
Write_AT24C02(8,min);
Delay10ms();
Write_AT24C02(9,sec);
Delay10ms();
}
}
void key_task(void)
{
static bit old_s4_flag = 0,old_s4_flag2 = 0;
uchar key_value = 0;
if(key_feq > 20)
{
key_feq = 1;
key_value = read_key();
}
switch(key_value)
{
case 7: //时钟
interface_index = 1;
if(old_s4_flag)
{
s4_flag = 0; //开始进行时间刷新
//写入设置的时间
Init_DS1302(hour,min,sec);
}
break;
case 6: //电压
interface_index = 2;
number = 1;
if(old_s4_flag2)
{
s4_flag2 = 0;
Write_AT24C02(2,min_volt >> 8); //高位
Delay100ms();
Write_AT24C02(3,min_volt & 0xff); //低位
Delay100ms();
Write_AT24C02(4,max_volt >> 8); //高位
Delay100ms();
Write_AT24C02(5,max_volt & 0xff); //低位
Delay100ms();
}
break;
case 5: //频率
interface_index = 3;
number = 2;
break;
case 4: //功能
if(interface_index == 1) //在时钟界面下
{
s4_flag = 1;
old_s4_flag = s4_flag;
if(set_bit == 0)
{
set_bit = 1;
}
else if(set_bit == 1)
{
set_bit = 2;
}
else if(set_bit == 2)
{
set_bit = 3;
}
else if(set_bit == 3)
{
set_bit = 1;
}
}
//电压设置
if(interface_index == 2) //在电压界面下设置上限和下限
{
s4_flag2 = 1;
old_s4_flag2 = s4_flag2;
if(set_bit_volt == 0)
{
set_bit_volt = 1;
}
else if(set_bit_volt == 1)
{
set_bit_volt = 2;
}
else if(set_bit_volt == 2)
{
set_bit_volt = 1;
}
}
//频率周期切换
if(interface_index == 3)
{
if(s4_flag3 == 0)
{
s4_flag3 = 1;
}
else if(s4_flag3 == 1)
{
s4_flag3 = 0;
}
}
//事件查询切换
if(interface_index == 4)
{
if(s4_flag4 == 0)
{
s4_flag4 = 1;
}
else if(s4_flag4 == 1)
{
s4_flag4 = 0;
}
}
break;
case 11: //加
if(s4_flag)
{
if(set_bit == 1)
{
if(hour < 24)
{
hour++;
}
else
{
hour = 12;
}
}
else if(set_bit == 2)
{
if(min < 60)
{
min++;
}
else
{
min = 60;
}
}
else if(set_bit == 3)
{
if(sec < 60)
{
sec++;
}
else
{
sec = 60;
}
}
}
if(s4_flag2)
{
if(set_bit_volt == 1)
{
if(max_volt < 9999) //四位数码管最大值
{
max_volt += 500;
}
else
{
max_volt = 9999;
}
}
else if(set_bit_volt == 2)
{
if(min_volt < 9999)
{
min_volt += 500;
}
else
{
min_volt = 9999;
}
}
}
break;
case 10: //减
if(s4_flag)
{
if(set_bit == 1)
{
if(hour > 0)
{
hour--;
}
else
{
hour = 0;
}
}
else if(set_bit == 2)
{
if(min > 0)
{
min--;
}
else
{
min = 0;
}
}
else if(set_bit == 3)
{
if(sec > 0)
{
sec--;
}
else
{
sec = 0;
}
}
}
if(s4_flag2)
{
if(set_bit_volt == 1)
{
if(max_volt > 0)
{
max_volt -= 500;
}
else
{
max_volt = 0;
}
}
else if(set_bit_volt == 2)
{
if(min_volt > 0)
{
min_volt -= 500;
}
else
{
min_volt = 0;
}
}
}
break;
case 9: //查询
interface_index = 4;
break;
case 8: //空
break;
default:
break;
}
}
void Save_Data(void)
{
if(Read_AT24C02(1) == 0xff) //不是第一次上电
{
min_volt = (Read_AT24C02(2))<<8 | Read_AT24C02(3) ;
Delay10ms();
max_volt = (Read_AT24C02(4))<<8 | Read_AT24C02(5) ;
Delay10ms();
event = Read_AT24C02(6); //事件类型
Delay10ms();
e_hour = Read_AT24C02(7);
Delay10ms();
e_min = Read_AT24C02(8);
Delay10ms();
e_sec = Read_AT24C02(9);
Delay10ms();
}
else
{
Write_AT24C02(1,0xff); //第一次上电后写入数据 作为后面的判断
Delay10ms();
Write_AT24C02(2,min_volt >> 8);
Delay10ms();
Write_AT24C02(3,min_volt & 0xff);
Delay10ms();
Write_AT24C02(4,max_volt >> 8);
Delay10ms();
Write_AT24C02(5,max_volt & 0xff);
Delay10ms();
Write_AT24C02(6,event);
Delay10ms();
Write_AT24C02(7,e_hour);
Delay10ms();
Write_AT24C02(8,e_hour);
Delay10ms();
Write_AT24C02(9,e_sec);
Delay10ms();
}
}
void Init_System(void)
{
Control_IO(0x80,0xff);
Control_IO(0xa0,0x00);
Control_IO(0xc0,0x00);
Init_Timer0();
Timer2Init();
Init_DS1302(hour,min,sec);
Save_Data();
}
void main(void)
{
Init_System();
while(1)
{
smg_task();
data_task();
logical_task();
key_task();
}
}
/*==========================================================下面为中断处理=========================================*/
void Server_Timer2() interrupt 12
{
static uchar dsp_smg = 1;
static uint count = 0;
static uint feq_count = 0;
if(++feq_count == 500)
{
feq_count = 0;
TR0 = 0;
feq = ((uint)(TH0 << 8) | TL0) * 2;
t = (1.0/feq) * 1000000;
TH0 = TL0 = 0;
TR0 = 1;
}
Control_IO(0xc0,0x00);
Control_IO(0xe0,smg_data[smg_bit[dsp_smg]]);
Control_IO(0xc0,1 << (dsp_smg - 1));
if(++dsp_smg > 8)
{
dsp_smg = 1;
}
if(s4_flag || s4_flag2)
{
if(count++ == 1000)
{
count = 0;
set_bit_flash = ~set_bit_flash;
}
}
//下面为数据刷新频率相关变量
key_feq++;
adc_feq++;
}
该文分享了第七届蓝桥杯单片机国赛的程序代码,包括数码管显示、数据处理、逻辑处理、按键任务和中断任务等功能模块,涉及DS1302时钟芯片、IIC通信和ADC电压测量。程序实现了时间显示、电压上下限设置、频率周期查询等操作,并提供了工程链接供下载。
884

被折叠的 条评论
为什么被折叠?



