第十届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)
一.题目分析(1).题目(2).题目分析注意上限和下限的调整,上限值必须大于下限值,低于下限LD2会闪烁,低于上限LD1会闪烁。
·
一.题目分析
(1).题目




(2).题目分析
1.参考配置界面
注意上限和下限的调整,上限值必须大于下限值,低于下限LD2会闪烁,低于上限LD1会闪烁
2.按键功能分析
B1:显示界面和设置界面相互切换,同时将数据保存到E2PROM里面
B2:切换选择参数选项
B3:加按键(指示灯序号和电压参数)---要有边界保护,电压参数设置范围是0~3.3V,LED设置为LD1~LD8
B4:减按键(指示灯序号和电压参数)---要有边界保护,电压参数设置范围是0~3.3V,LED设置为LD1~LD8
3.LED功能分析
a. 输出电压高于上限,上限指示灯闪烁
b.输出电压低于下限,下限指示灯闪烁
c. 输出电压在上下限之间,两灯熄灭
d.除了上下限指示灯以外的其他灯熄灭
(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 "I2C\bsp_i2c.h"
#include "ADC\bsp_adc.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的执行速度
//*按键扫描专用变量
uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old;
//*LED专用变量
uint8_t ucLed = 0x0;
uint8_t ucLed_Bor = 0x01;
//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符
//*EEPROM的相关变量
uint8_t EEPROM_String_1[5] = {0x11,0x22,0x33,0x44,0x55};
uint8_t EEPROM_String_2[5] = {0};
//系统全局变量
uint8_t Sys_State;//整体状态
float Voltage;//R37的电压值
uint8_t Vot_State;//电压状态 0-低于 1-中间 2-高于
uint8_t Max_Min_LED[4] = {24,12,1,2};//0-上限值 1-下限值 2-高报警灯 3-低报警灯
//***子函数声明区
void Key_Proc(void);
void Led_Proc(void);
void Lcd_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(White);
LCD_SetBackColor(White);
LCD_SetTextColor(Blue);
I2CInit();
ADC2_Init();
while (1)
{
Key_Proc();
Led_Proc();
Lcd_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;
switch(unKey_Down)
{
case 1://B1按键
if(Sys_State == 0)
{
Sys_State = 1;
}
else
{
Sys_State = 0;
iic_24c02_write(Max_Min_LED, 0, 4);
}
LCD_Clear(White);
break;
case 2://B2按键
if(Sys_State)
{
if(++Sys_State == 5)
Sys_State = 1;
}
break;
// uint8_t Max_Min_LED[4];//0-上限值 1-下限值 2-高报警灯 3-低报警灯
case 3://B3按键+
switch(Sys_State)
{
case 1://上限值+0.3
Max_Min_LED[0] += 3;
if((Max_Min_LED[0] >= 33)&&(Max_Min_LED[0] <= 40))
Max_Min_LED[0] = 33;
break;
case 2://下限值+0.3
if((Max_Min_LED[1]+3) < Max_Min_LED[0])
Max_Min_LED[1] += 3;
break;
case 3:
if(++Max_Min_LED[2] >=8) Max_Min_LED[2] = 8;
if(Max_Min_LED[2] == Max_Min_LED[3])
{
if(Max_Min_LED[3] == 8)
Max_Min_LED[2] = 7;
else
{
if(++Max_Min_LED[2] >=8)
Max_Min_LED[2] = 8;
}
}
break;
case 4:
if(++Max_Min_LED[3] >=8) Max_Min_LED[3] = 8;
if(Max_Min_LED[3] == Max_Min_LED[2])
{
if(Max_Min_LED[2] == 8)
Max_Min_LED[3] = 7;
else
{
if(++Max_Min_LED[2] >=8)
Max_Min_LED[2] = 8;
}
}
break;
}
break;
case 4://B4按键-
switch(Sys_State)
{
case 1://上限值-0.3
if((Max_Min_LED[0]-3) > Max_Min_LED[1])
Max_Min_LED[0] -= 3;
break;
case 2://下限值-0.3
Max_Min_LED[1] -= 3;
if(Max_Min_LED[1] >= 200)
Max_Min_LED[1] = 0;
break;
case 3://-
if(--Max_Min_LED[2] == 0) Max_Min_LED[2] = 1;
if(Max_Min_LED[2] == Max_Min_LED[3])
{
if(Max_Min_LED[3] == 1)
Max_Min_LED[2] = 2;
else
{
if(--Max_Min_LED[2] == 0)
Max_Min_LED[2] = 1;
}
}
break;
case 4://-
if(--Max_Min_LED[3] == 0) Max_Min_LED[3] = 1;
if(Max_Min_LED[3] == Max_Min_LED[2])
{
if(Max_Min_LED[2] == 1)
Max_Min_LED[3] = 2;
else
{
if(--Max_Min_LED[2] ==0)
Max_Min_LED[2] = 1;
}
}
break;
}
break;
}
}
3.LED扫描子函数
a.逻辑分析
根据上下限和中间值控制灯的亮灭
b.程序源码
//***LED扫描子函数
void Led_Proc(void)
{
if((uwTick - uwTick_Led_Set_Point)<200) return;//减速函数
uwTick_Led_Set_Point = uwTick;
//Max_Min_LED 2-高报警灯 3-低报警灯 LD8 ucLed 1000 0000
switch(Vot_State)
{
case 0://低于下限
ucLed ^= ( ucLed_Bor << (Max_Min_LED[3]-1));
break;
case 1://中间
ucLed = 0x00;
break;
case 2://高于上限
ucLed ^= ( ucLed_Bor << (Max_Min_LED[2]-1));
break;
}
LED_Disp(ucLed);
}
3.LCD扫描子函数
a.逻辑框图

b.程序源码
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<100) return;//减速函数
uwTick_Lcd_Set_Point = uwTick;
//采集数据专用区域
// uint8_t Max_Min_LED[4];//0-上限值 1-下限值 2-高报警灯 3-低报警灯
Voltage = ((((float)getADC2())/4096)*3.3);
if((Voltage*10) > Max_Min_LED[0])
Vot_State = 2;
else if((Voltage*10) < Max_Min_LED[1])
Vot_State = 0;
else
Vot_State = 1;
//我的代码
if(!Sys_State)//在主界面
{
sprintf((char *)Lcd_Disp_String, " Main ");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Volt:%4.2fV",Voltage);
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
switch(Vot_State)
{
case 0:
sprintf((char *)Lcd_Disp_String, " Status:Lower ");
break;
case 1:
sprintf((char *)Lcd_Disp_String, " Status:Normal ");
break;
case 2:
sprintf((char *)Lcd_Disp_String, " Status:Upper ");
break;
}
LCD_DisplayStringLine(Line6, Lcd_Disp_String);
}
else//在设置界面
{
// uint8_t Max_Min_LED[4];//0-上限值 1-下限值 2-高报警灯 3-低报警灯
sprintf((char *)Lcd_Disp_String, " Setting ");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Max Volt:%3.1fV ",((float)Max_Min_LED[0]/10.0));
if(Sys_State == 1) LCD_SetBackColor(Green);
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
LCD_SetBackColor(White);
sprintf((char *)Lcd_Disp_String, " Min Volt:%3.1fV ",((float)Max_Min_LED[1]/10.0));
if(Sys_State == 2) LCD_SetBackColor(Green);
LCD_DisplayStringLine(Line5, Lcd_Disp_String);
LCD_SetBackColor(White);
sprintf((char *)Lcd_Disp_String, " Upper:LD%1d ",(unsigned int)Max_Min_LED[2]);
if(Sys_State == 3) LCD_SetBackColor(Green);
LCD_DisplayStringLine(Line6, Lcd_Disp_String);
LCD_SetBackColor(White);
sprintf((char *)Lcd_Disp_String, " Lower:LD%1d ",(unsigned int)Max_Min_LED[3]);
if(Sys_State == 4) LCD_SetBackColor(Green);
LCD_DisplayStringLine(Line7, Lcd_Disp_String);
LCD_SetBackColor(White);
}
}
(2)BSP
在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)