本次实验使用的是蓝桥杯嵌入式大赛的指定开发板,STM32G431R8T6。
下面为 CubeMX 和代码部分
CubeMX定时器配置部分
选择对应引脚的通道设置为PWM输出模式(不要选择CH*N)。
以获取一个100Hz,占空比为50的脉冲信号,现在设置时钟频率为80MHz,参数设置中PSC,ARR需要我们自己配置(当然我们后期实现代码修改频率、占空比的时候会修改这些数据)。
公式1:脉冲频率 = (时钟频率)/ (PSC+1)/(ARR+1)
代入已知数据 100Hz = 80 000 000 / 8 000 / 100 ,求得 PSC = 8000 – 1 ARR = 100 – 1
公式2:占空比 = pulse / ARR
代入已知数据 50 = pulse / (100-1),求得pulse 约为 50
生成代码
pwm.c
#include "pwm.h"
/* PWM调节占空比、频率
* 参数:htim定时器,Channel定时器通道, freq设置对应的频率, duty设置对应的占空比
*/
void PWM_Set_freq_duty(TIM_HandleTypeDef htim, uint32_t Channel, uint32_t freq, uint32_t duty)
{
uint64_t tim_clk = 80000000;
uint32_t prescaler = 8000-1;
float arr = (tim_clk * 1.0) / freq / (prescaler+1) -1;
float pulse = duty * 1.0 / 100 * (arr+1);
/* 设置预分频值 */
__HAL_TIM_SET_PRESCALER(&htim, prescaler);
/* 设置自动重装载的值 */
__HAL_TIM_SetAutoreload(&htim, arr);
/* 设置占空比的值 */
__HAL_TIM_SetCompare(&htim, Channel, pulse);
}
/*
公式:脉冲频率 = (时钟频率)/ (PSC+1)/(ARR+1)
PSC = 8000-1 ARR = 100 – 1
*/
pwm.h
#ifndef __PWM_H_
#define __PWM_H_
#include "main.h"
void PWM_Set_freq_duty(TIM_HandleTypeDef htim, uint32_t Channel, uint32_t freq, uint32_t duty);
#endif
主函数功能验证部分
while (1)
{
if(keys[0].key_result == ONCE)
{
tim17_duty+=10;
if(tim17_duty>90) tim17_duty = 10;
PWM_Set_freq_duty(htim17, TIM_CHANNEL_1, tim17_freq, tim17_duty);
sprintf(lcd_string,"PA7 duty is %d ",tim17_duty);
LCD_DisplayStringLine(Line1, (unsigned char *)lcd_string);
keys[0].key_result = IDLE;
}
if(keys[1].key_result == ONCE)
{
tim16_freq+=10;
if(tim16_freq>120) tim16_freq = 40;
PWM_Set_freq_duty(htim16, TIM_CHANNEL_1, tim16_freq, tim16_duty);
sprintf(lcd_string,"PA6 freq is %d ",tim16_freq);
LCD_DisplayStringLine(Line2, (unsigned char *)lcd_string);
keys[1].key_result = IDLE;
}
}
注意在main函数开始时,我们还需要使能PWM输出:
/* 开启PWM两路输出 */
HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1); /* 使能后PWM就会输出,但是不可以改变频率和占空比 */
HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);