一、题目分析
开发板: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的输出电压分四种情况判断,其他功能还是比较简单实现的。