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

笔者参加第十三届蓝桥杯嵌入式比赛第二场,在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

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐