新闻| 文章| 资讯| 行情| 企业| wap手机版| article文章| 首页|会员中心|保存桌面|手机浏览
普通会员

易达信息科技

企业列表
新闻列表
推荐企业新闻
联系方式
  • 联系人:依依
友情链接
  • 暂无链接
首页 > 新闻中心 > STM32基础分析——PWM配置
新闻中心
STM32基础分析——PWM配置
发布时间:2024-11-12        浏览次数:2        返回列表

在使用STM32F103产生固定频率、固定占空比的PWM波时,虽然有官方以及众多开发板提供的例程,但是关于有点问题并没有说的很清晰,并且《STM32F10X参考手册》的中文翻译可能容易造成歧义,所以一开始并没有理解,这里就梳理一下我的理解,如果有误解的情况,希望交流指正。

STM32基础分析——PWM配置

先直接上段配置代码,这段代码是产生一个20kHz固定频率,50%固定占空比的方波信号,典型的配置过程,一般来说也不会有什么太多的疑问。但是我逐步了解背后的定时器工作逻辑的时候,就产生了一些疑问,也没有找到合理、清晰的解答。先说明一下,只有通用定时器和高级定时器才有PWM模式,基本定时器没有。



代码中有这样一条,有人会问函数和函数有什么区别?其实重点在Flag和IT,前者是外设的状态标志,而后者是外设的中断标志。状态标志就是一个外设它有自身的一些标志位(Flag),来表明它处于什么状态,下图就是定时器的状态标记。中断标志就是使能外设的中断后,每次发生一次中断,它会表明发生了什么样的中断,同样中断也有相应的标记。两者分别靠函数和函数来获取。

没有使能中断时,是可以读取该外设的状态标志的。同理,串口外设也有此区别。


模式1

在向上计数时,一旦TIMx_CNT < TIMx_CCR1时通道1为有效电平,否则为无效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。

模式2

在向上计数时,一旦TIMx_CNT < TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。

实际上可以看到,模式1和模式2并无本质的区别,只是在同样的有效电平情况下,输出的波形电平相反而已。那么什么又是有效电平?后面有机会单独说明。


这个问题才是我写这篇博客的源动力,网上有很多人问,但是回答者没能详细说明,《STM32F10X参考手册》中的描述也有歧义。我只能从别人回答的只言片语中摸索,然后根据自己的理解来解释。下面就看第二节的基本知识。

《STM32F10X参考手册》对此的描述如下:

自动装载寄存器是预先装载的,写或读自动重装载寄存器将访问预装载寄存器。根据在TIMx_CR1寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或在每次的更新事件UEV时传送到影子寄存器。当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1寄存器中的UDIS位等于’0’时,产生更新事件。更新事件也可以由软件产生。随后会详细描述每一种配置下更新事件的产生。

我在这个通用定时器框图里面找不到预装载寄存器,这就更增加疑惑了。后来翻了很多问答帖,大概明白了其中的意思,以下是我的总结以及理解。

从框图里面看到自动重装载寄存器(Auto Reload Register,ARR)和捕获/比较寄存器组(Capture/Compare Register,CCR)的框下面有阴影,这就说明这两种寄存器含有影子寄存器(Shadow Register)。影子寄存器实际上才是真正直接参与定时器工作的寄存器,具有即时性。我们配置的ARR和CCR相当于都是上层的寄存器,芯片在工作中,自动将这些上层寄存器的值传递到各自的影子寄存器,从而参与计数或者比较过程。

那么,预装载寄存器在哪里呢?

在参考文献《关于STM32影子寄存器和预装载寄存器和TIM_ARRPreloadConfig》中发现实际上ARR和CCR(可能)在物理底层上是两个寄存器的组合,即预装载寄存器(Preload Register)和影子寄存器。实际上,我们在代码层面,对ARR和CCR赋值,最终传递到直接参与工作的影子寄存器,中间还要经历一个预装载寄存器的传递,它在这里相当于缓存的作用。但是在手册中并没找到确实再物理硬件上存在预装载寄存器的蛛丝马迹(只查到缓存器一说),那么也可以这样理解。所谓的预装载寄存器实际上只是ARR和CCR在他们需要向影子寄存器传递值的时候的一种“功能化”的别称,也就是说在需要传值的时候,ARR和CCR就是各自影子寄存器的预装载寄存器。

预装载寄存器的概念应该是相对于影子寄存器来说的。影子寄存器是即时其作用的,而预装载寄存器的值只有传递到影子寄存器才能起作用,你可以把它理解为一个缓存。就程序员的角度观察,两者共用一个地址,无法直接区别访问,只能通过另外的办法来设置对该地址操作的具体行为。

作为类比,你可以把预装载寄存器理解为内存中的cache,数据写入了cache,却是不一定写入内存的。当然你可以通过MMU设置为写穿(write through)或写回(write back)模式。

那么ARR和CCR各自的影子寄存器的值在什么时候更新呢?

可以立即将值传入或者每次事件更新的时传入,依赖于相关的控制位。

以ARR为例,控制寄存器TIMx_CR1的位7——ARPE(自动重装载预装载允许位 ,Auto-reload preload enable),写“0”时,TIMx_ARR寄存器没有缓冲;写“1”时,TIMx_ARR寄存器被装入缓冲器。也就是说ARPE写1,则影子寄存器立即被更新,否则只有等到每次事件发生时,才更新,这就是的含义。


同理,CCR的影子寄存器也有相应操作。我选择的是TIM3的通道2,其控制寄存器CCMR1的OC2PE位(CCMR1控制通道1和通道2),相应的操作可以对照库函数来了解。

看到有人回复“如果不改变频率和占空比,纯粹输出PWM波,则可以不需要使能预装载”,那是不是意味着以下两句代码可以不写?这需要试一下……


那这样设计预装载和影子寄存器有什么好处呢?

参考如下,我的简单理解就是将定时器的赋值过程和工作过程独立开。