一.题目分析
(1).题目
(2).题目分析
1..按键功能分析
a. B1界面切换
b. B2每次按下,PA6手动模式占空比参数增加10%
c. B3每次按下,PA7手动模式占空比参数增加10%
d. B4模式切换
f. 在数据显示界面下每次按下B3按键,互换PA6和PA7输出脉冲信号频率
(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 "ADC\bsp_adc.h"
#include "TIM\bsp_tim.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;
//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符
//全局变量
_Bool Lcd_Show_State;//0- 数据界面,1- 参数界面
uint8_t PWM_Running_State = 2;
float R37_Voltage;
uint8_t PA6_Duty_Int = 10;
uint8_t PA7_Duty_Int = 10;
//***子函数声明区
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(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
ADC2_Init();
PWM_OUTPUT_TIM3_Init();
PWM_OUTPUT_TIM17_Init();
//PA6绿色
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 1000);
__HAL_TIM_SET_AUTORELOAD(&htim3, 9999);
//PA7黄色
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, 500);
__HAL_TIM_SET_AUTORELOAD(&htim17, 4999);
//*启动定时器3和定时器17通道输出
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); //PA6
HAL_TIM_PWM_Start(&htim17,TIM_CHANNEL_1); //PA7
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
Lcd_Show_State ^= 1;
LCD_Clear(Black);
break;
case 2://B2
if(Lcd_Show_State == 1)//当处于参数界面
{
PA6_Duty_Int += 10;
if(PA6_Duty_Int == 100) PA6_Duty_Int = 10;
}
break;
case 3://B3 //0- 数据界面,1- 参数界面
if(Lcd_Show_State == 0)//当处于数据界面
{
if(PWM_Running_State == 0) PWM_Running_State = 1;
else if(PWM_Running_State == 1) PWM_Running_State = 0;
else if(PWM_Running_State == 2) PWM_Running_State = 3;
else if(PWM_Running_State == 3) PWM_Running_State = 2;
}
if(Lcd_Show_State == 1)//当处于参数界面
{
PA7_Duty_Int += 10;
if(PA7_Duty_Int == 100) PA7_Duty_Int = 10;
}
break;
case 4://B4
if(PWM_Running_State == 0) PWM_Running_State = 2;
else if(PWM_Running_State == 2) PWM_Running_State = 0;
else if(PWM_Running_State == 1) PWM_Running_State = 3;
else if(PWM_Running_State == 3) PWM_Running_State = 1;
break;
}
3.LED扫描子函数
a.逻辑框图
b.程序源码
//***LED扫描子函数
void Led_Proc(void)
{
if((uwTick - uwTick_Led_Set_Point)<200) return;//减速函数
uwTick_Led_Set_Point = uwTick;
if(PWM_Running_State >= 2)//自动模式
{
ucLed |= 0x01;//LD1点亮
}
else //手动模式
{
ucLed &= (~0x01);//LD1熄灭
}
if(Lcd_Show_State)//参数界面
{
ucLed &= (~0x02);//LD2熄灭
}
else//数据界面
{
ucLed |= 0x02;//LD2点亮
}
LED_Disp(ucLed);
}
3.LCD扫描子函数
a.逻辑框图
b.程序源码
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<100) return;//减速函数
uwTick_Lcd_Set_Point = uwTick;
//数据采集区
R37_Voltage = ((((float)getADC2())/4096)*3.3);
//我的显示
if(Lcd_Show_State == 0)//数据界面
{
sprintf((char *)Lcd_Disp_String, " Data");
LCD_DisplayStringLine(Line0, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " V:%4.2fV",R37_Voltage);
LCD_DisplayStringLine(Line2, Lcd_Disp_String);
if(PWM_Running_State <= 1)
{
sprintf((char *)Lcd_Disp_String, " Mode:MANU");
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
}
else
{
sprintf((char *)Lcd_Disp_String, " Mode:AUTO");
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
}
}
else //参数界面
{
sprintf((char *)Lcd_Disp_String, " Para");
LCD_DisplayStringLine(Line0, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " PA6:%02d%%",(unsigned int)PA6_Duty_Int);
LCD_DisplayStringLine(Line2, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " PA7:%02d%%",(unsigned int)PA7_Duty_Int);
LCD_DisplayStringLine(Line4, Lcd_Disp_String);
}
//数据输出区
switch(PWM_Running_State)
{
case 0:
__HAL_TIM_SET_AUTORELOAD(&htim3, 9999); //PA6(绿色)的频率为100hz
__HAL_TIM_SET_AUTORELOAD(&htim17, 4999);//PA7(黄色)的频率为200hz
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (100*PA6_Duty_Int));//PA6(绿色)的占空比跟随设置
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, (50*PA7_Duty_Int));//PA7(黄色)的占空比跟随设置
break;
case 1:
__HAL_TIM_SET_AUTORELOAD(&htim3, 4999); //PA6(绿色)的频率为200hz
__HAL_TIM_SET_AUTORELOAD(&htim17, 9999);//PA7(黄色)的频率为100hz
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (50*PA6_Duty_Int));//PA6(绿色)的占空比跟随设置
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, (100*PA7_Duty_Int));//PA7(黄色)的占空比跟随设置
break;
case 2:
__HAL_TIM_SET_AUTORELOAD(&htim3, 9999); //PA6(绿色)的频率为100hz
__HAL_TIM_SET_AUTORELOAD(&htim17, 4999);//PA7(黄色)的频率为200hz
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (unsigned int)(10000*(R37_Voltage/3.3)));//PA6(绿色)的占空比跟随设置
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, (unsigned int)(5000*(R37_Voltage/3.3)));//PA7(黄色)的占空比跟随设置
break;
case 3:
__HAL_TIM_SET_AUTORELOAD(&htim3, 4999); //PA6(绿色)的频率为200hz
__HAL_TIM_SET_AUTORELOAD(&htim17, 9999);//PA7(黄色)的频率为100hz
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, (unsigned int)(5000*(R37_Voltage/3.3)));//PA6(绿色)的占空比跟随设置
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, (unsigned int)(10000*(R37_Voltage/3.3)));//PA7(黄色)的占空比跟随设置
break;
}
}
(2)BSP
在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习