一.题目分析
(1).题目
(2).题目分析
1.按键功能分析
a.B1界面切换
b.B2每次按下R加2
c.B3每次按下R减2
d.LED控制按键
2.信号输出功能分析
a.PA7信号输出-----信号的输出就需要使用到输入捕获和输出比较功能
b.输出信号的频率为输入信号频率的R分频
c.输出信号占空比和检测到的R37成正比
(当前电压值/3.3V)*周期 = 占空比
(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 = 0x01;
//*LCD显示专用变量
uint8_t Lcd_Disp_String[21];//最多显示20个字符
//*pwm相关变量
uint16_t PWM_T_Count;
//*主逻辑使用变量
uint8_t Disp_Screen_Num;//0-数据,1-参数
uint8_t R_Freq = 4;//分频值,初试为4
uint16_t ADC_Voltage_X100;
uint16_t Frq;
uint8_t LED_Func = 1;//1-启用,0-禁用
uint32_t AUTORELOAD_Num;
uint32_t COMPARE_Num;
//***子函数声明区
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_INPUT_TIM2_Init();
PWM_OUTPUT_TIM17_Init();
//*输入捕获PWM启动
HAL_TIM_Base_Start(&htim2); /* 启动定时器 */
HAL_TIM_IC_Start_IT(&htim2,TIM_CHANNEL_2);
//PA7黄色
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, 500);//没有波形输出
__HAL_TIM_SET_AUTORELOAD(&htim17, 4999); //200HZ
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;
if(unKey_Down == 1)//完成界面的切换
{
Disp_Screen_Num ^= 0x01;
LCD_Clear(Black);
if(Disp_Screen_Num == 0x00)//数据界面LD1点亮
{
ucLed &= (~0x03);
ucLed |= 0x01;
}
else if(Disp_Screen_Num == 0x01)//参数界面LD2点亮
{
ucLed &= (~0x03);
ucLed |= 0x02;
}
}
if(Disp_Screen_Num == 0x01)//在参数设置界面的时候,才可以加减
{
if(unKey_Down == 2)//+2功能
{
R_Freq += 2;
if(R_Freq > 10)
R_Freq = 10;
}
if(unKey_Down == 3)//-2功能
{
R_Freq -= 2;
if(R_Freq < 2)
R_Freq = 2;
}
}
if(unKey_Down == 4)//LED启用和停用功能
{
LED_Func ^= 0x01;
}
}
4.LED扫描子函数
a. 程序源码
void Led_Proc(void)
{
if((uwTick - uwTick_Led_Set_Point)<200) return;//减速函数
uwTick_Led_Set_Point = uwTick;
if(LED_Func == 0x01)
LED_Disp(ucLed);
else if(LED_Func == 0x00)
LED_Disp(0x00);
}
5.LCD扫描子函数
a. 逻辑框图
b. 程序源码
void Lcd_Proc(void)
{
if((uwTick - uwTick_Lcd_Set_Point)<100) return;//减速函数
uwTick_Lcd_Set_Point = uwTick;
ADC_Voltage_X100 = ((((float)getADC2())/4096)*330);
Frq = (1000000/PWM_T_Count);
//控制LED灯的变化
if((ADC_Voltage_X100<100)||(ADC_Voltage_X100>=300))
{
ucLed |= 0x04;
}
else
ucLed &= (~0x04);
if((Frq<1000)||(Frq>=5000))
{
ucLed |= 0x08;
}
else
ucLed &= (~0x08);
//控制输出PWM的变化
//AUTORELOAD_Num = 6289;
AUTORELOAD_Num = (1000000.0/(Frq/R_Freq));
COMPARE_Num = (((330-ADC_Voltage_X100)/330.0)*AUTORELOAD_Num); //求助各位大佬?究竟为什么?如果您告诉我,我以您的名义,补充录制一段,单独解释这个地方。
//完成频率的设置
__HAL_TIM_SET_AUTORELOAD(&htim17, AUTORELOAD_Num);
//完成占空比的设置
__HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, COMPARE_Num);
if(Disp_Screen_Num == 0)//显示数据
{
sprintf((char *)Lcd_Disp_String, " Data ");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " FRQ:%dHz ",(unsigned int)Frq);
LCD_DisplayStringLine(Line3, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " R37:%4.2fV ",(ADC_Voltage_X100*0.01));
LCD_DisplayStringLine(Line5, Lcd_Disp_String);
}
else if(Disp_Screen_Num == 1)//显示参数
{
sprintf((char *)Lcd_Disp_String, " Para ");
LCD_DisplayStringLine(Line1, Lcd_Disp_String);
sprintf((char *)Lcd_Disp_String, " R:%2d",(unsigned int)R_Freq);
LCD_DisplayStringLine(Line3, Lcd_Disp_String);
}
}
5.输入捕获PWM中断回调
a. 程序源码
//输入捕获PWM中断回调
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
PWM_T_Count = HAL_TIM_ReadCapturedValue(htim,TIM_CHANNEL_2)+1;
}
}
}
(2)BSP
在第六届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)-CSDN博客里面有详细的讲解,大家可前往此链接学习