草庐IT

第十三届第一场蓝桥杯嵌入式主观题讲解

amkl 2023-04-04 原文

第一次发帖,纪念一下哈!

笔者参加第十三届蓝桥杯嵌入式比赛第二场,在4.9号第一场比赛结束后拿到赛题进行练习后,将难点以及解决思路分享给大家,有讲解不到位的欢迎大家指出哈,相互学习进步。


目录

一、赛题分析

二、问题总结

三、代码(完整代码,功能全部实现,附有注释)


一、赛题分析


       这是刚刚过去的第十三届第一场嵌入式的省赛,模拟比赛的时候,拿到赛题,就发现相较于上一年简单了一些。但也有些踩坑点。所以,先一步一步的把其他的模块先实现了,其他的模块都很简单,非常中规中矩。接下来就搞细节部分,其实说难也不是很难,主要是比较麻烦。

      我觉得在我们拿到赛题的时候,应该分模块来实现,首先看看用到了哪些模块, 再去看每一个模块,赛题的要求是什么。比如说输出PWM, 题目要求需要改变频率和占空比,我们就需要配置定时器的输出比较模式。

我个人觉得,这套赛题难点如下:

  *难点1."@"的切换,显示,处理
  *难点2.密码错误计数,超过三次后再次确认密码时,正确次数清零,错误则继续保持闪烁报警。
  *难点3.串口信息处理,字数串长度,格式,范围,密码输入是否正确等 
  *难点4.LED2闪烁处理,间隔0.1s亮灭,5s后熄灭处理。

最后我觉得只要选择题不要错的太多,不要有太大的逻辑错误, 影响整体系统运行,大家应该都可以进国赛。

二、问题总结


      模块外设配置大家应该都不会遇到什么大的问题。

       逻辑方面第一个是主要就是串口。我串口使用的IDLE+RXNE来实现串口的不定长数据的接收的。在测试过程中发送字符不一定等长。在实现串口的部分,首先要实现能够正确识别,然后再注意一些细节的逻辑错误;

判断接收到正确信息的长度为7个字符,“-”的位置等等。
我是在字符串检查函数中进行如下操作

1.检查字符串长度,不为7个跳出检测

2.第四个字符是否为'-',不是跳出检测

3.检测数组第一到第三字符以及第五到第七字符ASCII范围是否在"0-9"之间,不是跳出检测

4.核对数组转化后第一到第三字符所传递的密码与当前密码是否相同,不是跳出检测

5.进行如上操作后仍未跳出检测,表明信息正确,则将数组第五到第七字符转化后赋值到密码储存数组当中去,实现密码修改功能。
下面附上串口部分的关键代码:

void  StringCheck(void)
{
 	uint8_t i=1;
	
	while(i)
	{
		if(RxCounter!=7)//长度不正确
		{
		 break;
		}
		if(RxBuffer[3]=='-')
		{
			for(i=0;i<3;i++)                            
			{                                              
				if(RxBuffer[i]>'9'||RxBuffer[i]<'0')
				break;
			}
			for(i=4;i<6;i++)                            
			{                                              
				if(RxBuffer[i]>'9'||RxBuffer[i]<'0')
				break;
			}
					
			Variable.UartPassword[0] = RxBuffer[0] - '0';
			Variable.UartPassword[1] = RxBuffer[1] - '0';
			Variable.UartPassword[2] = RxBuffer[2] - '0';
			
			if((Variable.UartPassword[0]!=Variable.Password[0])||\
				 (Variable.UartPassword[1]!=Variable.Password[1])||\
				 (Variable.UartPassword[2]!=Variable.Password[2]))
			break;
			
			Variable.Password[0] = RxBuffer[4] - '0';
			Variable.Password[1] = RxBuffer[5] - '0';
			Variable.Password[2] = RxBuffer[6] - '0';		
		}
	 break;
	}
}

 逻辑方面第二个是主要就是@的显示,切换等。

        我没有采用数组的形式存放@和0-9,而是在lcd函数中判断BxReset的值切换显示信息。

使用变量BxReset(x=1~3),赋值为0,在初始按键按下时,根据读取键值,改变其键值对应的变量BxReset,后续按下不再改变BxReset的值。屏幕显示Bx对应的数值(0~9)。

上电显示密码输入错误输出状态界面切换会密码输入界面的情况下将变量BxReset(x=1~3)的值赋值为0,实现@的显示。

下面附上其关键代码:

1.按键函数对其处理:

void Key_Proc(void)
{
	static uint8_t i=0;
 
  Key_refresh();	 
	if(key_falling==B1)//密码输入界面下B1值
	{
    if((Variable.Index==PSD)&&(Variable.B1Reset==0))
		{
		  Variable.B1Reset=1;
		}
		else if((Variable.Index==PSD)&&(Variable.B1Reset==1))
		{
			(Variable.InputPassword[0]==9)?(Variable.InputPassword[0]=0):(Variable.InputPassword[0]++);
		}
				
	}
	else	if(key_falling==B2)//密码输入界面下B2值
	{
    if((Variable.Index==PSD)&&(Variable.B2Reset==0))
		{
		  Variable.B2Reset=1;
		}
		else if((Variable.Index==PSD)&&(Variable.B2Reset==1))
		{
			(Variable.InputPassword[1]==9)?(Variable.InputPassword[1]=0):(Variable.InputPassword[1]++);
		}
	}
	else	if(key_falling==B3)//密码输入界面下B3值
	{
    if((Variable.Index==PSD)&&(Variable.B3Reset==0))
		{
		  Variable.B3Reset=1;
		}
		else if((Variable.Index==PSD)&&(Variable.B3Reset==1))
		{
			(Variable.InputPassword[2]==9)?(Variable.InputPassword[2]=0):(Variable.InputPassword[2]++);
		}
	}
	else if(key_falling==B4)//密码输入界面下确认键
	{
		for(i=0;i<3;i++)
		{
		  if(Variable.Password[i]==Variable.InputPassword[i])
			{
				Variable.PasswordRight=1;//密码正确
				Variable.Time5s_flag=1;//开启5s计时				
			}
			else
			{
			 Variable.PasswordError=1;//密码错误
			}
		}
		 Password_Check();//密码核对函数
	}
}

2.密码核对处理:

void Password_Check(void)
{
  if((Variable.PasswordRight==1)&&(Variable.PasswordError==0))//密码正确 
	{
	 Variable.Index=STA;
	 Variable.PasswordRight=0;
	 Variable.ErrorCnt=0;//错误次数清零
	}
	else//密码错误
	{
	 Variable.Index=PSD;
	 Variable.B1Reset=0;
	 Variable.B2Reset=0;
	 Variable.B3Reset=0;
	 Variable.InputPassword[0]=0;		
	 Variable.InputPassword[1]=0;
	 Variable.InputPassword[2]=0;
	 Variable.PasswordRight=0;
	 Variable.PasswordError=0;
	 Variable.ErrorCnt++;
		if(Variable.ErrorCnt>=3)//超过3次5s报警开启
		{
			Variable.ErrorTime5s_flag=1;
		}			
	}
}

3.界面切换时的处理

void Pwm_Proc(void)
{
  if(Variable.Index==STA)
	{
	 	TIM_SetAutoreload(TIM2,500 - 1);//设置频率为2KHz
		TIM_SetCompare2(TIM2,100);//设置占空比10%
		LED_Control(LED1,ON);//在输出界面保持led1亮
	}
	else
	{
		TIM_SetAutoreload(TIM2,1000 - 1);	//设置PWM频率为1KHz.
	  TIM_SetCompare2(TIM2,500);//设置占空比50%
		LED_Control(LED1,OFF);
	} 
	if(Variable.Time5s_flag==2)//5s时间到,复位密码,切换回原界面
	{
		Variable.Time5s_flag=0;
	  Variable.Index=PSD;
		Variable.B1Reset=0;
	  Variable.B2Reset=0;
	  Variable.B3Reset=0;
	  Variable.InputPassword[0]=0;		
	  Variable.InputPassword[1]=0;
	  Variable.InputPassword[2]=0;
	}
}

三、代码(完整代码,功能全部实现,附有注释)

 lanqiaobei_qianrushi/main.c at main · AMingKL/lanqiaobei_qianrushi (github.com)

baidu链接:https://pan.baidu.com/s/1-voaXg4X5lfm3ikiGbhL3Q 
提取码:amkl

有关第十三届第一场蓝桥杯嵌入式主观题讲解的更多相关文章

  1. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  2. ruby-on-rails - CarrierWave - PDF - 只选择第一页 - 2

    我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful

  3. ruby - 如何跳过 CSV 文件的第一行并将第二行作为标题 - 2

    有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|

  4. arrays - 在一行中选择数组的第一个和最后一个元素 - 2

    我的任务是从数组中选择最高和最低的数字。我想我很清楚我想做什么,但只是努力以正确的格式访问信息以满足通过标准。defhigh_and_low(numbers)array=numbers.split("").map!{|x|x.to_i}array.sort!{|a,b|ba}putsarray[0,-1]end数字可能看起来像"80917234100",要通过,我需要输出"9234"。我正在尝试putsarray.first.last,但一直无法弄明白。 最佳答案 有Array#minmax完全满足您需要的方法:array=[80,

  5. ruby-on-rails - Ruby 或 Rails 有只将第一个字符大写的方法吗? - 2

    或者好像我必须自己写方法?(保持DHA不变):ruby-1.9.2-p180:001>s='omega-3(DHA)'=>"omega-3(DHA)"ruby-1.9.2-p180:002>s.capitalize=>"Omega-3(dha)"ruby-1.9.2-p180:003>s.titleize=>"Omega3(Dha)"ruby-1.9.2-p180:005>s[0].upcase+s[1..-1]=>"Omega-3(DHA)" 最佳答案 如果我的回答只是垃圾,我深表歉意(我不做ruby)。但我相信我已经为您找到了答

  6. ruby - gsub 删除第一个逗号前的所有内容 - 2

    我有这个字符串:auteur="comtedeFlandreetHainaut,Baudouin,Jacques,Thierry"我想删除第一个逗号之前的所有内容,即在这种情况下保留“Baudouin,Jacques,Thierry”试过这个:nom=auteur.gsub(/.*,/,'')但这会删除最后一个逗号之前的每个逗号,只保留“Thierry”。 最佳答案 auteur.partition(",").last#=>"Baudouin,Jacques,Thierry" 关于rub

  7. ruby-on-rails - Order Hash 并删除第一个键值对 - 2

    我有一个以时间戳为键的哈希。hash={"2016-05-31T22:30:58+02:00"=>{"path"=>"/","method"=>"GET"},"2016-05-31T22:31:23+02:00"=>{"path"=>"/tour","method"=>"GET"},"2016-05-31T22:31:05+02:00"=>{"path"=>"/contact_us","method"=>"GET"}}我订购了这个系列并得到了第一双这样的:hash.sort_by{|k,_|k}.first.first但是我该如何删除它呢?删除方法requiresyou知道key的准确

  8. arrays - 字符串数组中字符串第一部分的总和 - 2

    我有一个字符串数组,我需要从中提取第一个单词,将它们转换为整数并获得它们的总和。示例:["5Apple","5Orange","15Grapes"]预期输出=>25我的尝试:["5","5","15"].map(&:to_i).sum 最佳答案 我从你的问题中找到了答案。["5Apple","5Orange","15Grapes"].map(&:to_i).sum在数组中,如果存在任何整数可转换值,那么它将自动转换为整数。 关于arrays-字符串数组中字符串第一部分的总和,我们在Sta

  9. 100个python算法超详细讲解:画直线 - 2

    1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva

  10. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

随机推荐