[GPTMR]基础定时
在探索先楫定时器外设的世界时,理解GPTMR(通用定时器)和PWM(脉宽调制)之间的区别至关重要。这两个在HPM都是独立的外设,但GPTMR可以与内部比较器和同步机制协同工作,生成基础的PWM信号。然而,对于如电机控制等需要高级特性的应用,比如死区时间管理和影子寄存器配置,则更适合使用专门的PWM模块。
每个先楫通用定时器都配备有四个通道,每个通道都包含一个独立的32位计数器、重装载寄存器、输入捕获以及输出比较功能。此外,这些通道还支持定时、输入捕获、PWM生成、中断触发(包括重装载中断和输入捕获中断),以及DMA请求。这些特性使得定时器成为一个多功能且强大的工具,适用于各种应用场景。
hpm_sdk中的samples/drivers/gptmr目录提供了丰富的示例代码,覆盖了上述提到的所有定时器功能。本文将以这些例子为基础,深入探讨如何有效利用GPTMR定时器来实现不同的任务。
本系列定时器文章会基于hpm_sdk下的gptmr例子进行阐述,截至SDK1.8.0,包括:
counter_sync: 定时器同步计数器产生两路同步PWM
sent_signal_decode: 定时器采集解析sent信号
t_shape_accel_decel: 定时器生成T型加减速脉冲
从例子分布上看,基于定时器的应用例子主要有两个sent_signal_decode和t_shape_accel_decel,其他是定时器的功能例子。
定时器每个通道包括一个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开始)。
例子:sdk/samples/drivers/gptmr/timer_basic
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库。
该库简单来说就是使用定时器以指定的精准时间定时,定时完成后回调功能。该库包含了开始定时begin、结束定时end之外,还可以随时update更新定时时间,也有可能设置定时优先级。
该代码放在https://github.com/RCSN/hpm_sdk_extra中,路径是demos/peripherals/gptmr
包含gptmr基地址、gptmr通道、状态、设置的毫秒值、reload值,以及用户回调函数。
需要赋值gptmr基地址、gptmr通道,并且使能其工作时钟。
其实也就是在工作的途中更新reload值,但由于gptmr并没有影子寄存器,无法暂存重装载值reload,但可以配合计数器更新计数器为0或者复位计数器来达到目的。比如更新计数器上,需要设置以下寄存器:
进而可以在发生重装载中断时改变reload值从而达到更新定时作用。
根据上述的模仿IntervalTimer库实现的API,开始计数10us,经过50次计数后更新为20us,计数到100次之后停止计数。通过每次计数后翻转IO观测。
可看到,10us更新到20us后,在后续持续20us一次计数定时。