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

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


前言

在这里插入图片描述

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小殷学长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值