问题来源:
最近使用BLDC硬件COM时间做硬件换向,手册中提到"预加载"机制,然后网上了解一下 ,然后发现一文章,观点总结如下:
本身我是接受这个观点的,但是我点开了评论区,就疑惑了
然后我决定试试:在实验之前,先搞清楚几个概念:定时器周期ARR值,更新事件发生时间点、修改周期值的时间点(这俩货很重要)、先产生更新事件,后进入更新中断。
实验前准备:
- 芯片STM32G431C8T6,使用TIM1,通道1。定时器主频170MHz,初始化预分频值设置为17000,周期值设置为50000,通道1比较值设置为10000,配置为PWM1模式。修改arr值统一修改为20000。
- 解释:定时器周期初始化为5s,修改时修改为2s。用PWM来观察定时器周期变化,便于用示波器测量周期和观察结果。
实验过程------1
板子上电,TIM1初始化,开启定时器。更新中断里修改AAR值为20000,观察示波器上PWM波的情况并测量周期值。
1. 不使能预加载,结果如下:
结果显示更新中断回调里设置ARR = 20000之后,中断回调程序结束,TIM1周期变为2s,也就是开头贴的博主所说的这一句:
2. 使能预加载,结果如下:
结果显示,在更新中断回调里更改ARR=20000,中断回调结束后依然是跑一个5s的周期之后,再变成2s,这里的结果也就对应这一句话:
总结:
为了防止语言歧义,我定义中断回调程序结束后的TIM跑的周期称为下一个周期。目前来看,原博主的总结是对的。
但是但是!!!!!!!!其实问题的关键根本不是在不在更新中断里修改ARR值**
- 1.对于重装载寄存器的预加载来说,关键在于改变ARR的时间点和当前定时器的时间点(定时器的计数值)
- 2.对于比较寄存器的预加载来说,关键在于改变比较值的时间点和当前定时器的时间点(定时器的计数值)
实验过程------2
接着验证,现在我把修改ARR的地方由更新中断里变成主循环之前,定时器初始化条件不变。
1.预加载使能,同时修改值 > 定时器当前计数值
使能预加载的情况下,开启通道后紧接着修改ARR值为20000,这时TIM1的计数值还没有跑到20000(定时器计数很慢)
结果为:
结果显示,开启预加载情况下,修改ARR的值,跑完初始化设定的5s,在下一个周期变为2s。
2.预加载使能,同时修改值 < 定时器当前计数值
在保证定时器计数已经超过25000的情况下,紧接着设置周期值为20000(程序我验证过,不存在已经跑过一个tim周期的情况存在),结果如下:
结果依然是在当前周期不生效,在下一个周期生效。所以在使能了预加载的情况在,生效时间永远是在发生更新事件后的下一个周期(手册也描述了,更新事件后才载入工作寄存器),而不论你更改ARR的时间点在哪里。
3.预加载失能,同时修改值 > 定时器当前计数值
结果如下:
结果显示,修改值立刻生效,这里先不下结论,先看最后一个实验
4. 预加载失能,同时修改值 < 定时器当前计数值
结果如下:
结果显示,第一个周期跑到了TIM1计数器的最大值(65535,示波器没那么精确),既不是50000,也不是20000。
终极结论:
1. 首先不要纠结于下个周期生效还是下下个周期生效这种模糊的说法,直接忘掉OK?
2. 使能重装载寄存器预加载的情况下,不论修改ARR值的时间点在哪,结果都是在修改之后,更新事件发生后的下一周期生效。
3. 在不使能预加载的情况下,其实生效机制就是立刻生效,但是要注意:
1)修改值小于当前定时器的计数值(就是定时器已经跑过了这个修改点),修改后,本次周期会跑到该定时器的最大周期值(16位就是0xFFFF,32位就是0xFFFFFFFF)
2)修改值大于当前定时器的计数值(就是定时器还未跑过修改点),修改后,立刻生效,本次定时器周期就会变成修改值。
4.由于我比较关注的是比较通道的预加载,所以同样也做了实验,这里就不贴出来了,结果是一样的,依然是这个逻辑。
最后再叨叨两句:
回头看博主的话:
虽然我理解他的意思但是这种表述真的是很模糊的,在定时器更新中断回调里修改ARR,和在其他地方修改ARR两种情况所说的下一个定时器周期是一个概念吗?什么是下一个?什么是下下个?所以希望大家避免这种表述方式;