第十三届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)(第一场)
一.题目分析
(1).题目
(2).题目分析
1.按键功能分析
a. 密码调整功能,按下B1,B2,B3三位密码值分别加1,按键刚上电显示界面的密码值为@
b. 密码确认功能B4,密码正确就跳转到输出状态页面,不正确就停留在输入界面,同时显示界面的三位密码值重置为@
2.脉冲输出功能分析
a.无正确密码提交时,PA1输出1KHz的方波信号
b.输入正确密码时,PA1输出2KHz 10%占空比的脉冲信号持续5秒,之后切换回密码输入界面@@@
3.串口通信功能分析
发送指定格式:当前密码-新密码,可修改密码,如果当前密码不正确就无法修改
4.LED指示功能分析
a.密码验证成功,LD1亮5秒之后熄灭
b.连续三次及以上的密码输入错误,LD2以0.1秒闪烁5秒熄灭
(3).逻辑导图
二.CubeMX配置
由于蓝桥杯使用的板子都是STM32G431RBT6,配置都是相同的,模板已经在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客配置完成,大家可以前往学习
三.相关代码实现
(1)MAIN
1.全局变量声明
#include "main.h"
#include "RCC\bsp_rcc.h"
#include "KEY_LED\bsp_key_led.h"
#include "LCD\bsp_lcd.h"
#include "UART\bsp_uart.h"
#include "TIM\bsp_tim.h"//***全局变量声明区
//*减速变量
__IO uint32_t uwTick_Key_Set_Point = 0;//控制Key_Proc的执行速度
__IO uint32_t uwTick_Led_Set_Point = 0;//控制Led_Proc的执行速度
__IO uint32_t uwTick_Lcd_Set_Point = 0;//控制Lcd_Proc的执行速度
__IO uint32_t uwTick_Usart_Set_Point = 0;//控制Usart_Proc的执行速度//*按键扫描专用变量
uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old;//*LED专用变量
uint8_t ucLed;//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符//*串口专用变量
uint8_t counter = 0;
uint8_t str[40];
uint8_t rx_buffer;
uint8_t RX_Buff[7];//全局变量
unsigned char B1_value = 255;
unsigned char B2_value = 255;
unsigned char B3_value = 255;
unsigned char Screen_Disp_Flag;
unsigned char Password[3] = {1, 2, 3};
__IO uint32_t uwTick_PWM_Output = 0;//控制PWM输出为5s
unsigned char PWM_Output_Just_Do_One_Time;
unsigned char KEY_input_error = 0;
__IO uint32_t uwTick_LED_BULING = 0;//控制LED在连续三次以上出错后的闪烁
unsigned char LED_BULING_Ctrl;//***子函数声明区
void Key_Proc(void);
void Led_Proc(void);
void Lcd_Proc(void);
void Usart_Proc(void);
2.系统主函数
int main(void)
{/* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* Configure the system clock */SystemClock_Config();/*bsp资源的初始化*/KEY_LED_Init();LCD_Init();LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White); UART1_Init();MX_TIM2_Init();//*串口接收中断打开HAL_UART_Receive_IT(&huart1, (uint8_t *)(&rx_buffer), 1);HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2); //PA1while (1){Key_Proc();Led_Proc();Lcd_Proc();Usart_Proc();}}
3.按键扫描子函数
a. 逻辑框图
b. 程序源码
//***按键扫描子函数
void Key_Proc(void)
{if((uwTick - uwTick_Key_Set_Point)<50) return;//减速函数uwTick_Key_Set_Point = uwTick;ucKey_Val = Key_Scan();unKey_Down = ucKey_Val & (ucKey_Old ^ ucKey_Val); ucKey_Up = ~ucKey_Val & (ucKey_Old ^ ucKey_Val); ucKey_Old = ucKey_Val;if(Screen_Disp_Flag == 0){if(unKey_Down == 1){if(++B1_value == 10)B1_value = 0;}if(unKey_Down == 2){if(++B2_value == 10)B2_value = 0;} if(unKey_Down == 3){if(++B3_value == 10)B3_value = 0;}if(unKey_Down == 4){if((B1_value == Password[0])&&(B2_value == Password[1])&&(B3_value == Password[2])){Screen_Disp_Flag = 1;__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,50);//输出修改__HAL_TIM_SET_AUTORELOAD(&htim2,499); ucLed |= 0x01; uwTick_PWM_Output = uwTick; PWM_Output_Just_Do_One_Time = 1; KEY_input_error = 0; }else{B1_value = 255;B2_value = 255; B3_value = 255;KEY_input_error++;if(KEY_input_error >= 3){uwTick_LED_BULING = uwTick;LED_BULING_Ctrl = 1;}}}}if(((uwTick - uwTick_PWM_Output) >= 5000)&&(PWM_Output_Just_Do_One_Time == 1)){Screen_Disp_Flag = 0;__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,500);//输出修改__HAL_TIM_SET_AUTORELOAD(&htim2,999);B1_value = 255;B2_value = 255; B3_value = 255;ucLed &= (~0x01); PWM_Output_Just_Do_One_Time = 0; }
}
4.LED扫描子函数
a. 逻辑分析
根据闪烁标志位控制LD2闪烁五秒熄灭
b. 程序源码
void Led_Proc(void)
{if((uwTick - uwTick_Led_Set_Point)<100) return;//减速函数uwTick_Led_Set_Point = uwTick;if(((uwTick - uwTick_LED_BULING) <= 5000)&&(LED_BULING_Ctrl == 1)){ucLed ^= 0x02; }else{LED_BULING_Ctrl = 0; ucLed &= (~0x02); }LED_Disp(ucLed);
}
5.LED扫描子函数
a. 逻辑导图
b. 程序源码
void Lcd_Proc(void)
{if((uwTick - uwTick_Lcd_Set_Point)<100) return;//减速函数uwTick_Lcd_Set_Point = uwTick;if(Screen_Disp_Flag == 0){sprintf((char *)Lcd_Disp_String, " PSD ");LCD_DisplayStringLine(Line1, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, " B1:%d ",(unsigned int)B1_value);if(B1_value == 255)sprintf((char *)Lcd_Disp_String, " B1:@ "); LCD_DisplayStringLine(Line3, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, " B2:%d ",(unsigned int)B2_value);if(B2_value == 255)sprintf((char *)Lcd_Disp_String, " B2:@ "); LCD_DisplayStringLine(Line4, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, " B3:%d ",(unsigned int)B3_value);if(B3_value == 255)sprintf((char *)Lcd_Disp_String, " B3:@ "); LCD_DisplayStringLine(Line5, Lcd_Disp_String); }else{sprintf((char *)Lcd_Disp_String, " STA ");LCD_DisplayStringLine(Line1, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, " F:2000Hz ");LCD_DisplayStringLine(Line3, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, " D:10%% ");LCD_DisplayStringLine(Line4, Lcd_Disp_String); sprintf((char *)Lcd_Disp_String, " ");LCD_DisplayStringLine(Line5, Lcd_Disp_String); }
}
6.串口接收中断回调函数
a. 逻辑导图
b. 程序源码
//串口接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{RX_Buff[counter] = rx_buffer; counter++;if(counter == 7){if(((RX_Buff[0]-'0') == Password[0])&&((RX_Buff[1]-'0') == Password[1])&&((RX_Buff[2]-'0') == Password[2])){Password[0] = (RX_Buff[4]-'0');Password[1] = (RX_Buff[5]-'0');Password[2] = (RX_Buff[6]-'0');sprintf(str, "success\r\n");}else{sprintf(str, "error\r\n"); }HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50); counter = 0; }HAL_UART_Receive_IT(&huart1, (uint8_t *)(&rx_buffer), 1);
}
(2)BSP
在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习