STM32定时器PWM波生成时计数自动重装载值无效问题的可能原因和解决

1. 问题说明

  在使用STM32G431RBT6芯片的开发板的时候,要实现在程序执行的过程中要改变产生PWM波的频率和占空比,需要调用的带参宏是

/* 
	该带参宏在文件 stm32gxx_hal_tim.h 中
	在 stm32_hal_legacy.h 中也有重定义该宏名为 __HAL_TIM_SetAutoreload
	二者都可以用
*/
#define __HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__)
#define __HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__)

当一开始初始化定时器TIM输出的PWM,可以正常输出波形。但是发现在后期自定义自动重装载数值后,波形消失了!

2. 问题原因

  经过多次测试,发现了这条自动重装载的语句使用的一条潜规则,那就是:第二个参数__AUTORELOAD__必须不可以为0,否则后期所有自动重装载无效!!!

__HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__)

如果出了这样问题的朋友,首先你先要确定你的定时器初始化没有问题,即当代码中没有添加重装载语句的情况下能够产生PWM波形,这是前提,否则就是定时器基本配置问题,不属于本文讨论范畴,本文主要是针对在定时器配置确认无误,初始化后可以产生PWM波的情况下,后期重装载后出现无波形的情况。
  那么如果定时器配置无误,那么请检查一下你需要重装载的频率变量定义,如你在main文件中以下方式在main函数上面声明,也就是声明了一个全局的频率变量Freq以供后期重装载,注意如果没有赋初值,那么在该位置声明的变量将默认为0

/* uint16_t 类型在stm32的固件库中有通过 typedef 进行定义,其原型为unsigned short int */
uint16_t Freq;

然后你后期进行自动重装载数值以重新控制输出PWM波的频率时(假设80MHz系统时钟经过80分频得到的定时器外设的时钟频率为1MHz,那么根据期望频率Freq得到需要重装载的数值就是1000000 / Freq),使用的语句是

__HAL_TIM_SET_AUTORELOAD(&htimx, 1000000 / Freq);

那么请一定检查一下整个代码的执行逻辑。你在一开始在全局区域声明该变量时,没有将其赋值或赋予其零值,那么该变量Freq都将初始化为0值。然后请你检查当程序每一次到上面这条自动重装载语句时,Freq变量都已经赋予其了非零值! 这是本文的核心,并且注意必须是每一次,每一次,每一次(尤其是程序刚开始第一次执行该语句的时候,通常在程序刚启动的一段时间,一些未赋值的全局参数都采集到相关数值而仍保持零值)!!! 一旦该程序在运行过程中在Freq为0值的情况下进入了该语句,那么C语言中有一个规定:任何整形变量除以0,结果为0!!!
在这里插入图片描述
那么就会回到本小节最前面的话,__AUTORELOAD__出现了值为0的输入,那么后续所有自动重装载作废,PWM再无输出!

3. 问题解决

  根据前面导致该问题的思路,有两种解决办法:

  1. 将前面代码中的1000000改为1000000.0,即将整形的立即数改为浮点型立即数,这是因为C语言中的又一个规定:即浮点型数字除以0,结果是0xFFFF(十六进制F的位数由赋值的变量的类型决定,8位就是0xFF,16位就是0xFFFF,32位就是0xFFFFFFFF)。如对于16位的数据,如下图所示,1000000.0 / 0在C语言中的执行结果为0xFFFF,那么该结果就不是0。 在这里插入图片描述
    这样就允许将0值的Freq变量代入1000000.0 / Freq的运算中,作为__AUTORELOAD__的值传入自动重转载宏中。
  2. 另一种方式就更加直截了当,就是索性在初始化Freq时就赋予其非0值,如
uint16_t Freq = 1000;		// 任何非零值均可,也可以根据程序需要赋予其它值,只要时非零值即可

同时保证程序运行中,Freq的重新赋值不会有0值即可。
  这个隐藏规则的问题确实非常搞心态,花了很长时间才调试出原因,希望对大家有所帮助~

  • 27
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值