STM32PWM--基于HAL库(第十三届蓝桥杯嵌入式模拟题)
文章目录
- 前言
- 一、CubeMX配置(第十三届模拟题完整版)
- 二、代码相关定义、声明
-
- 1.函数声明
- 2.宏定义
- 3.变量定义
- 三、主要函数
-
- 1.按键扫描
- 2.配置模式
- 3.LCD显示
- 4.频率检测(TIM2输入捕获中断函数)
- 5.PWM输出(TIM3)
- 6.Main函数
- 四、实验结果
-
- 1.输入频率检测
- 2.R值
- 3.输出频率
- 五、源码(转载请注明出处)
- 总结
前言
相关说明:
开发板:CT117E-M4(STM32G431RB 蓝桥杯嵌入式比赛板)
开发环境: CubeMX+Keil5
涉及题目:第十三届蓝桥杯嵌入式模拟题
题目难点:根据输入的PWM,实时更新输出PWM
CubeMX配置、主要函数代码及说明:
一、CubeMX配置(第十三届模拟题完整版)
1.使能外部高速时钟:
2.配置时钟树:
3.GPIO:
4.ADC(默认配置即可):
5.TIM2(输入捕获,检测输入信号的频率):
6.TIM3(PWM输出):
7.NVIC(输入捕获中断配置):
二、代码相关定义、声明
1.函数声明
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim);//输入捕获回调函数void Get_Adc(void); //获取ADC的值void Function_Mode_Change(void);//模式改变void Setting_Mode(void);//配置模式void KEY_Scan(void);//按键扫描void LCD_Show(void);//LCD显示void LED_CloseAll(void);//关闭所有LEDvoid LED_Mode_Change(vod);//LED禁用改变void LED_Show(void);//LED状态改变void PWM_Output(void);//PWM输出配置
2.宏定义
#define LED_GPIO_PORTGPIOC#define LED1_GPIO_PINGPIO_PIN_8#define LED2_GPIO_PINGPIO_PIN_9#define LED3_GPIO_PINGPIO_PIN_10#define LED4_GPIO_PINGPIO_PIN_11#define LED5_GPIO_PINGPIO_PIN_12#define LED6_GPIO_PINGPIO_PIN_13#define LED7_GPIO_PINGPIO_PIN_14#define LED8_GPIO_PINGPIO_PIN_15#define ON GPIO_PIN_RESET#define OFF GPIO_PIN_SET#define LED1(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED1_GPIO_PIN,a)#define LED2(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED2_GPIO_PIN,a)#define LED3(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED3_GPIO_PIN,a)#define LED4(a) HAL_GPIO_WritePin(LED_GPIO_PORT,LED4_GPIO_PIN,a)#define KEY1_GPIO_PORTGPIOB#define KEY1_GPIO_PINGPIO_PIN_0#define KEY2_GPIO_PORTGPIOB#define KEY2_GPIO_PINGPIO_PIN_1#define KEY3_GPIO_PORTGPIOB#define KEY3_GPIO_PINGPIO_PIN_2#define KEY4_GPIO_PORTGPIOA#define KEY4_GPIO_PINGPIO_PIN_0
3.变量定义
uint8_t LCD_show=0;//决定为数据显示(0)还是参数设置(1) 控制LCD显示uint8_t LED_change=0;//LCD_show标志位改变则为1 控制LED状态转变uint8_t R=4;//参数Ruint8_t R_step=2;//R每次改变值uint8_t R_min=2;//R值下限uint8_t R_max=10;//R值上限uint8_t R_change=1;//R更改标志位double R37_v;//R37的电压值double V_max=3.3;//电压上限值uint32_t Tim_clock=1000000;//Tim时钟频率 1MHzuint32_t In_Hz;//输入信号频率uint32_t In_Hz_old;//上一次输入信号频率uint32_t Out_Hz;//PWM输出信号频率TIM_OC_InitTypeDef sConfigOC={0};//用于配置Pulseuint8_t LED_ban=0;//LED禁用标志位char str[33]; //用于sprintf组合字符串
三、主要函数
1.按键扫描
void KEY_Scan(){//KEY1 Press 界面切换(数据显示参数设置)if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET);Function_Mode_Change();//模式改变LCD_Show();//LCD更新LED_change=1;//改变标志位置1LED_Show();//LED更新Setting_Mode();//进入配置模式}}//KEY4 Press LED(控制是否禁用LED)else if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET);LED_Mode_Change();//禁用/启用 LEDLED_change=1;//改变标志位置1LED_Show();//更新显示}}}
2.配置模式
void Setting_Mode(){while(1){//KEY1 Press 界面切换(数据显示参数设置)if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY1_GPIO_PORT,KEY1_GPIO_PIN)==GPIO_PIN_RESET);Function_Mode_Change();//模式改变R_change=1;//默认为更改LCD_Show();//LCD更新LED_change=1;//改变标志位置1LED_Show();//LED更新break;//退出配置模式}}//KEY2 Press ++(每次按下R参数增加2)else if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY2_GPIO_PORT,KEY2_GPIO_PIN)==GPIO_PIN_RESET);R+=R_step;//R增加if(R>R_max)R=R_max;//范围为2~10R_change=1;//R更改标志位置1LCD_Show();//更新显示}}//KEY3 Press --(每次按下R参数减少2)else if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY3_GPIO_PORT,KEY3_GPIO_PIN)==GPIO_PIN_RESET);R-=R_step;//R减小if(R<R_min)R=R_min;//范围为2~10R_change=1;//R更改标志位置1LCD_Show();//更新显示}}//KEY4 Press LED(控制是否禁用LED)else if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){HAL_Delay(10);if(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET){while(HAL_GPIO_ReadPin(KEY4_GPIO_PORT,KEY4_GPIO_PIN)==GPIO_PIN_RESET);LED_Mode_Change();//禁用/启用 LEDLED_change=1;//改变标志位置1LED_Show();//更新显示}}}//while}
3.LCD显示
void LCD_Show(){if(LCD_show==0){LCD_DisplayStringLine(Line1,(unsigned char *)"Data ");sprintf(str," FRQ:%dHz ",In_Hz);LCD_DisplayStringLine(Line3,(unsigned char *)str);//FRQPWM_Output();//根据输入频率以及R值动态输出PWMIn_Hz=0;Get_Adc();//获取ADC的值sprintf(str," R37:%.2fV ",R37_v);LCD_DisplayStringLine(Line5,(unsigned char *)str);//R37LED_change=1;//受到LCD干扰 LED更新显示LED_Show();HAL_Delay(50);}else if(LCD_show==1 && R_change){R_change=0;LCD_DisplayStringLine(Line1,(unsigned char *)"Para ");sprintf(str," R:%d ",R);LCD_DisplayStringLine(Line3,(unsigned char *)str);//RLCD_DisplayStringLine(Line5,(unsigned char *)" ");HAL_Delay(50);}}
4.频率检测(TIM2输入捕获中断函数)
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//测量频率{uint32_t count;count=__HAL_TIM_GET_COUNTER(&htim2);;//获取定时器计数值In_Hz=Tim_clock/count;//外部输入信号频率TIM2->CNT=0;//PWM_Output();}
5.PWM输出(TIM3)
void PWM_Output(){HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_2);//关闭PWM/* 配置PWM输出频率 */ Out_Hz=In_Hz/R;//In_Hz的值为输入频率 分频则将该频率再/Rhtim3.Init.Prescaler = 80-1;//分频值htim3.Init.Period = Tim_clock/Out_Hz-1;//计数值配置/* 配置PWM占空比 *///R37_v=((int)(R37_v*100))*0.01;//过滤(保留小数点后两位,避免电流干扰)sConfigOC.Pulse = R37_v/3.3*Tim_clock/Out_Hz-1;//测得电压值/3.3*计数值HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);HAL_TIM_PWM_Init(&htim3);//重新初始化HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);//开启PWM}
6.Main函数
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(); MX_TIM2_Init(); MX_TIM3_Init(); /* USER CODE BEGIN 2 */LCD_Init();//LCD初始化HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);//输入捕获准备工作HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);//PWM参数配置sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) ;HAL_TIM_PWM_Init(&htim3);HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);//启动PWM /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */LCD_Clear(Black);LCD_SetBackColor(Black);LCD_SetTextColor(White);LCD_DisplayStringLine(Line0,(unsigned char *)" ");LCD_DisplayStringLine(Line2,(unsigned char *)" ");LCD_DisplayStringLine(Line4,(unsigned char *)" ");LCD_DisplayStringLine(Line6,(unsigned char *)" ");LCD_DisplayStringLine(Line7,(unsigned char *)" ");LCD_DisplayStringLine(Line8,(unsigned char *)" ");LCD_DisplayStringLine(Line9,(unsigned char *)" "); while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */KEY_Scan();//按键扫描LCD_Show();//LCD更新信息LED_Show();//LED状态改变 } /* USER CODE END 3 */}
四、实验结果
1.输入频率检测
此处用的是另一块开发板为该板提供信号,频率为1KHz;并调节R37使其电压为1.65V,预期占空比为1.65/3.3=50%。
2.R值
默认R值为4,作用为将输入信号进行分频处理;预期输出频率为1K/4=250Hz。
3.输出频率
这里直接用示波器检测输出PWM,频率为250Hz,占空比为50%,符合预期。
五、源码(转载请注明出处)
总结
以上就是全部内容,如有错误请批评指正。