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

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


前言

在这里插入图片描述

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

下面为蓝桥杯单片机第六届国赛程序部分,功能差不多都实现了,可能存在小bug,望大佬指正,总体来说这届难度并不是很大,有需完整工程的小伙伴可自行下载。

在这里插入图片描述

链接: https://pan.baidu.com/s/1Hig3ys3Upz3BfHpNFcnj5Q?pwd=4dbj 提取码: 4dbj 复制这段内容后打开百度网盘手机App,操作更方便哦 
--来自百度网盘超级会员v5的分享

一、真题

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、源码

在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/*====================================第六届蓝桥杯单片机组国赛==================================
@Author:小殷童鞋
@Date:2023.6.1
*************************************************************************************************/
#include "public.h"
#include "iic.h"
/*=========================================下面为宏和变量定义====================================*/

//LED控制
uchar L[5];
uchar relay = 0;
uchar buzzer = 0;
//设置为10对应着0xff 关闭数码管初始化
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 = 1;                                  //界面变量
uchar adc = 0;                                        //rb2 adc
uint volt = 0;                                        //rb2电压
uint distance = 0;                                    //超声波距离
uchar number = 0;                                     //货物类别编号
uchar work_mode = 0;                                  //1 为空载 2为非空载 3 为过载
bit l3_flag = 0;                                      //L3闪烁标志位
uchar set_t1 = 2,set_t2 = 4;                          //第一类和第二类默认传送时间
bit start = 0;                                        //开始传送
bit emergy_stop = 0;                                  //停止传送
bit l4_flag = 0;                                      //L4 闪烁标志
uchar set_bit = 0;                                    //调整时间位
bit s6_flag = 0;                                      //S6按下标志
bit set_bit_flash = 0;
//下面为数据刷新频率
uchar adc_feq = 0;                                     //rb2采集频率
uchar key_feq = 0;                                     //按键刷新频率
uchar dis_feq = 0;                                     //超声波刷新频率
/*==========================================下面为函数相关声明=====================================*/
void Init_System(void);                                                 //系统初始化
void smg_task(void);                                                    //数码管显示任务
void data_task(void);                                                   //数据处理任务
void key_task(void);                                                    //按键处理任务
void logical_task(void);                                                //逻辑处理任务
/*===========================================下面为函数实现=========================================*/
void smg_task(void)
{
	if(interface == 1)
	{
		smg_bit[1] = interface;
		smg_bit[2] = 10;
		smg_bit[3] = 10;
		smg_bit[4] = distance/10%10;
		smg_bit[5] = distance%10;
		smg_bit[6] = 10;
		smg_bit[7] = 10;
		smg_bit[8] = number;
	}
	else if(interface == 2)
	{
		//第一类时间
		smg_bit[1] = interface;
		smg_bit[2] = 10;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = 10;
		if(number == 1)
		{
			smg_bit[7] = set_t1/10;
			smg_bit[8] = set_t1%10;
		}
		else
		{
			smg_bit[7] = set_t2/10;
		}   smg_bit[8] = set_t2%10;	
	}
	else if(interface == 3)
	{
		smg_bit[1] = interface;
		smg_bit[2] = 10;
		smg_bit[3] = 10;
		if(set_bit == 1)
		{
			if(set_bit_flash)
			{
				smg_bit[4] = set_t1/10;
				smg_bit[5] = set_t1%10;
			}
			else
			{
				smg_bit[4] = 10;
				smg_bit[5] = 10;
			}
			smg_bit[7] = set_t2/10;
			smg_bit[8] = set_t2%10;
		}
		else if(set_bit == 2)
		{
			if(set_bit_flash)
			{
				smg_bit[7] = set_t2/10;
				smg_bit[8] = set_t2%10;
			}
			else
			{
				smg_bit[7] = 10;
				smg_bit[8] = 10;
			}
		}
		smg_bit[6] = 10;

	}
}

void data_task(void)
{
	if(T2H < 0xd9)
	{
		if(dis_feq > 120)
		{
			dis_feq = 1;
			distance = get_distance();
		}
		
		
		if(adc_feq > 150)
		{
			adc_feq = 1;
			adc = read_rb2();
			volt = adc * (5.0/255) * 100;     //扩大100倍方便处理
			//通过电压判断空载 非空载  过载
			if(volt > 0 && volt < 100)
			{
				//空载 
				work_mode = 1;
			}
			else if(volt >= 100 && volt < 400)
			{
				//非空载
				work_mode = 2;
			}
			else if(volt >= 400)
			{
				//过载 
				work_mode = 3;
			}
		}
	
	}
}

void logical_task(void)
{
	//通过距离判断货物类:大于30为2类 小于等于为1类
	number = (distance > 30)?(2):(1);
	//空载
	L[1] = (work_mode == 1)?(1):(0);
	//非空载
	L[2] = (work_mode == 2)?(1):(0);
	//过载 0.5s 闪烁
	if(work_mode == 3)
	{
		L[3] = (l3_flag == 1)?(1):(0);
		buzzer = 1;
	}
	else
	{
		L[3] = 0;
		buzzer = 0; 
	}
	
	//继电器控制
	relay = (start == 1)?(1):(0);
	//下面为紧急按键控制逻辑
	L[4] = (l4_flag == 1)?(1):(0);
}


void key_task(void)
{
	uchar key_value = 0;
	if(key_feq > 20)
	{
		key_feq = 1;
		key_value = read_key();
	}
	
	if(key_value == 4)
	{
		if(work_mode == 1 || work_mode == 3 || start == 1)
		{
			//无效
		}
		else
		{
			start = 1;
			interface = 2;
		}
	}
	else if(key_value == 5)
	{
		//在传送过程中才有效
		if(start == 1)
		{
			//紧急停止 继电器断开 L4 0.5s闪烁  计时停止 再次按下传送恢复L4熄灭 恢复计时
			if(emergy_stop == 0)
			{
				emergy_stop = 1;
				l4_flag = 1;
			}
			else if(emergy_stop == 1)
			{
				emergy_stop = 0;
				l4_flag = 0;
			}
		}	
	}
	//下面按键仅在空载有效
	else if(key_value == 6)
	{
		//时间设置按键 
		//第一次按下设置第一类时间 第二次设置第二类时间 第三次保存调整后的数据到EEPROM并关闭数码管显示
		if(work_mode == 1)
		{
			s6_flag = 1;
			interface = 3;
			if(set_bit == 0)
			{
				set_bit = 1;  //第一类
			}
			else if(set_bit == 1)
			{
				set_bit = 2;  //第二类
			}
			else if(set_bit == 2)
			{
				set_bit = 3;  //存储到eeprom
				s6_flag = 0;
				write_eeprom(0x01,set_t1);
				Delay10ms();
				write_eeprom(0x03,set_t2);
				Delay10ms();
			}
			else if(set_bit == 3)
			{
				set_bit = 1;
			}
		}
	}
	else if(key_value == 7)
	{
		//时间调整
		if(work_mode == 1 && interface == 3)
		{
			if(set_bit == 1)
			{
				//调整第一类时间
				if(set_t1 >= 10)
				{
					set_t1 = 1;
				}
				else
				{
					set_t1++;
				}
			}
			else if(set_bit == 2)
			{
				//调整第二类时间
				if(set_t2 >= 10)
				{
					set_t2 = 1;
				}
				else
				{
					set_t2++;
				}
			}
		}
	}
}

void Init_System(void)
{
	
	Control_IO(0x80,0xff);   //关闭LED
	Control_IO(0xa0,0x00);   //关闭蜂鸣器和继电器
	Control_IO(0xc0,0x00);   //关闭数码管
	Timer2Init();            //定时器2初始化
	
	if(read_eeprom(0x00) == 0xff)  //不是第一次上电
	{
		set_t1 = read_eeprom(0x01);
		Delay10ms();
		set_t2 = read_eeprom(0x03);
		Delay10ms();
	}
	else
	{
		write_eeprom(0x00,0xff);
		Delay10ms();
		write_eeprom(0x01,set_t1);
		Delay10ms();
		write_eeprom(0x03,set_t2);
		Delay10ms();
	}

}

void main(void)
{
	Init_System();
	while(1)
	{
		logical_task();      //逻辑处理任务
		smg_task();          //数码管显示任务
		data_task();         //数据处理任务
		key_task();          //按键处理任务
	}
}

/*===============================================下面为中断处理========================================*/
void Timer2_Server() interrupt 12
{
	static uchar dsp_smg = 1;
	static uint l3_t = 0,time = 0,l4_t = 0,flash_t = 0;
	//LED控制
	Control_IO(0x80,~(L[1] << 0 | L[2] << 1| L[3] <<2 | L[4] <<3));
	//继电器和蜂鸣器控制
	Control_IO(0xa0,relay << 4 | buzzer << 6);
	//数码管控制  空载下所有数码管熄灭
	if(work_mode == 1 && s6_flag == 0)
	{
		Control_IO(0xc0,0x00);
	}
	else
	{
		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;
		}
	}
	//L3闪烁控制
	if(work_mode == 3)
	{
		if(l3_t++ == 500)
		{
			l3_t = 0;
			l3_flag = ~l3_flag;
		}
	}
	
	//L4 闪烁控制
	if(emergy_stop == 1)
	{
		if(l4_t++ == 500) 
		{
			l4_t = 0;
			l4_flag = ~l4_flag;
		}
	}
	
	//数码管闪烁时间设置
	if(set_bit == 1 ||set_bit == 2)
	{
		if(flash_t ++ == 500)
		{
			flash_t = 0;
			set_bit_flash = ~set_bit_flash;
		}
	}
	if(start == 1 && emergy_stop == 0)
	{
		time++;
		if(time == 1000) //1s
		{
			time = 0;
			if(number == 1)
			{
				if(set_t1 > 0)
				{
					set_t1--;
				}
				else
				{
					set_t1 = 0;  //时间到
					start = 0;
				}
			}
			else if(number == 2)
			{
				if(set_t2 > 0)
				{
					set_t2--;
				}
				else
				{
					set_t2 = 0;
					start = 0;
				}
			}
		}
	}
	//下面为数据刷新频率变量
	adc_feq++;
	key_feq++;
	dis_feq++;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小殷学长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值