【蓝桥杯单片机第九届国赛真题】
前言
有幸进入国赛,为自己大学最后一个比赛画上完满的句号^@^
下面为蓝桥杯单片机第九届国赛程序部分,功能差不多都实现了,可能存在小bug,望大佬指正,总体来说这届难度并不是很大,有需完整工程的小伙伴可自行下载。
工程链接
链接: https://pan.baidu.com/s/1dYQ7dR_AoXLRDZz6ZcvJYg?pwd=4i73 提取码: 4i73 复制这段内容后打开百度网盘手机App,操作更方便哦
--来自百度网盘超级会员v5的分享
一、真题
二、源码
在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/*==============================================第九届国赛=====================================
@Author:小殷同学
@Date:2023.6.3
===============================================================================================*/
#include "public.h"
#include "iic.h"
#include "onewire.h"
/*=================================================下面为变量相关定义============================*/
uchar L[9];
//数码管段码(0~9、shut-off、"-")
code uchar smg_data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,
0xbf,0xc6,0xc1,0x8e,0x89,0x8c};
//初始化,使所有数码管熄灭(必须是9个元素)
xdata uchar smg_bit[11] = {10,10,10,10,10,10,10,10,10};
uchar interface = 1,data_index = 1,display = 0,display_index = 1,param_index = 0; //界面
uint adc_volt = 0,set_volt = 10,last_adc_volt = 0; //adc电压
uint temperature = 0,last_temperature = 0; //温度
uint feq = 0,last_feq = 0; //频率
uchar key_feq = 0; //按键刷新频率
uchar adc_feq = 0; //adc 刷新频率
uchar t_feq = 0; //温度刷新频率
bit l8_flag = 0,l8_flash = 0;
/*======================================下面为函数相关声明=========================================*/
void Init_System(void); //系统初始化
void smg_task(void); //数码管显示任务
void data_task(void); //数据处理任务
void logical_task(void); //逻辑处理任务
void key_task(void); //按键任务
void Save_Data_AT24C02(void); //数据保存读取AT24C02
/*===========================================下面为函数相关实现======================================*/
void smg_task(void)
{
//温度
if(data_index == 1)
{
if(interface == 1)
{
smg_bit[1] = 12; //C 0110 0011 0XC6
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = temperature/1000;
smg_bit[6] = temperature/100%10;
smg_bit[7] = temperature/10%10;
smg_bit[8] = temperature%10;
}
//电压
else if(interface == 2)
{
smg_bit[1] = 13; //U 1000 0011 0xc1
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = adc_volt/100;
smg_bit[8] = adc_volt/10%10;
}
//频率
else if(interface == 3)
{
smg_bit[1] = 14; //F 0111 0001 0X8E
smg_bit[2] = 10;
smg_bit[3] = 10;
if(feq > 9999)
{
smg_bit[4] = feq/10000;
}
if(feq > 999)
{
smg_bit[5] = feq/1000%10;
}
if(feq > 99)
{
smg_bit[6] = feq/100%10;
}
if(feq > 9)
{
smg_bit[7] = feq/10%10;
}
smg_bit[8] = feq%10;
}
}
//回显界面
if(display == 1)
{
smg_bit[1] = 15; //H 1001 0001 0x89
if(display_index == 1)
{
smg_bit[2] = 12; //C 0110 0011 0XC6
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = last_temperature/1000;
smg_bit[6] = last_temperature/100%10;
smg_bit[7] = last_temperature/10%10;
smg_bit[8] = last_temperature%10;
}
else if(display_index == 2)
{
smg_bit[2] = 13; //U 1000 0011 0xc1
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = last_adc_volt/100;
smg_bit[8] = last_adc_volt/10%10;
}
else if(display_index == 3)
{
smg_bit[2] = 14; //F 0111 0001 0X8E
smg_bit[3] = 10;
if(feq > 9999)
{
smg_bit[4] = last_feq/10000;
}
if(feq > 999)
{
smg_bit[5] = last_feq/1000%10;
}
if(feq > 99)
{
smg_bit[6] = last_feq/100%10;
}
if(feq > 9)
{
smg_bit[7] = last_feq/10%10;
}
smg_bit[8] = last_feq%10;
}
}
// 参数设置界面
if(param_index == 1)
{
smg_bit[1] = 15; //P 0011 0001 0x8c
smg_bit[2] = 10;
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = set_volt/10;
smg_bit[8] = set_volt%10;
}
}
void data_task(void)
{
if(T2H < 0xd9)
{
if(adc_feq > 120)
{
adc_feq = 1;
adc_volt = Read_ADC(0x03);
adc_volt = adc_volt * (5.0/255)*100;
}
if(t_feq > 150)
{
t_feq = 1;
temperature = Read_Temperature() * 100;
}
}
}
void logical_task(void)
{
//下面为LED逻辑控制
L[1] = (interface == 1 && data_index == 1)?(1):(0); //温度测量界面
L[2] = (interface == 3 && data_index == 1)?(1):(0); //频率测量界面
L[3] = (interface == 2 && data_index == 1)?(1):(0); //电压测量界面
//RB2输出电压大于set_vlot时 L8 0.2闪烁
if(adc_volt > set_volt*10)
{
l8_flag = 1;
}
else
{
l8_flag = 0;
L[8] = 0; //避免不满足条件时L[8] 正处于闪烁状态
}
L[8] = (l8_flash == 1)?(1):(0);
}
void key_task(void)
{
uchar key_value = 0;
static uchar i = 0;
static uchar s7_flag = 0;
if(key_feq > 20)
{
key_feq = 1;
key_value = Read_key();
}
switch(key_value)
{
//温度、电压、频率界面显示切换
case 4:
if(data_index == 1)
{
if(++interface > 3)
{
interface = 1;
}
}
if(display == 1)
{
if(++display_index > 3)
{
display_index = 1;
}
}
break;
//存储温度 电压 频率到EEPROM
case 5:
Write_AT24C02(0x01,temperature >> 8); //温度高位
Delay10ms();
Write_AT24C02(0x02,temperature & 0xff); //温度低位
Delay10ms();
Write_AT24C02(0x03,adc_volt >> 8); //电压高位
Delay10ms();
Write_AT24C02(0x04,adc_volt & 0xff); //电压低位
Delay10ms();
Write_AT24C02(0x05,feq >> 8); //频率高位
Delay10ms();
Write_AT24C02(0x06,feq & 0xff); //频率低位
Delay10ms();
break;
case 6:
//数据回显
if(param_index == 0)
{
data_index = 0;
display = 1;
param_index = 0;
//读取EEPROM数据
last_temperature = (Read_AT24C02(0x01) << 8)|Read_AT24C02(0x02);
Delay10ms();
last_adc_volt = (Read_AT24C02(0x03)<< 8)|Read_AT24C02(0x04);
Delay10ms();
last_feq = (Read_AT24C02(0x05)<< 8)|Read_AT24C02(0x06);
Delay10ms();
}
else if(param_index == 1)
{
//0.1 - 5 1-50
if(set_volt < 50)
{
set_volt += 1;
}
else
{
set_volt = 1;
}
Write_AT24C02(0x07,set_volt); //存储电压参数
}
break;
//参数设置
case 7:
if(s7_flag == 0)
{
s7_flag = 1;
param_index = 1;
display = 0;
data_index = 0;
}
else if(s7_flag == 1)
{
param_index = 0;
data_index = 1;
display = 0;
s7_flag = 0;
}
break;
case 106:
//在参数设置界面下长按s6 实现快速增加 题目没严格要求这里设置为长按一次加5次
if(param_index == 1)
{
for(i = 0;i<5;i++)
{
set_volt += 1;
}
Write_AT24C02(0x07,set_volt); //存储电压参数
}
break;
default:break;
}
}
void Save_Data_AT24C02(void)
{
static uchar i = 0;
if(Read_AT24C02(0x88) == 0xff) //不是第一次上电
{
last_temperature = (Read_AT24C02(0x01) << 8)|Read_AT24C02(0x02);
Delay10ms();
last_adc_volt = (Read_AT24C02(0x03) <<8)|Read_AT24C02(0x04);
Delay10ms();
last_feq = (Read_AT24C02(0x05)<< 8)|Read_AT24C02(0x06);
Delay10ms();
set_volt = Read_AT24C02(0x07);
}
else //第一次上电
{
Write_AT24C02(0x88,0xff);
Delay10ms();
Write_AT24C02(0x07,set_volt);
Delay10ms();
for(i =0;i<6;i++)
{
Write_AT24C02(i,0);
Delay10ms();
}
}
}
void Init_System(void)
{
Control_IO(0x80,0xff);
Control_IO(0xa0,0x00);
Control_IO(0xc0,0x00);
while(t_feq++ < 150)
{
temperature = Read_Temperature() * 100;
}
Timer0Init();
Timer2Init();
Save_Data_AT24C02();
}
void main(void)
{
Init_System();
while(1)
{
smg_task();
data_task();
logical_task();
key_task();
}
}
/*========================================下面为中断处理========================================*/
void Timer2_Server() interrupt 12
{
static uchar dsp_smg = 1;
static uint f_count = 0;
static uint l8_t =0;
if(++f_count == 500)
{
f_count = 0;
TR0 = 0;
feq = ((uint)(TH0 << 8) | TL0);
TH0 = TL0 = 0;
TR0 = 1;
}
//下面为LED控制
Control_IO(0x80,~(L[1]<< 0|L[2] << 1|L[3] << 2|L[8] <<7));
Control_IO(0xc0,0x00);
if((data_index == 1 && interface == 2 && dsp_smg == 7) ||(data_index == 1 && interface == 1 && dsp_smg == 6)
|| (display == 1 && display_index == 2 && dsp_smg == 7) ||(display == 1 && display_index == 1 && dsp_smg == 6)
|| (param_index == 1 && dsp_smg == 7) )
{
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(l8_flag == 1)
{
if(l8_t++> 200) //0.2s
{
l8_t = 0;
l8_flash = ~l8_flash;
}
}
else
{
l8_flash = 0;
}
key_feq++;
adc_feq++;
t_feq++;
}