历史上的今天
返回首页

历史上的今天

今天是:2025年01月28日(星期二)

2020年01月28日 | stm32影子寄存器、预装载寄存器

2020-01-28 来源:eefocus

一直没搞清楚stm32定时器的TIM_OC1PreloadConfig、TIM_ARRPreloadConfig函数的作用,影子寄存器、预装载寄存器、重载寄存器的概念。今天来研究一下:


首先看定时器的框图:

图中有阴影的小方框,代表该功能对应的寄存器有影子寄存器,也就是:PSC预分频器、自动重装载寄存器、REP寄存器和4个通道的捕获/比较寄存器。


可以看到这几个寄存器都是经常用到的,而且存在定时器工作过程中修改他们的可能性。在定时器工作过程中修改他们的值,就会出现一个问题了:如果上次ARR的值是200,通道1的比较寄存器CCR1值是100,产生占空比为50%的PWM。这个时候我要改变PWM的频率,我把ARR的值改为100,CCR1的值还没来得及更改,那么占空比肯定就会出问题,所以我就需要让他们同步修改。以前ARR=200,CCR1=100,提高频率后ARR=100,CCR1=50,我需要这两个寄存器的值同步修改,最好还是让他们计数完一个周期后再修改,那么进入下一个周期ARR、CCR1同步修改过去,对PWM的占空比就没有一点影响了。


为了达到这个目的,就得先用一个寄存器A把修改的值保存好(ARR_A=100,CCR1_A=50),一旦上一个周期结束,给一个信号,立即就把寄存器A的值赋值过去,立即生效,这样就完成了最理想的在定时器运行中修改寄存器的过程。下面对应到stm32中:


有影子寄存器的寄存器实际上对应了两个寄存器:一个是用户可以写入或读出数据的寄存器,称为preload register(预装载寄存器),另一个是用户看不见的、但在操作中真正起作用的寄存器称为shadow register(影子寄存器)。我们修改的定时器周期、预分频系数、通道的比较值等都是修改的表面那个预装载寄存器,要让这个修改起作用,就还要把预装载寄存器的值赋给影子寄存器才行。


从ARR预装载寄存器传送到影子寄存器,有两种方式,一种是立刻更新,一种是等触发事件之后更新;这两种方式主要取决于寄存器TIMx->CR1中的“APRE”位:

APRE=0,当ARR值被修改时,同时马上更新影子寄存器的值;

APRE=1,当ARR值被修改时,必须在下一次事件UEV发生后才能更新影子寄存器的值;

这就是TIM_ARRPreloadConfig(TIM1, ENABLE);函数的作用:


#define  TIM_CR1_ARPE     ((uint16_t)0x0080)

 

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)

{

  if (NewState != DISABLE)

  {

    TIMx->CR1 |= TIM_CR1_ARPE;

  }

  else

  {

    TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE);

  }

}


4个通道的捕获/比较寄存器也是同样的道理,从CCRx的预装载寄存器传送到影子寄存器由下面的位控制:

TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);函数的作用就是修改这个位:


#define  TIM_CCMR1_OC1PE        ((uint16_t)0x0008)

#define TIM_OCPreload_Enable    ((uint16_t)0x0008)

 

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)

{

  uint16_t tmpccmr1 = 0;

 

  tmpccmr1 = TIMx->CCMR1;

  tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE);

  tmpccmr1 |= TIM_OCPreload;

  TIMx->CCMR1 = tmpccmr1;

}

 


再给几个时序图:


1、APRE=0,直接给ARR影子寄存器赋值的情况:

可以看到之前ARR=FF,给ARR赋值为36后,马上就生效了,并在等于36时发生了溢出。


2、APRE=1,在下一个周期再更新值的情况:

可以看到之前ARR=F5,这个时候修改ARR的值为36,只有表面的重加载寄存器值更改了,真正起作用的影子寄存器并没有更改。等到上一个周期结束,发生更新事件,影子寄存器才更改。

推荐阅读

史海拾趣

B&F;公司的发展小趣事

在航空领域,产品质量直接关系到乘客的生命安全。因此,B&F公司一直将质量控制放在首要位置。公司采用严格的生产流程和质检标准,确保每一架FK系列飞机都符合最高标准。此外,公司还注重电子系统的可靠性和稳定性测试,确保飞机在各种恶劣环境下都能正常运行。这种对质量的严格把控,为B&F公司赢得了客户的信任和市场的认可。

蜂鸟无线公司的发展小趣事
由于PWM调速是通过调整电压脉冲的占空比来控制电动机的平均电压,因此能够减少能量损失,提高系统的能效。
GE Industrial Solutions公司的发展小趣事
光耦的隔离作用虽然能减少电气噪声的干扰,但光耦本身也可能引入噪声。解决方法包括选择低噪声的光耦,或在电路中加入滤波电路。
Crystalfontz America Inc公司的发展小趣事

随着产品技术的不断提升,Crystalfontz America Inc公司开始积极拓展市场。公司通过与各大电子设备制造商建立合作伙伴关系,将产品应用于嵌入式系统、机架式服务器、仪器集群等领域。同时,公司还积极参加各类行业展会和技术交流活动,提升品牌知名度,吸引更多潜在客户。这些举措有效推动了公司市场份额的扩大和业务的快速增长。

广东长利光电(Changli Optoelectronic)公司的发展小趣事

进入21世纪,广东长利光电开始将目光投向国际市场。公司积极参加各种国际展览和交流活动,与世界各地的客户建立了广泛的联系。凭借优质的产品和服务,公司逐渐在国际市场上崭露头角。为了更好地服务全球客户,广东长利光电在中国设立了多个办事处,并建立了完善的销售和服务网络。

安森德(Ascend)公司的发展小趣事

在快速发展的过程中,安森德公司始终注重品牌建设和文化塑造。公司坚持以客户为中心的服务理念,不断提升产品质量和服务水平。同时,安森德还积极参与各类行业活动和公益事业,提升公司的社会形象和品牌价值。在内部管理方面,公司倡导创新、协作、担当的企业文化,为员工提供了一个良好的工作环境和发展平台。这些举措不仅增强了员工的归属感和凝聚力,也为公司的长远发展奠定了坚实的基础。

问答坊 | AI 解惑

3v与5v接口问题的解决

本帖最后由 paulhyde 于 2014-9-15 09:38 编辑 希望对大家有帮助哈!  …

查看全部问答>

各位版主帮我修个程序,,十万着急,,对熟悉人很简单

我附件的程序有个问题:   如果修改了参数不按SET突然断电就保存不了,,要修改为只要修改了参数不按SET也可以自动保存   把哪个地方修了发个说明过来,...最好发个修改后完整的版本和完整版本哪里有修改的说明过来....麻烦了,,,  …

查看全部问答>

MSP430芯片SPI的驱动程序,存储器用的芯片AT45DB161D 编译时找不到头文件include "AT45DB161D.h"

我写的程序是关于MSP430的SPI驱动,实现数据的简单读写,但在编译时总提示  找不到头文件 include \"AT45DB161D.h\"的源文件,下面是我写的程序: #include #include \"AT45DB161D.h\" #define NOP() { _nop_(); _nop_(); _nop_(); ...…

查看全部问答>

问个小问题~~

各位大虾......弱弱的问下.... 现在要招嵌入式开发的公司是不是都不要新手的呢? 偶想转..不知道有没有公司要新手的...一个人自学好难啊~~…

查看全部问答>

.Net Compact Framework 1.1中有没有获得当前线程ID的方法?

.Net Compact Framework 1.1中有没有获得当前线程ID的方法? 完全版中倒是有AppDomain.GetCurrentThreadID() coredll.dll中有没有我也不知道。 哪位大虾帮帮我啊~…

查看全部问答>

USB虚拟串口要命的丢数据

换了一个硬盘,从Windows2000换到XP,原来在测试的一个数据采集板突然就不能用了。应用板是STM32F103VB,USB口发送采集的数据到PC,偷了一点懒,直接用虚拟串口的例子改的USB通信程序,这部分程序在Window2000下用了两个多月了,一直好好的。 ...…

查看全部问答>

线路的尖峰毛刺造成FPGA工作不正常

  使用EP2C35 FPGA 设计了多个串口工作,出现了几个问题. 第一次, 由于内核电源1.2V 供电不是完整平面,而是带状线供电,EP2C35 在代码容量大的情况下,而且输入FPGA 信号变换频繁, 造成整个EP2C35 所有的D触发器停止翻转. 经过多次验证, 只要输入 ...…

查看全部问答>

请问:Error[e16]: Segment CSTACK (size: 0x50 align: 0x1) is too long for segment de

Error[e16]: Segment CSTACK (size: 0x50 align: 0x1) is too long for segment definition. At least 0x4 more bytes needed. The pro××em occurred while processing the segment placement command "-Z(DATA)CSTACK+_STACK_SIZE#", wher ...…

查看全部问答>

ARM问题

我用ADS1.2编译生成两个目标文件(init.o 和main.o),仿真没问题,但是我烧了几次复位没有反应(S3C2410开发板)。请高人请点:两个目标文件(init.o和main.o)怎么烧写。备注一下,我烧写用K9S1208()函数。…

查看全部问答>