STM32定时器更新事件可以暂停否?

发布者:Huanle666最新更新时间:2023-10-10 来源: elecfans关键字:STM32  定时器  暂停 手机看文章 扫描二维码
随时随地手机看文章

有人使用STM32的定时器的输出比较功能,具体就是输出4个通道的PWM信号。不过 他需要不定时地调整4个通道的占空比,即调整他们的CCR值。但现在有个小问题,那就是新的CCR值的获得往往会能跨越多个目前定时器的计数周期,这样的话,即使开启各个通道CCR值的预装功能,似乎也很保证做到一次性修改。因为它希望新的CCR值被同时更新。换句话说,他担心不同通道新的CCR值分散在不同计数周期生效,可能给应用带来些麻烦。


我们知道,STM32定时器的预装寄存器的值到影子寄存器的更新往往离不开更新事件。一般来讲,只要启动了定时器,更新事件会随着计数器的溢出而自然产生。


既然这样,比方若是在下面四个时刻获得了新的CCR值,有没有办法让这几个值同时实施更新,而不是分布在不同时刻生效呢?

8f52fbec-641e-11ed-8abf-dac502259ad0.png

其实是可以的。有两种方法可以参考,但有个共同的前提,就是开始做新数据准备时,先把定时器更新事件的产生允许关闭,因为STM32定时器更新事件最终是否产生是可以软件控制的,我们可以等数据都准备好了再允许定时器更新事件的产生。通过对TIMER控制寄存器的UDIS位置1或清零达到关闭或允许更新事件的产生的目的。

8f7434f6-641e-11ed-8abf-dac502259ad0.png

在这个前提下,我们可以有两种做法。

第一种,在准备新数据时,先通过对UDIS写1禁止更新事件的产生,同时开启CCR的预装功能,然后就可以悠闲地给各通道的CCR寄存器写新值了,不必担心它会生效,此时我们只是写进了CCR的预装寄存器。等到4个通道的新值都写进各自CCR预装寄存器后,再将更新事件位UDIS清零以允许定时器更新事件产生,数据更新的事就交给后续更新事件来完成,不必担心生效先后问题。

还有一种做法,那就是用户根本不直接对CCR进行改写操作,而是先将4个通道的新数据放在连续的内存里,借助定时器事件的DMABurst传输功能一次性完成修改。

大致流程是,先通过对UDIS写1禁止更新事件产生,然后将4个通道的新的CCR数据按照CCR1、CCR2、CCR3、CCR4的顺序放在内存,配置基于定时器更新事件的DMA Burst传输功能。即一个定时器事件可以触发DMA完成多个定时器寄存器与内存间的一次性传输。

此时,4个通道的CCR寄存器的预装功能可以开启,也可以不开启,但是几个通道的配置要保持一致,不要有的通道开启、有的不开启,否则反而不能保证几个通道参数的同步修改。

8fa0144a-641e-11ed-8abf-dac502259ad0.png

针对第2种做法,这里简单示范下实现过程。这里以STM32G4系列的TIM4来设计的。

8fadc806-641e-11ed-8abf-dac502259ad0.png

8fd9625e-641e-11ed-8abf-dac502259ad0.png

上图中红线配置提示开启了CCR寄存器的预装功能。前面说了也可以同时都不开启。

900a77b8-641e-11ed-8abf-dac502259ad0.png

使用CubeMx配置后生成HAL库工程代码,添加用户代码。我定义一个4字大小的数组

CCR_Data【4】用来存放新的CCR数据。下面代码实际上是我模拟反复调用的,在别的地方动态修改NewDataOK的值。

if(NewDataOK)

{

//Prohibit Update event ’generation since now

TIM4->CR1|=(TIM_CR1_UDIS); 

NewDataOK =0;

CCR_Data[0]=CCR1_Value;

CCR_Data[1]=CCR2_Value;

CCR_Data[2]=CCR3_Value;

CCR_Data[3]=CCR4_Value;

HAL_DMA_Abort(&hdma_tim4_up);

htim4.DMABurstState= HAL_DMA_BURST_STATE_READY; 

HAL_TIM_DMABurst_WriteStart(&htim4,TIM_DMABASE_CCR1, TIM_DMA_UPDATE,&CCR_Data[0],TIM_DMABURSTLENGTH_4TRANSFERS);

__HAL_TIM_CLEAR_FLAG(&htim4,TIM_FLAG_UPDATE);

//Update event generation allowed now

TIM4->CR1 &=~(TIM_CR1_UDIS);

}

其中,HAL_TIM_DMABurst_WriteStart()函数是Cube库里现存的,它实现从内存到定时器寄存器的BURST传输。还有一个函数HAL_TIM_DMABurst_ReadStart()实现从定时器寄存器到内存的BURST传输。

下面截图是测试结果,各个通道同步变化:

90c8b552-641e-11ed-8abf-dac502259ad0.png

我给的测试数据4个通道都是一样的,示波器只接了3个通道。

上面重点分享了定时器更新事件的产生可以通过软件关闭或开启的这个特性,我们可以在以后STM32开发应用中灵活运用。 不过,请不要把定时器更新事件是否可以产生跟更新事件源混为一谈。这里讨论的是更新事件产生的允许问题,而更新事件源则讨论的是更新事件怎么来的,它可以因计数器的溢出、工作在复位模式的从定时器收到触发信号或者由软件操作寄存器而产生。


关键字:STM32  定时器  暂停 引用地址:STM32定时器更新事件可以暂停否?

上一篇:SD NAND 的 SDIO在STM32上的应用详解(中篇)
下一篇:一种基于STM32的智能采油控制系统的设计与实现

推荐阅读最新更新时间:2024-11-02 00:26

工程师笔记|高精度定时器与高级控制定时器 PWM 封波后再恢复的区别
引言 在高精度定时器中,可以使用外部事件来对 PWM 输出进行封锁,并可自动恢复;在高级控制定时器中,可以使用 Break 或是 Clr_input 来对 PWM 输出进行封锁, 然后也可以自动恢复,其中 Break 必须结合 AOE 置位来实现自动恢复。 虽然都可以实现封波后的自动恢复,但是在二者之间还是存在一些区别。 PWM 封波-自动恢复原理分析 在高精度定时器中,通过配置 PWM 的 Set 与 Reset 事件,当 Set/Reset 事件发生时,PWM 输出做出对应的响应。要实现封波-自动恢复,只需配置合适的 Reset 事件,Reset 发 生时,触发 PWM 输出 inactive 电平,当 Reset 事件
[单片机]
关于STM32 Systick 延时函数 变量全局引用的问题
有这样一段代关于systick.c,如下: #include SysTick.h volatile unsigned int TimingDelay ; // 精确延时在SysTick中断里用的计数变量 // 在全局变量里面一定要加上volatile关键字(易变的),否则在全局引用中容易造成编译器的传递错误 void SysTick_1ms_Configuration(void) { /* Setup SysTick Timer for 1 msec interrupts */ if (SysTick_Config(SystemFrequency / 1000)) { /* Capture error */ while (
[单片机]
stm32:中断配置的步骤
使用外部中断的一般步骤 1、初始化I/O 口, 2、开启AFIO时钟 3、建立I/O口与中断线的映射关系,使用库函数 void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource), 参数GPIO_PortSource表示I/O口,取值:GPIO_PortSourceGPIOx (A..G).。 参数GPIO_PinSource表示中断线,取值:GPIO_PinSourcex(0..15).。 4、初始化中断线,即配置结构EXTI_InitStructure,其成员 EXTI_Line:中断线,取值EXTI_Line0x(0~15)
[单片机]
Visual Studio 2019 +STM32实现串口通讯
1.下载 免费版 Visual Studio 2019 并进行安装visualstudio.microsoft.com/zh-hans/ 2.双击软件创建项目 3.选择Windows窗体应用程序(.NET Framework)创建项目。 4.项目创建完成,初始界面。 5.选择左侧的工具栏,选择 组件,然后双击 串口组件将串口添加进入项目。 6.点击鼠标右键,修改串口模块的属性,包括 波特率等,本实验采用默认。 7.双击串口模块,添加数据接收中断函数 8.添加按钮模块,控制STM32开发板LED灯的亮灭。 9.好的现在基本界面与模块添加完成,开始写程序,添加程序各种变量: //串口通讯命令 publi
[单片机]
Visual Studio 2019 +<font color='red'>STM32</font>实现串口通讯
沙场点兵STM32微处理器全系列成员
众所周知,STM32系列32位Flash微控制器在电子行业中不管是以前还是现在都有着无可替代、无与伦比的地位。其基于ARM Cortex™‑M处理器,旨在为MCU用户提供新的开发自由度,集高性能、实时功能、数字信号处理、低功耗与低电压操作等特性于一身,同时还保持了集成度高和易于开发的特点,最重要的是,性价比高、价格便宜。 无可比拟且品种齐全的STM32产品基于行业标准内核,提供了大量工具和软件选项,使该系列产品成为小型项目和完整平台的理想选择。下面我们”沙场点兵”STM32系列中全系列成员,捕捉精髓,学习技术,创造可能…… NO.1:STM32 F0入门级Cortex™-M0 MCU 基于ARM® Cortex-
[单片机]
stm32中“拔掉jlink”程序无法正确运行
Q:在调试stm32程序时,从电脑USB口拔掉jlink后开发板上程序为什么无法正确运行?断点复位后也不行。 A:首先,要拔了jlink与开发板的连接(而不仅仅是其与PC的连接),因为jlink本省内部也有电路,对开发板上的程序运行有所影响; 其次,检查stm32的boot 的配置,将BOOT0配置为0才能从复位后Flash启动。BOOT的具体配置如下: BOOT1 BOOT0 启动模式 说明 X 0 Flash 复位后选择主闪存启动 0 1
[单片机]
stm32 直接读写寄存器代码风格总结
简单的总结了一下stm32 寄存器读写代码风格,以备后用: 根据memory mapping 直接写寄存器代码风格: #define GPIOA_BASE1 (uint32_t)0x40010800 #define GPIOA_CRH ((uint32_t*)(GPIOA_BASE1+0x04)) 转换为指针之后,直接读写: *GPIOA_CRH=0x000004B0; //A端口 //复用推挽输出 结构体指针解决连续多个寄存器读写设置: #define Usart1_BASE 0x40013800 typedef struct { __IO uint32_t SR; __IO
[单片机]
<font color='red'>stm32</font> 直接读写寄存器代码风格总结
正点原子STM32 USB读卡器代码分析
USB读卡器的基本原理就是向主机提供SD读写功能,并不需要加入文件系统功能。 USB设备的实现步骤: 1、 初始化系统时钟,设置USB时钟 2、 配置USB中断,选择通道,设置优先级,使能中断 3、 配置GPIO 4、 USB的初始化,对描述符、设备的端点接口等的初始化 5、 FLASH的初始化 sd_size=(long long)SD_GetSectorCount()*512; //得到SD卡容量,字节. Mass_Memory_Size =sd_size%4294967296; //当SD卡容量超过4G的时候,需要用到两个u32来表示 Mass_Memory_Size
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved