第十届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)

一、题目分析

开发板:CT117E-M4 (STM32G431RBT6)
开发环境: (MDK) Keil5+CubeMX

首先,本届赛题普遍比较简单,涉及到了LCD,LED指示灯,模拟电压输入以及按键模块。

其次,我们在官方给的资源数据包中的MDK5_LCD_HAL基础上做修改即可

二、CubeMX配置

三、相关代码

1、函数相关定义

#include "lcd.h"
#include "stdio.h"

_Bool ui = 0;//界面

u8 Tag;//按键松开
u8 Cnt;//按键按下

float Volt = 0;//实时显示的电压值
u8 Status[6] = "Upper";//定义一个数组判断电压是否处于上限到下限的区间内

float Max_Volt = 2.4;//上电显示的上限电压值
float Min_Volt = 1.2;//上电显示的下限电压值

float Max_Volt_Valid = 2.4;//实时显示的上限电压值
float Min_Volt_Valid = 1.2;//实时显示的下限电压值

u8 Led_Upper = 1;//电压超过上限的提醒指示灯(默认上电显示LED1)
u8 Led_Lower = 2;//电压低于下限的提醒指示灯(默认上电显示LED2)

u8 Led_Upper_Valid = 1;//实时(同上)
u8 Led_Lower_Valid = 2;//实时(同上)

u8 Key2_Cnt = 2;//B2执行的行数
u8 Led_Ctrl = 0;

u32 lcd_tick = 0;  
u32 key_tick = 0;
u32 ADC_Value = 0;
u32 LED_tick = 0;
  

2、按键模块

#define k1 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)
#define k2 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)
#define k3 HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)
#define k4 HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
#define key k1|(k2<<1)|(k3<<2)|(k4<<3)|0xf0

void KEY_Read()
{
	u8 keydate = (key) ^ 0xff;
	Tag = keydate & (keydate ^ Cnt);
	Cnt = keydate;
}

void KEY_proc()
{
	if(uwTick - key_tick < 10) return;
	key_tick = uwTick;
	KEY_Read();
	if(Tag & 0x01)
	{
		ui =! ui;
		LCD_Clear(White);
		if(Max_Volt>Min_Volt)
		{
			Max_Volt_Valid = Max_Volt;
			Min_Volt_Valid = Min_Volt;
		}
		else
		{
			Max_Volt = Max_Volt_Valid;
			Min_Volt = Min_Volt_Valid;
		}
		if(Led_Upper == Led_Lower)
		{
			Led_Upper = Led_Upper_Valid;
			Led_Lower = Led_Lower_Valid;
		}
		else
		{
			Led_Upper_Valid = Led_Upper;
			Led_Lower_Valid = Led_Lower;
		}
		Led_Ctrl = 0x00;
	}
	if(Tag & 0x02 && ui)
	{
		Key2_Cnt += 2;
		if(Key2_Cnt == 10)
			Key2_Cnt = 2;
	}
	if(Tag & 0x04 && ui)
	{
		if(Key2_Cnt == 2 && Max_Volt < 3.29f)
		{
			Max_Volt += 0.3f;
		}
		if(Key2_Cnt == 4 && Min_Volt < 3.29f)
		{
			Min_Volt += 0.3f;
		}
		if(Key2_Cnt == 6 && Led_Upper < 8)
		{
			Led_Upper ++;
		}
		if(Key2_Cnt == 8 && Led_Lower < 8)
		{
			Led_Lower ++;
		}
	}
	if(Tag & 0x08 && ui)
	{
		if(Key2_Cnt == 2 && Max_Volt > 0.01f)
		{
			Max_Volt -= 0.3f;
		}
		if(Key2_Cnt == 4 && Min_Volt > 0.01f)
		{
			Min_Volt -= 0.3f;
		}
		if(Key2_Cnt == 6 && Led_Upper > 1)
		{
			Led_Upper --;
		}
		if(Key2_Cnt == 8 && Led_Lower > 1)
		{
			Led_Lower --;
		}
	}
}

3、LCD模块

void LCD_proc()
{
	if(uwTick - lcd_tick < 100) return;
	lcd_tick = uwTick;
	u8 lcd_buff[20];
	if(ui == 0)
	{
		sprintf((char *)lcd_buff,"        Main   ");
		LCD_DisplayStringLine(Line1,lcd_buff);
		sprintf((char *)lcd_buff,"    Volt:%4.2fV   ",Volt);
		LCD_DisplayStringLine(Line4,lcd_buff);
		sprintf((char *)lcd_buff,"    Status:%s   ",Status);
		LCD_DisplayStringLine(Line6,lcd_buff);
	}
	else
	{
		sprintf((char *)lcd_buff,"       Setting  ");
		LCD_DisplayStringLine(Line1,lcd_buff);
		if(Key2_Cnt == 2)
		{
			LCD_SetBackColor(Green);
			sprintf((char *)lcd_buff,"   Max Volt:%3.1fV   ",Max_Volt);
			LCD_DisplayStringLine(Line2,lcd_buff);
			LCD_SetBackColor(White);
		}
		else
		{
			sprintf((char *)lcd_buff,"   Max Volt:%3.1fV   ",Max_Volt);
			LCD_DisplayStringLine(Line2,lcd_buff);
		}
		if(Key2_Cnt == 4)
		{
			LCD_SetBackColor(Green);
			sprintf((char *)lcd_buff,"   Min Volt:%3.1fV   ",Min_Volt);
			LCD_DisplayStringLine(Line4,lcd_buff);
			LCD_SetBackColor(White);
		}
		else
		{
			sprintf((char *)lcd_buff,"   Min Volt:%3.1fV   ",Min_Volt);
			LCD_DisplayStringLine(Line4,lcd_buff);
		}
		if(Key2_Cnt == 6)
		{
			LCD_SetBackColor(Green);
			sprintf((char *)lcd_buff,"   Upper:LD%d   ",Led_Upper);
			LCD_DisplayStringLine(Line6,lcd_buff);
			LCD_SetBackColor(White);
		}
		else
		{
			sprintf((char *)lcd_buff,"   Upper:LD%d   ",Led_Upper);
			LCD_DisplayStringLine(Line6,lcd_buff);
		}
		if(Key2_Cnt == 8)
		{
			LCD_SetBackColor(Green);
			sprintf((char *)lcd_buff,"   Lower:LD%d   ",Led_Lower);
			LCD_DisplayStringLine(Line8,lcd_buff);
			LCD_SetBackColor(White);
		}
		else
		{
			sprintf((char *)lcd_buff,"   Lower:LD%d   ",Led_Lower);
			LCD_DisplayStringLine(Line8,lcd_buff);
		}
	}
}

4、LED模块

void LED_proc()
{
	if(uwTick - LED_tick < 200) return;
	LED_tick = uwTick;
	if(Volt > Max_Volt_Valid)
	{
		Led_Ctrl ^= 0x01<<(Led_Upper_Valid - 1);
		Led_Ctrl &= ~(0x01<<(Led_Lower_Valid - 1));
		sprintf((char *)Status,"Upper");
	}
	else if(Volt < Min_Volt_Valid)
	{
		Led_Ctrl ^= 0x01<<(Led_Lower_Valid - 1);
		Led_Ctrl &= ~(0x01<<(Led_Upper_Valid - 1));
		sprintf((char *)Status,"Lower");
	}
	if(Volt > Min_Volt_Valid && Volt < Max_Volt_Valid)
	{
		Led_Ctrl = 0x00;
		sprintf((char *)Status,"Normal");
	}
	LED_Disp(Led_Ctrl);
}

5、ADC模块

void ADC_proc()
{
	HAL_ADC_Start(&hadc2);
	ADC_Value = HAL_ADC_GetValue(&hadc2);
	Volt = ADC_Value * 3.3f / 4095.0f;
}

6、主函数模块

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_ADC2_Init();
  /* USER CODE BEGIN 2 */

    LCD_Init();
	LED_Disp(0x00);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	
    LCD_Clear(White);
    LCD_SetBackColor(White);
    LCD_SetTextColor(Blue);

    while (1)
    {
		LCD_proc();
		KEY_proc();
		ADC_proc();
		LED_proc();
	
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    }
  /* USER CODE END 3 */
}

四、总结

本届题目我认为最难的地方在于B2的设置,被选择的参数项需要“高亮”显示,以及LED指示灯的功能,R37的输出电压分四种情况判断,其他功能还是比较简单实现的。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值