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

news2024/12/24 3:21:23

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

文章目录

  • 【蓝桥杯单片机第八届国赛真题】
  • 前言
  • 一、真题
  • 二、源码


前言

在这里插入图片描述

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

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

在这里插入图片描述

工程链接

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

注意点

这届难度并不是很大,值得注意的是在进行EEPROM存储10次测距时,可以用更好的方式,下面为我使用的存储形式。


void Save_AT24C02_Data(void)
{
	static uchar i = 0;
	if(Read_AT24C02(0x00) == 0xee)  //上电不是第一次
	{
		set_dis = Read_AT24C02(0x88);
		Delay10ms();
		//读取10次存储的数据
		for(i = 0;i<10;i++)
		{
			dis_info[i] = (Read_AT24C02(i) << 8) |Read_AT24C02(i+10);
			Delay10ms();

		}
	}
	else
	{
		Write_AT24C02(0x00,0xee);
		for(i = 0;i <10;i++)             //第一次上电时都是0
		{
			Write_AT24C02(i,0);
			Delay10ms();
			Write_AT24C02(i+10,0);
			Delay10ms();
		}
	}
}

Save_AT24C02_Data这个函数的功能是进行初始化时,进行存储EEPROM中数据的读取,Read_AT24C02(0x00) == 0xee这句判断是为了非第一次上电进行之前内容的读取,else 里面的内容相当于进行第一次上电的初始化,因为数组是存储测距的数据所以在第一次上电时全部设置了0。
Write_AT24C02(i,0);
Delay10ms();
Write_AT24C02(i+10,0);
Delay10ms();
这里进行加10是为了进行存储地址区分,因为EEPROM这里只能读取一个字节,如果所测的距离在一个字节范围内当然可以直接进行该地址内容的读取和写入,防止所测距离大于一个字节的范围这里每次所测 的数据都放在了两个地址中,见data_task函数中进行EEPROM数据的写入,其中number为数组下标索引。
Write_AT24C02(number,dis_info[number] >> 8); //写高位
Delay10ms();
Write_AT24C02(number+10,dis_info[number] & 0xff); //写低位
Delay10ms();

一、真题

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

在这里插入图片描述

二、源码

在main.c中主要分为5部分功能,smg_task数码管显示任务、data_task数据处理任务、logical_task逻辑处理任务、key_task按键任务以及中断任务。
/*=======================================第八届国赛==================================
@Author:小殷同学
@Date:2023.6.2
===================================================================================*/
#include <STC15F2K60S2.H>
#include "public.h"
#include "iic.h"
/*====================================下面为变量相关定义============================*/
//数码管段码(0~9、shut-off、"-")
code uchar smg_data[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0x8e};
//初始化,使所有数码管熄灭(必须是9个元素)
xdata uchar smg_bit[11] = {10,10,10,10,10,10,10,10,10};
uchar L[9];
xdata uchar  dis_info[10] = {0},info_index = 0;        //数组存储10组数据 下标索引
uchar number = 0;                                      //索引号
bit start_dis = 0;                                     //开始测距
bit dis_mode = 0;                                      //模式
bit finish_flag = 0,l1_flash = 0;                      //完成标志 和l1闪烁
uchar adc = 0;                                         //dac
uchar interface = 1;                          		   //界面
bit s5_flag = 0;                              		   //s5标志
uint dis = 0,sum_dis = 0,old_dis = 0,temp_dis =0,set_dis = 0;          //超声波距离 上次和本次和  上一次值
uchar dis_feq = 0;                             //超声波测距频率
uchar key_feq = 0;                             //按键扫描频率
/*===================================下面为函数相关声明================================*/
void smg_task(void);                            //数码管显示任务
void data_task(void);                           //数据处理任务
void logical_task(void);                        //逻辑处理任务
void key_task(void);                            //按键任务
void Save_AT24C02_Data(void);                   //存储读取数据AT24C02
/*==================================下面为函数相关实现==================================*/
void smg_task(void)
{
	//测距界面
	if(interface == 1)
	{
		smg_bit[1] = dis_mode;
		smg_bit[2] = 10;
		smg_bit[3] = 10;
		if(dis_mode == 0)
		{
			smg_bit[4] = old_dis/10;
			smg_bit[5] = old_dis%10;
		}
		else 
		{
			smg_bit[4] = sum_dis/10;
			smg_bit[5] = sum_dis%10;
		}
		smg_bit[6] = dis/100;
		smg_bit[7] = dis/10%10;
		smg_bit[8] = dis%10;
	}
	//回显界面
	else if(interface == 2)
	{
		smg_bit[1] = (number+1)/10; //加1 为了让显示索引从1-10 数组下标为0-9
		smg_bit[2] = (number+1)%10;
		smg_bit[3] = 10;
		smg_bit[4] = 10;
		smg_bit[5] = 10;
		smg_bit[6] = dis_info[number]/100;
		smg_bit[7] = dis_info[number]/10%10;
		smg_bit[8] = dis_info[number]%10;
	}
	//参数界面
	else if(interface == 3)
	{
		smg_bit[1] = 12;   //F 0111 0001 0x8e
		smg_bit[2] = 10;     
		smg_bit[3] = 10;
		smg_bit[4] = 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(start_dis)
		{
			if(dis_feq >120)
			{
				dis_feq = 1;
				temp_dis = dis;              //保存一次 在测距之前先保存之前的数据
				dis = get_distance();
				number++;                    //编号加加
				dis_info[number] = dis;      //数据存储
				start_dis = 0;
				finish_flag = 1;              //测距完成
				Write_AT24C02(number,dis_info[number] >> 8);  //写高位
				Delay10ms();
				Write_AT24C02(number+10,dis_info[number] & 0xff); //写低位
				Delay10ms();
			}
		}
	}
}

void logical_task(void)
{
	uchar i = 0;
	if(dis_mode == 0)
	{
		if(dis != temp_dis)         //判断距离是否发送改变
		{ 
			old_dis = temp_dis;
		}
	}
	else if(dis_mode == 1)
	{
		sum_dis = (dis + old_dis);
	}
	if(number > 10){
		number = 0;          //只测量10次
	}
	
	//DAC处理
	if(dis <= set_dis)
	{
		adc = 0;
		write_dac(0);  //0v
	}
	else
	{
		adc = (dis - set_dis)*0.02; 
		write_dac(adc * 51);
	}
	if(adc > 5)
	{
		write_dac(255);  //5v
	}
	
	//led控制
	if(finish_flag)
	{
		L[1] = (l1_flash == 1)?(1):(0);
	}
	
	L[7] = (interface == 3)?(1):(0);
	L[8] = (interface == 2)?(1):(0);

}


void key_task(void)
{
	uchar key_value = 0;
	static bit s5_flag = 0,s6_flag = 0;
	if(key_feq > 20)
	{
		key_feq = 1;
		key_value = Read_key();
	}
	switch(key_value)
	{
		case 4:
			start_dis = 1;
			interface = 1;
			break;
		case 5:
			if(s5_flag == 0)
			{
				s5_flag = 1;
				interface = 2;
			}
			else if(s5_flag == 1)
			{
				s5_flag = 0;
				interface = 1;
			}
			break;
		case 6:
			if(s6_flag == 0)
			{
				s6_flag = 1;
				interface = 3;
			}
			else if(s6_flag == 1)
			{
				s6_flag = 0;
				interface = 1;
			}
			break;
		case 7:
			if(interface == 1)
			{
				if(dis_mode == 0)
				{
					dis_mode = 1;
				}
				else if(dis_mode == 1)
				{
					dis_mode = 0;
				}
			}
			else if(interface == 2)
			{
				if(++number > 9)
				{
					number = 0;            //翻页索引
				}
			}
			
			//参数设置
			if(interface == 3)
			{
				//0-90
				if(set_dis < 90)
				{
					set_dis += 10;
				}
				else
				{
					set_dis = 0;
				}
				Write_AT24C02(0x88,set_dis);
				Delay10ms();
			}
			break;
		default:break;
	}
}

void Save_AT24C02_Data(void)
{
	static uchar i = 0;
	if(Read_AT24C02(0x00) == 0xee)  //上电不是第一次
	{
		set_dis = Read_AT24C02(0x88);
		Delay10ms();
		//读取10次存储的数据
		for(i = 0;i<10;i++)
		{
			dis_info[i] = (Read_AT24C02(i) << 8) |Read_AT24C02(i+10);
			Delay10ms();

		}
	}
	else
	{
		Write_AT24C02(0x00,0xee);
		for(i = 0;i <10;i++)             //第一次上电时都是0
		{
			Write_AT24C02(i,0);
			Delay10ms();
			Write_AT24C02(i+10,0);
			Delay10ms();
		}
	}
	
}

void Init_System(void)
{
	Control_IO(0x80,0xff);         //关闭LED
	Control_IO(0xa0,0x00);         //关闭继电器和蜂鸣器
	Control_IO(0xc0,0x00);         //关闭数码管
	Timer2Init();                  //定时器2初始化
	Save_AT24C02_Data();           //EEPROM数据读取
}

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,count = 0;
	static uint t = 0;
	//LED控制
	Control_IO(0x80,~(L[1] << 0 | L[2] << 1|L[7] << 6| L[8] << 7));
	//数码管控制
	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;
	}
	
	if(finish_flag)
	{
		if(t++ == 200)
		{
			t = 0;
			l1_flash = ~l1_flash;
			count++;
			if(count == 20)
			{
				count = 0;
				finish_flag = 0;
				L[1] = 0;       //防止第10次的时候L[1] 还处于亮灯状态
			}
		}
	}
	
	dis_feq++;
	key_feq++;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/603303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt(C++)使用QChart动态显示3个设备的温度变化曲线

一、介绍 Qt的QChart是一个用于绘制图表和可视化数据的类。提供了一个灵活的、可扩展的、跨平台的图表绘制解决方案,可以用于各种应用程序,如数据分析、科学计算、金融交易等。 QChart支持多种类型的图表,包括折线图、散点图、柱状图、饼图等。它还支持多个数据系列(data…

Emacs之magit提交代码(一百零八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

【Python】导出docx格式Word文档中的文本、图片和附件等

【Python】导出docx格式Word文档中的文本、图片和附件等 零、需求 为批量批改学生在机房提交的实验报告&#xff0c;我需要对所有的实验文档内容进行处理。需要批量提取Word文档中的图片和附件以便进一步检查。如何提取&#xff1f;我想到了用起来比较方便的Python&#xff0…

基于Three.js和MindAR实现的网页端摄像头头部帽饰、头盔3D虚拟试穿戴功能(含源码)

前言 研究学习、使用Mind AR有一段时间了&#xff0c;发现它的虚拟试穿戴功能还是比较好玩的&#xff0c;对售卖头部佩戴相关产品的公司还是有一定的应用价值的。例如&#xff1a;耳环、口罩、眼镜、头盔和帽子等都是适用的。 于是我收集了很多头部佩戴相关的3D模型进行测试&a…

人体姿态估计(Human Pose Estimation)

人体姿态估计的介绍与应用 姿态估计问题可以分为两大类&#xff1a;2D姿态估计和3D姿态估计。前者是为每个关键点预测一个二维坐标 (x,y) &#xff1b;后者是为每个关键点预测一个三维坐标 (x,y,z) &#xff0c;增加了一维深度信息。 2D姿态估计 主要有两种方法&#xff0c;基…

ASP.NET Core MVC 从入门到精通之自动映射(一)

随着技术的发展&#xff0c;ASP.NET Core MVC也推出了好长时间&#xff0c;经过不断的版本更新迭代&#xff0c;已经越来越完善&#xff0c;本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容&#xff0c;适用于初学者&#xff0c;在校毕业生&#xff0c…

Golang 从零开始实现多人聊天室(五)开发前奏-目录结构优化

系列文章目录 跟着&#x1f63d;猫猫学Golang&#xff0c;快人一步 系列初开&#xff0c;跟着我走进Go 语言的世界里&#x1f30d; 系列目录 Golang 从零开始实现多人聊天室&#xff08;一&#xff09;服务端监听 Golang 从零开始实现多人聊天室&#xff08;二&#xff09;客…

PLSQL连接Oracle 数据库配置详解

1. 下载instantclient-basic-win32-11.2.0.1.0 Oracle Instant Client - Free tools and libraries for connecting to Oracle Database &#xff08;oracle官网下载地址:http://www.oracle.com/technetwork/topics/winsoft-085727.html &#xff0c; 下载地址2&#xff1a;h…

nginx中相关通信总结

目录 1.master进程监听socket 2.master和worker进程通信机制 2.1通信渠道 2.2通信方法 2.3通信内容 2.4子进程事件处理 3.epoll封装 4.linux系统下信号查看 1.master进程监听socket nginx在master进程socket bind listen&#xff0c;accept在通过epoll在子进程中控制&a…

数据链路层:MAC地址

数据链路层&#xff1a;MAC地址&#xff08;以太网MAC子层所使用的地址&#xff09; 湖科大教书匠&#xff1a;MAC地址 声明&#xff1a;该学习笔记来自湖科大教书匠&#xff0c;笔记仅做学习参考 多主机连接在同一个广播信道上&#xff0c;要想实现两个主机之间的通信&#x…

MIUI系统降级刷机

成果图 解锁成功图 刷机确实成功了,不知道为什么显示失败的红色error,但是不影响使用 。 我的是小米平板5 Pro 刷机不是个简单的事情,有很多细节要注意,稍不留神手机就会变成砖,我见过好多人手机刷成砖,我无能为力,我也是个外行,自己多方面的了解许久之后,才开始对自…

你连存活到JDK8中著名的Bug都不知道,我怎么敢给你加薪

在笔者研究 JDK 源码时&#xff0c;注意到在CopyOnWriteArrayList 和ArrayList 的构造器中都出现了如下 bug 字样 6260652 其实代表的JDK bug 列表中的编号 http://bugs.java.com/bugdatabase/view_bug.do?bug_id6260652 http://bugs.java.com/bugdatabase/view_bug.do?bug…

【Leetcode60天带刷】day04链表——24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交

题目&#xff1a;24. 两两交换链表中的节点 Leetcode原题链接&#xff1a;24. 两两交换链表中的节点 思考历程与知识点&#xff1a; 因为头结点没有前一个节点&#xff0c;所以为了让所有节点都能采用同一种调换方式&#xff0c;选择用虚拟头结点的写法。虚拟头结点可以理解…

英文论文(sci)解读复现【NO.16】OTA:目标检测的最优传输分配

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

从零开始学习JavaScript:轻松掌握编程语言的核心技能③

从零开始学习JavaScript&#xff1a;轻松掌握编程语言的核心技能③ 一&#xff0c;JavaScript条件语句1.1 if...Else 语句1.2 if...else if...else 语句1.3 switch 语句1.4 for 循环1.5 while 循环 二&#xff0c;JavaScript break 和 continue 语句2.1 break语句2.2 continue语…

支付系统设计四:支付核心设计03-快捷短信确认(失败转代扣)

文章目录 前言一、快捷支付1. 执行流程1.1 发送短信1.1.1 发送短信(正常情况)1.1.2 发送短信(异常情况) 1.2 短信确认1.2.1 短信确认(正常情况)1.2.2 短信确认(异常情况) 2. 短信确认流程分析2.1 Service层执行2.2 快捷支付确认2.2.1 快捷支付确认命令链2.2.2 流程分析2.2.3 详…

Nacos 详解

Nacos是阿里的一个开源产品&#xff0c;是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案。 1.1 什么是配置 应用程序在启动和运行的时候往往需要读取一些配置信息&#xff0c;配置基本上伴随着应用程序的整个生命周期&#xff0c;比如&#xff1a;数 据库…

istio证书异常

istio有时会出现证书异常的问题&#xff0c;例如证书校验失败&#xff0c;证书过期等&#xff0c;此时需要我们手动处理istio证书问题。 一、我的istio版本 client version: 1.3.3 control plane version: 1.3.3二、开始处理 1、先查询istio的密钥istio-ca-secret&#xff1a…

飞桨 GPU 训练

飞桨官网介绍使用流程 paddle —— 飞桨的深度学习核心框架本地 padddlepaddle 的安装和卸载安装查看当前安装的版本卸载 启动 GPU 训练指定 GPU 飞桨创建项目PaddlePaddle 2.1.2 下的对比修改为 paddlepaddle2.4.0 CUDA 飞桨 飞桨官网&#xff1a;https://www.paddlepaddle.o…

编程最重要的技术之一 — 调试(以C语言代码为例)

编程最重要的技术之一 — 调试&#xff08;以C语言代码为例&#xff09; 前言1. 什么是bug?2. 调试是什么&#xff1f;有多重要&#xff1f;2.1 调试是什么&#xff1f;2.2 调试的基本步骤2.3 Debug和Release的介绍 3. Windows环境调试介绍3.1 调试环境准备3.2 学会快捷键3.3 …