【蓝桥杯嵌入式】STM32G431——十三届第一场省赛真题及程序设计代码详解


前言

本次分享的内容是关于第十三届蓝桥杯嵌入式省赛的解题思路和经验总结。这也是我自上月以来的首次更新,希望能够为大家提供一些有用的参考和指导。

一、题目介绍

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

二、相关模块介绍和重难点分析

1.相关模块

第十三届比赛主要有:LED、KEY、LCD、TIM、USART。

2.重难点分析

这届的目的是做一个密码锁,主要是对按键和屏幕处理的考查。通过按键输入密码,并且通过是否正确输入密码来改变PA1脉冲的输出状态和LED的闪烁情况,以及通过串口发送正确的指令来改变原有的密码。
**难点1:**按键从ASCII码@变成ASCII码0然后在依次增加变成9在变回0如此循环。
**难点2:**对LED1灯持续亮五秒和PWM脉冲持续输出2KHZ五秒再变回1KHZ的处理,这可能是本届最易出错的点。

三.题解

1、代码相关定义与函数声明:

char view;//LCD显示界面 0是输入密码界面 1是PWM输出界面
char temp[20];//LCD显示参数数组
char mark='@';//ASCII@变量
char secret_one,secret_sec,secret_thir;//定义3位输入参数变量
uint8_t judge;//判断串口数据是否合法
uint8_t uled;//LED显示参数
uint8_t pwm;//PWM输出状态界面 0是PWM输出1KHZ 1是PWM输出2KHZ
uint8_t flag;//输入密码超过三次报警标志位
uint8_t wordnum=0;//密码输入次数
uint8_t keynum=0;//按键值
uint8_t arr[7];//接受串口数据数组
uint8_t word[3]={'1','2','3'};//初始化密码,储存密码数组
extern struct Chword New_word;
extern char Cword;
__IO uint32_t LED_tick;//LED计时时间
__IO uint32_t PWM_tick;//PWM计时时间

......函数声明......
void pro_view(void);//界面处理函数
void key_pro(uint8_t keyword);安检处
void dis_chword(void);
void LED_dis(void);

2、主函数代码:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */
	
  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */
  	secret_one=mark;//初始化输入密码界面的参数
	secret_sec=mark;
	secret_thir=mark;
  	LCD_Init();      
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	LED_pro(0x00);//使LED全部熄灭
	HAL_UART_Receive_IT(&huart1,arr,7);//开启串口接收中断
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	 
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  keynum=Key_Read();
	  key_pro(keynum);
	  dis_chword();
	  pro_view();
	  LED_dis();
  }
  /* USER CODE END 3 */
}

3、按键扫描函数:

eg:这里需要注意题目中给出的避免多次触发,最好给按键上锁。

uint8_t Key_Read(void)
{
	//定义按键锁变量
	static uint8_t key_lock=1;
	
	if((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==RESET||HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==RESET||
	   HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==RESET||HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==RESET)
	   &&key_lock==1)
	{
		//给按键上锁,避免多次触发
		key_lock=0;
		//消抖
		HAL_Delay(10);
		
		//判断B1是否按下
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==RESET)
		{
			return 1;
		}
		
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==RESET)
		{
			return 2;
		}
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==RESET)
		{
			return 3;
		}
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==RESET)
		{
			return 4;
		}

	}
	//按键松手
	if((HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==SET&&HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==SET&&
	    HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==SET&&HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==SET)
	    &&key_lock==0)
	   {
		   //开锁
		 key_lock=1;
	   }
	
	   return 0;
}

4、按键处理函数:

eg:这里就是我上面提到的第一个难点和第二个LED1难点,第一个难点写代码容易写成从’@'变为0,然后9直接变为1了,而没有变成0。解决方法是单独用if单独判断为’@‘时就变为0。至于第二个难点解决方法用系统时钟uwtick变量计时,计时完全五秒不会影响程序的运行。(或者用定时器计时来解决)

void key_pro(uint8_t keyword)
{
	
	if(keyword==1)
	{
		if(secret_one==mark){
		secret_one='0';
		}
		else{
				secret_one=secret_one+1;
				if(secret_one>'9'){
				secret_one='0';
			}
		}

	}
	if(keyword==2)
	{
		if(secret_sec==mark){
		secret_sec='0';
		}
		else{
			secret_sec=secret_sec+1;
			if(secret_sec>'9'){
			secret_sec='0';
			}
		}	
	}
	if(keyword==3)
	{
		if(secret_thir==mark){
		secret_thir='0';
		}
		else{
		   	secret_thir=secret_thir+1;
			if(secret_thir>'9'){
			secret_thir='0';
			}
		}
	}
	if(keyword==4){
		//判断密码是否正确
		if(secret_one==word[0] &&secret_sec==word[1] &&secret_thir==word[2]){
			//点亮LED1
			uled |= 0x01;
			LED_tick=uwTick;//开始计时
			wordnum=0;//密码输入次数清零
			pwm=1;//转变PWM波状态
			PWM_tick=uwTick;//PWM时间开始计时
			view=1;//切换成PWm输出界面
			LCD_Clear(Black);//清屏
		}
		else{
			wordnum++;//错误密码输入次数增加
			if(wordnum>=3){
				LED_tick=uwTick;
				wordnum=0;
				flag=1;//报警
			}
			secret_one=mark;//错误三次以上密码参数恢复'@'状态
			secret_sec=mark;
			secret_thir=mark;
		}
		

	}
}

5、界面和PWM输出处理函数:

eg:这里的PWM输出时间处理,跟上面一样就行。

void pro_view(void)
{	
	//配置PWM初始状态下的输出和占空比
	if(pwm==0){
		__HAL_TIM_SetAutoreload(&htim2,1999);
		__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,100);
	}
	//配置PWM在密码正确时的输出和占空比
	if(pwm==1){
		__HAL_TIM_SetAutoreload(&htim2,999);
		__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,100);
	}
	//输入密码界面
	if(view==0)
	{
		sprintf(temp,"      PSD");
		LCD_DisplayStringLine(Line2,(uint8_t*)temp);
		sprintf(temp,"    B1:%c",secret_one);
		LCD_DisplayStringLine(Line4,(uint8_t*)temp);
		sprintf(temp,"    B2:%c",secret_sec);
		LCD_DisplayStringLine(Line5,(uint8_t*)temp);
		sprintf(temp,"    B3:%c",secret_thir);
		LCD_DisplayStringLine(Line6,(uint8_t*)temp);
	}

	if(view==1)//PWM输出状态界面
	{
		if(uwTick-PWM_tick>5000){
			pwm=0;
		}
		if(pwm==0){
			sprintf(temp,"      STD");
			LCD_DisplayStringLine(Line2,(uint8_t*)temp);
			sprintf(temp,"    F:1000HZ");
			LCD_DisplayStringLine(Line4,(uint8_t*)temp);
			sprintf(temp,"    D:10%%");
			LCD_DisplayStringLine(Line5,(uint8_t*)temp);			
		}
		else{
			sprintf(temp,"      STD");
			LCD_DisplayStringLine(Line2,(uint8_t*)temp);
			sprintf(temp,"    F:2000HZ");
			LCD_DisplayStringLine(Line4,(uint8_t*)temp);
			sprintf(temp,"    D:10%%");
			LCD_DisplayStringLine(Line5,(uint8_t*)temp);
		
		}
	}
}

6、LED处理函数:

void LED_dis(void)
{
	static __IO uint32_t led_tick;//减速变量
	if(uwTick-led_tick<100){//以0.1秒闪烁
		return;
	}
	led_tick=uwTick;
	//五秒后LED1、2熄灭
	if(uwTick-LED_tick>5000){
		uled=0x00;
		flag=0;
	}
	//报警,点亮LED2
	if(flag==1){
		uled^=0x02;
	}
	LED_pro(uled);
}

7、串口处理函数:

struct Chword
{
	uint8_t Pri[3];
	uint8_t Sec;
	uint8_t Fin[3];
};
struct Chword New_word;//记录串口信息结构体
char Cword=0;//接收数据成功标志位
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//记录串口信息
	New_word.Pri[0]=arr[0];
	New_word.Pri[1]=arr[1];
	New_word.Pri[2]=arr[2];
	New_word.Sec=arr[3];
	New_word.Fin[0]=arr[4];
	New_word.Fin[1]=arr[5];
	New_word.Fin[2]=arr[6];
	
	Cword=1;
	//清除原有数组数据,为下次接收数据做准备
	memset(arr,0,7);
}

8、判断串口信息格式是否有误以及修改密码函数

uint8_t judge_word(void)
{
	uint8_t i=0;
	if(Cword==1)
	{
	//验证串口信息
		for(i=0;i<3;i++){
			if(New_word.Fin[i]>'0' && New_word.Fin[i]<'9' &&
				New_word.Pri[i]>'0' && New_word.Pri[i]<'9' &&
				 New_word.Sec=='-'
				 ){
				return 2;//数据合格
			}
		}
	}
		return 1;//若接收失败也不合格
}
//修改密码函数
void dis_chword(void)
{
	judge=judge_word();//判断密码是否合格
	//修改密码
	if(judge==2){
		if(New_word.Pri[0]==word[0] && New_word.Pri[1]==word[1] && New_word.Pri[2]== word[2]){
			word[0]=New_word.Fin[0];
			word[1]=New_word.Fin[1];
			word[2]=New_word.Fin[2];
		}	
	}

	
}

总结:

通过本届试题的分析,我觉得这次串口模块的考察相对上届更简单了,其他模块也没有太多创新,整体难度比上届稍微容易一些。解题过程也没有太大困难,只要注意细节就能拿到满分。和以往一样,完整的源代码如下。

源码:

源码

  • 22
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
### 回答1: 蓝桥杯是全国性的计算机大赛,旨在提高大学生的计算机技术水平和创新能力。嵌入式STM32G431是一款嵌入式芯片,具有高性能和低功耗的特点。第十二届第一场省赛停车计费系统是蓝桥杯的一道工程题目,要求参赛选手设计一个停车场计费系统。 停车计费系统是指通过嵌入式技术实现对车辆进入和离开停车场的自动检测、计时和计费的系统。对于这个题目,参赛选手可以根据题目要求,使用STM32G431芯片设计一个具有以下功能的系统: 1. 车辆进入检测:使用车辆传感器检测车辆的进入,触发计时。 2. 车辆离开检测:使用车辆传感器检测车辆的离开,停止计时。 3. 计时功能:使用内部时钟模块获取进入和离开的时间,并计算停车时间。 4. 计费功能:根据停车时间,按照一定的计费规则进行计费。 5. 显示功能:使用液晶显示屏显示当前的停车信息,如车牌号、停车时间、费用等。 6. 数据存储功能:使用闪存等储存介质将停车数据进行存储,以便后续的数据分析和查询。 设计一个停车计费系统涉及到硬件设计和软件编程两个方面。硬件方面,参赛选手需要选择合适的传感器、显示屏、存储介质等,以及设计电路和接口进行连接。软件方面,需要使用C语言或者汇编语言编写程序,对芯片进行编程,实现各项功能。 通过此次比赛,选手们可以锻炼嵌入式系统的设计能力和编程能力,了解实际应用中嵌入式系统的工作原理和应用场景。同时,也能提升对STM32G431芯片的理解和运用能力。这对于培养嵌入式技术人才,推动物联网技术的发展都具有积极意义。 ### 回答2: 蓝桥杯是面向计算机爱好者的智力竞赛,而嵌入式STM32G431是一款嵌入式系统开发板。第十二届第一场省赛的停车计费系统真题工程,则是要求参赛选手设计并实现一个能够进行停车计费的系统。 停车计费系统是一种用于自动计费和管理停车场的系统。这个系统可以通过识别车辆的进出以及停车的时间,自动计算并收费。在这个工程中,选手需要使用嵌入式STM32G431开发板以及相关的硬件和软件,来设计一个能够实现停车计费功能的系统。 首先,选手需要使用传感器或摄像头来实现车辆进出的检测。当车辆进入或离开停车场时,传感器会发出信号并通过STM32G431进行检测。接着,选手需要编程实现识别车辆的算法,以便能够识别不同的车辆。当车辆停放时,系统会通过计时器记录停车的时间。 然后,选手需要编写计费算法,根据停车的时间来计算费用。这个算法可以根据停车场的规则来确定费用的计算方式,例如按小时计费或按照不同的时间段采用不同的费率。 最后,选手还需要设计一个界面,使得系统能够与用户进行交互。用户可以通过该界面查询停车费用,并进行付款。同时,选手还需要保证系统的稳定性和安全性,确保数据的准确性和保密性。 总而言之,蓝桥杯嵌入式STM32G431第十二届第一场省赛停车计费系统真题工程要求选手使用硬件和软件开发能力,设计并实现一个完整的停车计费系统。这需要选手具备嵌入式系统开发、传感器技术、算法设计和界面设计等多方面的知识和技能。 ### 回答3: 蓝桥杯嵌入式stm32g431——第十二届第一场省赛停车计费系统真题工程是一个基于STM32G431开发板的停车计费系统设计题目。该系统的主要功能是实现停车场的车辆进入、出场的计费管理。 首先,该系统需要实现一个车辆进入检测的功能。当车辆进入停车场时,系统会通过传感器检测到车辆的到达,并记录下进入的时间。 然后,系统需要实现一个车辆出场的功能。当车辆准备离开停车场时,系统会通过传感器检测到车辆的离开,并记录下离开的时间。 接下来,系统需要计算车辆停留的时间。通过进入时间和离开时间的差值计算得出车辆停留的时长。 最后,系统需要计算停车费用。根据停车场的计费规则,根据车辆停留的时长计算出停车费用,并将费用显示在屏幕上。 在实现上述功能的过程中,需要运用STM32G431开发板的各种功能和模块,包括GPIO口、定时器、中断、串口通信等。通过编写相应的代码,实现按钮的控制、传感器检测、时间的计算以及屏幕的显示等功能。 该项目的设计需要考虑多种情况,比如车辆重复进入出场、车辆进入出场顺序错乱等,要充分考虑这些异常情况并进行相应的处理。在代码编写过程中,还需注意代码的优化和资源的合理利用,以提高系统的性能和效率。 通过完成这个项目的设计与实现,可以加深对STM32G431嵌入式系统的了解和应用,并提升嵌入式系统开发的能力。同时,也能锻炼自己的逻辑思维、问题解决能力和团队合作精神。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

嵌入式-小博

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

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

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

打赏作者

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

抵扣说明:

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

余额充值