第七届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)
一.题目分析
(1).题目
(2).题目分析
1.按键功能分析
a.B1按下一次进入设定页面,再次按下退出设置页面同时保存设定
b.B2按下高亮选择三个待修改的阈值
c.增加阈值,每次增加5cm直到95cm
d.减少阈值,每次减少5cm直到5cm
2.输出分析
a.将上一次的数据缓存
b.判断这一次调整的等级与上一次是否一致
c.按题目所给的输出数据格式上报串口
(3).逻辑导图
二.CubeMX配置
由于蓝桥杯使用的板子都是STM32G431RBT6,配置都是相同的,模板已经在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客配置完成,大家可以前往学习
三.相关代码实现
(1)MAIN
1.全局变量声明
//*减速变量
__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的执行速度
__IO uint32_t uwTick_Data_Set_Point = 0;//控制Data_Collect_Proc的执行速度
//*按键扫描专用变量
uint8_t ucKey_Val, unKey_Down, ucKey_Up, ucKey_Old;
//*LED专用变量
uint8_t ucLed;
//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符
//*串口专用变量
uint16_t counter = 0;
uint8_t str[40];
uint8_t rx_buffer;
//全局变量
uint8_t Interface_Num;//00-首界面,10-设置第一个阈值,11-设置第二个阈值,12-设置第三个阈值
float SUM_AD_R37;//求AD采集十次的数值的和
float AVE_AD_R37;//AD采集的平均值
uint8_t AD_Ctrl_Num;//AD控制采集次数的变量
uint8_t Height;//液位高度数值
uint8_t Level;//液面等级
uint8_t Level_Old;//液面等级,上一次的
uint8_t Compare_Level_Disp[3] = {30, 50, 70};//阈值初值
uint8_t Compare_Level_Ctrl[3] = {30, 50, 70};//阈值初值
_Bool Level_Change_Flag;//1-变化
uint8_t Buling_Times = 10;//变化次数为闪灭各5次
_Bool Uart_Get_Data;//1-变化
uint8_t Buling_Times_Uart = 10;//变化次数为闪灭各5次
//***子函数声明区
void Key_Proc(void);
void Led_Proc(void);
void Lcd_Proc(void);
void Usart_Proc(void);
void Data_Collect_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);
UART1_Init();
I2CInit();
ADC2_Init();
/*外设使用基本配置*/
//*EEPROM测试
iic_24c02_read(Compare_Level_Ctrl, 0, 3);
Compare_Level_Disp[0] = Compare_Level_Ctrl[0];
Compare_Level_Disp[1] = Compare_Level_Ctrl[1];
Compare_Level_Disp[2] = Compare_Level_Ctrl[2];
HAL_UART_Receive_IT(&huart1, (uint8_t *)(&rx_buffer), 1);
while (1)
{
Data_Collect_Proc();
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(unKey_Down == 1)
{
if(Interface_Num == 0x00)
{
Interface_Num = 0x10;
LCD_Clear(White);
}
else
{
if((Compare_Level_Disp[0] < Compare_Level_Disp[1])&&(Compare_Level_Disp[1] < Compare_Level_Disp[2]))
{
Interface_Num = 0x00;
LCD_Clear(White);
iic_24c02_write(Compare_Level_Disp, 0, 3);
Compare_Level_Ctrl[0]= Compare_Level_Disp[0];
Compare_Level_Ctrl[1]= Compare_Level_Disp[1];
Compare_Level_Ctrl[2]= Compare_Level_Disp[2];
}
else
{
sprintf((char *)Lcd_Disp_String, " DATA ERROR");
LCD_SetTextColor(Red);
LCD_DisplayStringLine(Line0, Lcd_Disp_String);
LCD_SetTextColor(Blue);
}
}
}
if(unKey_Down == 2)
{
if((Interface_Num >> 4) == 0x1)
{
if(++Interface_Num == 0x13)
Interface_Num = 0x10;
}
}
if(unKey_Down == 3)//+
{
if(Interface_Num == 0x10)
{
Compare_Level_Disp[0] += 5;
if(Compare_Level_Disp[0] >= 100) Compare_Level_Disp[0] = 95;
}
if(Interface_Num == 0x11)
{
Compare_Level_Disp[1] += 5;
if(Compare_Level_Disp[1] >= 100) Compare_Level_Disp[1] = 95;
}
if(Interface_Num == 0x12)
{
Compare_Level_Disp[2] += 5;
if(Compare_Level_Disp[2] >= 100) Compare_Level_Disp[2] = 95;
}
}
if(unKey_Down == 4)//-
{
if(Interface_Num == 0x10)
{
Compare_Level_Disp[0] -= 5;
if(Compare_Level_Disp[0] == 0) Compare_Level_Disp[0] = 5;
}
if(Interface_Num == 0x11)
{
Compare_Level_Disp[1] -= 5;
if(Compare_Level_Disp[1] == 0) Compare_Level_Disp[1] = 5;
}
if(Interface_Num == 0x12)
{
Compare_Level_Disp[2] -= 5;
if(Compare_Level_Disp[2] == 0) Compare_Level_Disp[2] = 5;
}
}
LED扫描子函数
a.逻辑框图
b.程序源码
void Led_Proc(void)
{
if((uwTick - uwTick_Led_Set_Point)<200) return;//减速函数
uwTick_Led_Set_Point = uwTick;
if(Level_Change_Flag == 1)
{
if(Buling_Times--)
ucLed ^= 0x02;
if(Buling_Times == 0)
{
Level_Change_Flag = 0;
Buling_Times = 10;
ucLed = 0;
}
}
if(Uart_Get_Data == 1)
{
if(Buling_Times_Uart--)
ucLed ^= 0x04;
if(Buling_Times_Uart == 0)
{
Uart_Get_Data = 0;
Buling_Times_Uart = 10;
ucLed = 0;
}
}
LED_Disp(ucLed);
}
数据收集子函数
a.逻辑框图
b.程序源码
void Data_Collect_Proc(void)
{
if((uwTick - uwTick_Data_Set_Point)<1000) return;//减速函数
uwTick_Data_Set_Point = uwTick;
//中值滤波处理
for( AD_Ctrl_Num = 0;AD_Ctrl_Num <= 9; AD_Ctrl_Num++)
{
// SUM_AD_R37 += ((((float)getADC2())/4096)*3.3);
SUM_AD_R37 += ((float)getADC2());
}
SUM_AD_R37 /= 4096;
SUM_AD_R37 *= 3.3;
AVE_AD_R37 = SUM_AD_R37/10;
SUM_AD_R37 = 0;
// AVE_AD_R37 = ((((float)getADC2())/4096)*3.3);
Height = (uint8_t)(AVE_AD_R37*30.3);
Level_Old = Level;
if(Height <= Compare_Level_Ctrl[0])
Level = 0;
if((Height <= Compare_Level_Ctrl[1])&&(Height > Compare_Level_Ctrl[0]))
Level = 1;
if((Height <= Compare_Level_Ctrl[2])&&(Height > Compare_Level_Ctrl[1]))
Level = 2;
if(Height > Compare_Level_Ctrl[2])
Level = 3;
if(Level > Level_Old)
{
sprintf(str, "A:H%3d+L%1d+U\r\n",(unsigned int)Height,(unsigned int)Level);
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);
Level_Change_Flag = 1;
}
else if(Level < Level_Old)
{
sprintf(str, "A:H%3d+L%1d+D\r\n",(unsigned int)Height,(unsigned int)Level);
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);
Level_Change_Flag = 1;
}
ucLed ^= 0x1;//让LD1翻滚变化
}
LCD显示子函数
a.逻辑框图
b.程序源码
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<100) return;//减速函数
uwTick_Lcd_Set_Point = uwTick;
if(Interface_Num == 0x00)
{
LCD_SetBackColor(White);
sprintf((char *)Lcd_Disp_String, " Liquid Level");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Height:%3dcm",(unsigned int)Height);
LCD_DisplayStringLine(Line3, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " ADC:%4.2fV",AVE_AD_R37);
LCD_DisplayStringLine(Line5, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Level:%1d",Level);
LCD_DisplayStringLine(Line7, Lcd_Disp_String);
}
else if((Interface_Num>>4) == 0x1)
{
sprintf((char *)Lcd_Disp_String, " Parameter Setup");
LCD_SetBackColor(White);
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Threshold 1: %2dcm ",(unsigned int)Compare_Level_Disp[0]);
if(Interface_Num == 0x10)
LCD_SetBackColor(Yellow);
else
LCD_SetBackColor(White);
LCD_DisplayStringLine(Line3, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Threshold 2: %2dcm ",(unsigned int)Compare_Level_Disp[1]);
if(Interface_Num == 0x11)
LCD_SetBackColor(Yellow);
else
LCD_SetBackColor(White);
LCD_DisplayStringLine(Line5, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " Threshold 3: %2dcm ",(unsigned int)Compare_Level_Disp[2]);
if(Interface_Num == 0x12)
LCD_SetBackColor(Yellow);
else
LCD_SetBackColor(White);
LCD_DisplayStringLine(Line7, Lcd_Disp_String);
}
串口扫描子函数
a. 程序源码
void Usart_Proc(void)
{
if((uwTick - uwTick_Usart_Set_Point)<1000) return;//减速函数
uwTick_Usart_Set_Point = uwTick;
}
串口接收中断回调函数
a.逻辑框图
b.程序源码
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(rx_buffer == 'C')
{
Uart_Get_Data = 1;
sprintf(str, "C:H%3d+L%1d\r\n",(unsigned int)Height,(unsigned int)Level);
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);
}
else if(rx_buffer == 'S')
{
Uart_Get_Data = 1;
sprintf(str, "S:TL%2d+TM%2d+TH%2d\r\n",(unsigned int)Compare_Level_Ctrl[0],(unsigned int)Compare_Level_Ctrl[1],(unsigned int)Compare_Level_Ctrl[2]);
HAL_UART_Transmit(&huart1,(unsigned char *)str, strlen(str), 50);
}
HAL_UART_Receive_IT(&huart1, (uint8_t *)(&rx_buffer), 1);
}
(2)BSP
在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习