一.题目分析

(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博客里面有详细的讲解,大家可前往此链接学习

Logo

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

更多推荐