有幸进入国赛,为自己大学最后一个比赛画上完满的句号^@^
下面为蓝桥杯单片机第十届国赛程序部分,功能差不多都实现了,可能存在小bug,望大佬指正,有需完整工程的小伙伴可自行下载。
在该工程中,长按的功能会先导致短按界面的切换,还未解决,题目无特殊说明,不能导致界面的切换应该也算ok。
工程链接
链接: https://pan.baidu.com/s/1gqBQ2bb7g20u45Nmqf7A6w?pwd=x8ty 提取码: x8ty 复制这段内容后打开百度网盘手机App,操作更方便哦
--来自百度网盘超级会员v5的分享
在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/*============================第十届国赛================================
@Author:小殷同学
@Date:2023.6.6
=======================================================================*/
#include "public.h"
#include "iic.h"
#include "onewire.h"
/*==========================下面为宏和变量定义=========================*/
//数码管段码(0~9、shut-off、"-")
code uchar smg_data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6,0xc7,
0xc0,0x8c};
//初始化,使所有数码管熄灭(必须是9个元素)
xdata uchar smg_bit[11] = {10,10,10,10,10,10,10,10,10};
uchar L[5]; //led控制
uchar str[12]; //串口接收缓存
bit usart_flag = 0; //接收完成标志
uchar count_index = 0; //数组下标索引
uchar data_interface = 1,mode = 1,param_interface = 1; //界面相关
uchar number = 0; //参数编号
bit param_set_flag = 0; //参数设置标志
xdata uint temperature = 0,dis = 0,count = 0; //温度 距离 计数
xdata uint set_t = 30,set_dis = 35,old_set_t = 30,old_set_dis = 35; //温度阈值和距离
//下面为数据刷新周期变量
uchar t_feq = 0;
uchar dis_feq = 0;
uchar key_feq = 0;
uchar led_feq = 0;
bit adc_flag = 1; //adc启动标志位
/*===========================下面为函数相关声明=========================*/
void Init_System(void); //系统初始化
void smg_task(void); //数码管显示任务
void data_task(void); //数据刷新任务
void logical_task(void); //逻辑处理任务
void key_task(void); //按键任务
/*============================下面为函数相关实现========================*/
void smg_task(void)
{
if(mode == 1)
{
if(data_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(data_interface == 2)
{
smg_bit[1] = 13;//L 1110 0011 0xc7
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = 10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = dis/10;
smg_bit[8] = dis%10;
}
else if(data_interface == 3)
{
smg_bit[1] = 14; //O 0000 0011 0xc0
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = (count > 9999)?(count/10000):(10);
smg_bit[5] = (count > 999)?(count/1000%10):(10);
smg_bit[6] = (count > 99)?(count/100%10):(10);
smg_bit[7] = (count > 9)?(count/10%10):(10);
smg_bit[8] = count%10;
}
}
else if(mode == 2)
{
if(param_interface == 1)
{
smg_bit[1] = 15;//P 0011 0001 0x8c
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = number%10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = set_t/10;
smg_bit[8] = set_t%10;
}
else if(param_interface == 2)
{
smg_bit[1] = 15;//P 0011 0001 0x8c
smg_bit[2] = 10;
smg_bit[3] = 10;
smg_bit[4] = number%10;
smg_bit[5] = 10;
smg_bit[6] = 10;
smg_bit[7] = set_dis/10;
smg_bit[8] = set_dis%10;
}
}
}
void data_task(void)
{
if(T2H < 0xd9)
{
if(t_feq > 150)
{
t_feq = 1;
temperature = Read_Temp() * 100;
}
if(dis_feq > 120)
{
dis_feq = 1;
dis = Get_Dis();
}
}
if(usart_flag)
{
if(str[0] == 'S' && str[1] == 'T' && count_index == 2)
{
printf("$%d,%.2f\r\n",dis,temperature/100.0);
}
else if(str[0] == 'P' && str[1] == 'A' && str[2] == 'R' && str[3] == 'A' && count_index == 4)
{
printf("\#%d,%d\r\n",set_dis,set_t);
}
else
{
printf("ERROR\r\n");
}
usart_flag = 0;
count_index = 0;
}
}
void logical_task(void)
{
//参数编号
number = (param_interface == 1)?(4):(5);
if(led_feq > 120)
{
led_feq = 1;
//LED控制
L[1] = (temperature > set_t * 100)?(1):(0);
L[2] = (dis < set_dis)?(1):(0);
L[3] = (adc_flag == 1)?(1):(0);
}
//DAC输出
if(adc_flag == 1)
{
if(dis <= set_dis)
{
//5v -255
Write_DAC(2*51);
}
else
{
Write_DAC(4*51);
}
}
else
{
Write_DAC(0.4*51);
}
}
void key_task(void)
{
uchar key_value = 0;
if(key_feq > 20)
{
key_feq = 1;
key_value = read_key();
}
switch(key_value)
{
//参数和数据界面切换
case 13:
if(mode == 1)
{
mode = 2;
//数据界面进入参数界面默认为温度参数
param_interface = 1;
}
else if(mode == 2)
{
mode = 1;
//参数界面进入数据界面默认为温度数据
data_interface = 1;
if(old_set_dis != set_dis || old_set_t != set_t) //当设置参数有变化时才发送改变
{
old_set_dis = set_dis;
old_set_t = set_t;
count++;
Write_AT24C02(1,count >> 8);
Delay5ms();
Write_AT24C02(2,count & 0xff);
Delay5ms();
}
}
break;
//数据界面切换
case 12:
if(mode == 1)
{
if(++data_interface > 3)
{
data_interface = 1;
}
}
else if(mode == 2)
{
if(++param_interface > 2)
{
param_interface = 1;
}
}
break;
//在参数界面下减
case 16:
if(mode == 2)
{
//温度参数
if(param_interface == 1)
{
if(set_t > 0)
{
set_t -= 2;
}
}
else if(param_interface == 2)
{
if(set_dis > 0)
{
set_dis -= 5;
}
}
}
break;
//参数界面下 加
case 17:
if(mode == 2)
{
if(param_interface == 1)
{
if(set_t < 99)
{
set_t += 2;
}
else
{
set_t = 99;
}
}
else if(param_interface == 2)
{
if(set_dis < 99)
{
set_dis += 5;
}
else
{
set_dis = 99;
}
}
}
break;
//长按s12
case 112:
count = 0;
break;
//长按s13 切换adc输出功能
case 113:
adc_flag = ~adc_flag;
break;
}
}
void Init_System(void)
{
Control_IO(0x80,0xff);
Control_IO(0xa0,0x00);
Control_IO(0xc0,0x00);
while(t_feq++ < 150)
{
temperature = Read_Temp()*100;
}
UartInit();
Timer2Init();
if(Read_AT24C02(0) == 0xff) //不是第一次上电
{
count = (Read_AT24C02(1)<<8|Read_AT24C02(2)); //上电读取EEPROM
}
else
{
Write_AT24C02(0,0xff);
Delay5ms();
Write_AT24C02(1,count >> 8);
Delay5ms();
Write_AT24C02(2,count & 0xff);
Delay5ms();
}
}
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;
Control_IO(0x80,~(L[1] <<0 | L[2] << 1 | L[3] <<2));
Control_IO(0xc0,0x00);
if(data_interface == 1 && dsp_smg == 6 && mode == 1)
{
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;
}
t_feq++;
dis_feq++;
key_feq++;
led_feq++;
}
void Usart_Server() interrupt 4
{
uchar dat = 0;
if(RI)
{
RI = 0;
dat = SBUF;
if(dat == 0 || dat == '\r' || dat == '\n')
{
usart_flag = 1;
str[count_index] = '0';
}
else
{
str[count_index++] = dat;
}
}
}