【蓝桥杯单片机第十一届国赛真题】

【蓝桥杯单片机第十一届国赛真题】


前言

在这里插入图片描述

有幸进入国赛,为自己大学最后一个比赛画上完满的句号^@^

下面为蓝桥杯单片机第十一届国赛程序部分,功能差不多都实现了,可能存在小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++;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小殷学长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值