[GPTMR]基础定时

一、前言


在探索先楫定时器外设的世界时,理解GPTMR(通用定时器)和PWM(脉宽调制)之间的区别至关重要。这两个在HPM都是独立的外设,但GPTMR可以与内部比较器和同步机制协同工作,生成基础的PWM信号。然而,对于如电机控制等需要高级特性的应用,比如死区时间管理和影子寄存器配置,则更适合使用专门的PWM模块。

每个先楫通用定时器都配备有四个通道,每个通道都包含一个独立的32位计数器、重装载寄存器、输入捕获以及输出比较功能。此外,这些通道还支持定时、输入捕获、PWM生成、中断触发(包括重装载中断和输入捕获中断),以及DMA请求。这些特性使得定时器成为一个多功能且强大的工具,适用于各种应用场景。

hpm_sdk中的samples/drivers/gptmr目录提供了丰富的示例代码,覆盖了上述提到的所有定时器功能。本文将以这些例子为基础,深入探讨如何有效利用GPTMR定时器来实现不同的任务。

image.png

本系列定时器文章会基于hpm_sdk下的gptmr例子进行阐述,截至SDK1.8.0,包括:

cntmode: 定时器外部计数模式例子

counter_sync: 定时器同步计数器产生两路同步PWM

input_capture: 定时器输入捕获例子

monitor: 定时器监视功能

opmode: 定时器单次模式功能

output_compare: 定时器输出比较例子

pwm_generate: 定时器生成PWM

pwm_measure: 定时器测量PWM

sent_signal_decode: 定时器采集解析sent信号

t_shape_accel_decel: 定时器生成T型加减速脉冲

timer_basic: 定时器基础定时

从例子分布上看,基于定时器的应用例子主要有两个sent_signal_decode和t_shape_accel_decel,其他是定时器的功能例子。

二、GPTMR定时器定时功能讲解

以下寄存器说明参考先楫用户手册,这里不做截图和阐述。

(一)定时器定时需要操作的寄存器说明

定时器每个通道包括一个32位计数器(CHANNEL[CNT]j寄存器)和32位的重装载寄存器(CHANNEL[RLD]寄存器),计时器支持向上计数。

CHANNEL[CNT]寄存器是个只读寄存器,读取CHANNEL[CNT]j寄存器会返回当前计数值,每发生一次计数时钟周期,计数器就计数一次。

如果需要更新当前计数器,可以设置CHANNEL[CR]寄存器的CNTUPT位为1,且设置CHANNEL[CNTUPTVAL]的值,那么CHANNEL[CNT]寄存器就会更新为CHANNEL[CNTUPTVAL]的值。

CHANNEL[RLD]寄存器用于计数器的计数周期,当计数器计数到该计数周期,CHANNEL[CNT]寄存器会自动清零,同时会产生一次重载事件,对应的定时器通道会产生重载标志,SR寄存器的CHxRLDF位会置一。

IRQEN寄存器的CHxRLDEN置一时,重载中断被使能,当SR寄存器的CHxRLDF位被置一时,会触发重载中断。

CHANNEL[CR]寄存器的DMASEL=‘0b11’,并且HANNEL[CR]寄存器的DMAEN位为1时,重载请求DMA被使能,当SR寄存器的CHxRLDF位被置一时,会产生一次DMA请求。

注意:

1、设置CHANNEL[CR]寄存器的CNTUPT位会在下一个周期后自动清零。

2、SR寄存器的CHxRLDF位需要写一清除标志位,否则会频繁进入重载中断或者频繁请求DMA。

3、必须确保已启用GPTMR的工作时钟以保障定时器能够正常运行。

(二)配置流程

根据上述的寄存器说明,从配置流程上也很简单,只需要以下三个步骤:

1、设置CHANNEL[RLD]寄存器值,定义计数器的重载值。

2、设置CHANNEL[CR]寄存器的CEN位,启动计数器。

3、设置IRQEN寄存器的CHxRLDEN位,中断使能配置。‘

比如:使用GPTMR配置一个1S的定时器,配置GPTMR的工作时钟为100MHz,重载值设置为1S * 100Mhz = 100000000个计数单位,当计数器计数到重载值时,会产生重载标志事件。那么reload值就是99999999(100000000 - 1,计数器从0开始)。

在hpm_sdk中,可以看到也是根据该操作进行。

例子:sdk/samples/drivers/gptmr/timer_basic

image.png

gptmr_channel_config API主要配置定时器的相关功能,其传入参数gptmr_channel_config_t可参考相关宏定义,该配置后续也会进行阐述,这里只需要关心reload这个重装载参数值。

在配置之前建议使用gptmr_channel_get_default_config API进行缺省。

gptmr_start_counter API是开启计数器。

gptmr_enable_irq API是使能定时器相关中断。

注意:需要通过clock_add_to_group(APP_BOARD_GPTMR_CLOCK, 0)使能定时器工作时钟,默认最大100Mhz。

三、以应用阐述外设功能

单纯从外设阐述,未免有些过于枯燥,外设系列每篇文章以应用角度出发,更能体现外设功能的独特以及全面。

本篇基础定时,从原理上阐述可能过于简单,刚好也有开发者想在SDK上实现基于imxrt1052的Teensy板子下的arduino库---IntervalTimer库。

截图.png

该库简单来说就是使用定时器以指定的精准时间定时,定时完成后回调功能。该库包含了开始定时begin、结束定时end之外,还可以随时update更新定时时间,也有可能设置定时优先级。

该代码放在https://github.com/RCSN/hpm_sdk_extra中,路径是demos/peripherals/gptmr

1、interval_timer实例结构体

包含gptmr基地址、gptmr通道、状态、设置的毫秒值、reload值,以及用户回调函数。

image.png

2、interval_timer实例初始化

需要赋值gptmr基地址、gptmr通道,并且使能其工作时钟。

image.png

3、interval_timer实例开始工作

参考以上的timer_basic例子接口实现

image.png

4、interval_timer实例更新定时

其实也就是在工作的途中更新reload值,但由于gptmr并没有影子寄存器,无法暂存重装载值reload,但可以配合计数器更新计数器为0或者复位计数器来达到目的。比如更新计数器上,需要设置以下寄存器:

image.png

image.png

记录需要更新的us转换的reload值:

image.png

进而可以在发生重装载中断时改变reload值从而达到更新定时作用。

image.png

5、interval_timer实例结束定时

只需要关闭计数器和复位计数器即可。

image.png

四、应用验证

根据上述的模仿IntervalTimer库实现的API,开始计数10us,经过50次计数后更新为20us,计数到100次之后停止计数。通过每次计数后翻转IO观测。

image.png

可看到,10us更新到20us后,在后续持续20us一次计数定时。

image.png

0
0
发表回复 0

Your email address will not be published. Required fields are marked *