本文章只简述PWM功能和相关配置步骤
PWM是在通用定时器的基础上实现的一个功能,它是通过定时器计数和修改占空比来实现的。例如呼吸灯就是用PWM来实现。我们知道STM32中关于电信号只有高电平和低电平,那么我们怎么让电路实现一个类似于正弦状的电信号呢,PWM就是实现此类功能的。PWM是通过修改占空比来模拟出类似于正弦状的电信号,假如我们让我们的程序在运行中它的占空比是动态变化的,
我们就是类似于上图中那样通过占空比来实现电信号的波形。
PWM的相关配置步骤
TIM_HandleTypeDef g_timx_pwm_chy_handle;
/* 通用定时器PWM输出初始化函数 */
void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
{
TIM_OC_InitTypeDef timx_oc_pwm_chy;
g_timx_pwm_chy_handle.Instance = TIM3; //基地址
g_timx_pwm_chy_handle.Init.Prescaler = psc; //预分频系数
g_timx_pwm_chy_handle.Init.Period = arr; //自动重装载值
g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数
HAL_TIM_PWM_Init(&g_timx_pwm_chy_handle); //PWM初始化
timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1; //pwm模式一
timx_oc_pwm_chy.Pulse = arr / 2; //占空比为一半 设置CCRx的值
timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_LOW; //低电平有效
HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle, &timx_oc_pwm_chy, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, TIM_CHANNEL_2);
}
上面就是我们程序员要写的PWMinit函数的全部内容,其中包含了配置步骤中的134。
配置步骤第一步其实与基本定时器没有区别只是多了一个计数模式的配置,这里我选择的是向上计数。
剩下的是关于PWM的相关配置,首先是选择PWM模式1,之后设置初始占空比。以及低电平有效。
此图就是关于PWM模式一和模式二的区别,以模式一中的向上计数的低电平有效举例,我们通过看图易知此模式下,当计数值大于CCRX后我们输出高电平,低于则输出低电平,而我们就是通过修改CCRX来实现不同的占空比。
配置完后调用一下HAL_TIM_PWM_ConfigChannel()和HAL_TIM_PWM_Start()函数就完成了。
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_TIM3_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_5;
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOB, &gpio_init_struct);
__HAL_RCC_AFIO_CLK_ENABLE(); //打开重映射AFIO时钟
__HAL_AFIO_REMAP_TIM3_PARTIAL(); //TIM3部分重映射时钟使能
}
}
以上代码就是步骤二中的相关配置,这里我们用到了重映射功能,就是一个GPIO口实现多个功能
这里我们需要查看参考手册来寻找我们需要重映射的引脚,我们可以看到LED0是PB5对应TIM3通道二,这也是为什么我们要配置为通道二,因为这个是对应的。之后观看代码易知相关的时钟使能,我们记住即可,代码后面也有注释。
这里我们其实对PWM的配置已经完成了至于步骤5和6,步骤6没用上就不说了,步骤五的函数其实就是一个类似于直接能修改CCRx的函数,也就是直接修改占空比,我们可以在主函数中调用来实现。
int main(void)
{
uint16_t ledrpwmval = 0;
uint8_t dir = 1;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟,72M */
delay_init(72); /* 初始化延时函数 */
led_init(); /* 初始化LED */
gtim_timx_pwm_chy_init(500 - 1, 72 - 1);
while(1)
{
delay_ms(5);
if (dir)ledrpwmval++; /* dir==1 ledrpwmval递增 */
else ledrpwmval--; /* dir==0 ledrpwmval递减 */
if (ledrpwmval > 300)dir = 0; /* ledrpwmval到达300后,方向为递减 */
if (ledrpwmval == 0)dir = 1; /* ledrpwmval递减到0后,方向改为递增 */
/* 修改比较值控制占空比 */
__HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, TIM_CHANNEL_2, ledrpwmval);
}
}
以上就是主函数中的代码。可以看到通过调用__HAL_TIM_SET_COMPARE()函数来实现动态修改占空比。