[GPTMR]输入捕获
在常规的一些MCU开发中,比如需要测量输入信号的频率或者占空比,往往都是使用输入捕获中断来获取当前的计数器,然后做一些运算操作得出输入信号的频率或者占空比,这往往带来两个问题:
2、获取的计数器值并不是输入捕获到边沿时刻的计数器值,而是进入到处理中断后的计数器值,存在一定的误差。
在先楫所有的MCU系列中,GPTMR定时器不单单支持发生捕获的时候会将捕获到边沿时刻的计数器值保存到指定的寄存器中,而且还支持PWM测量模式,硬件自动测量输入信号的周期和占空比,存储到指定的寄存器中,这些寄存器可以通过DMA搬运,完全不需要CPU参与即可实时测量输入信号的周期和占空比,完美解决以上的缺点。
在pwm_measure例子中,当输入的1Khz,50%占空比信号时,可自动测量PWM,并通过DMA搬运到指定缓存区,进行缓存区显示。
这里的工作时钟的时钟源来源于默认pll,比如HPM5300系列,对于gptmr的时钟源默认就是PLL1CLK0,8分频得到100MHz工作时钟,故也可不用设置pll。
若需要手工更改pll,也可使用先楫的clock tool配置:
链接:https://tools.hpmicro.com/clock
比如以下,选择使用PLL0CLK2作为时钟源,经过四分频后也可以得到gptmr的100M工作频率。最后配置完成点击生成clock代码即可。
2、使能对应的输出引脚的Pinmux功能为capture比较输出
在sdk中可参考每个board的pinmux的gptmr pins初始化,比如对应的hpm5300evk。
这里就是设置了PB06的pimmux功能为GPTMR0的通道0输入捕获
链接:https://tools.hpmicro.com/pinmux
比如使用GPTMR0的通道0。最后配置完成点击生成pinmux代码即可。
参考先楫用户手册以及HPM_SDK对于PWM生成的配置,可以总结以下步骤:
1、设置CHANNEL[CR]寄存器的CEN位,配置关闭计数器。
2、设置CHANNEL[CR]寄存器的CNTRST位,复位计数器。
3、设置IRQEN寄存器的CHxCAPEN位,中断使能配置。
4、设置CHANNEL[CR]的CAPMODE位,选择输入捕获的模式。
5、设置CHANNEL[RLD]的寄存器值,配置计数器重载值。
6、设置CHANNEL[CR]寄存器的CEN位,配置启动计数器。
7、查看SR寄存器的CHxCAPF输入捕获标志位是否置1,若置1则检测到上升沿或下降沿或上升沿和下降沿。需要清除输入捕获标志位 SR.CHxCAPF = 1。
8、读取CHANNEL[CAPPOS]值,获取捕获到上升沿时候的计数值。
9、读取CHANNEL[CAPNEG]值,获取捕获到下降沿时候的计数值。
10、读取CHANNEL[CAPPRD]值,获取捕获到PWM周期。读取CHANNEL[CAPDTY]值,获取捕获到PWM占空比。
1、PWM测量模式中的CHANNEL[CAPPRD]和CHANNEL[CAPDTY]寄存器,是以计数器为单位。如果需要频率赫兹单位以及占空比百分比单位,需要进行转换。
PWM周期(HZ) = GPTMR工作时钟频率(HZ)/ CHANNEL[CAPPRD]
PWM占空比(百分比) = (CHANNEL[CAPDTY] / CHANNEL[CAPPRD])* 100
2、 输入捕获模式为上升沿和下降沿模式时,检测到上升沿和下降沿后,也就是翻转才会发生输入捕获标志位事件。
3、PWM模式下,也可以使用输入捕获中断和获取输入捕获标志位,检测到上升沿和下降沿后才会发生输入捕获标志位事件和中断。
4、输入捕获的上升沿和下降沿捕获到的计数器值寄存器同样也是计数器为单位。
配合hpm_sdk中的samples/drivers/gptmr/input_capture
2、设置CHANNEL[CR].CAPMODE = ‘0b001’,捕获模式为捕获上升沿模式
3、设置CHANNEL[RLD] = 0xFFFFFFFF,配置最大的重载值
4、关闭通道输入捕获标志位中断使能位 IRQEN.CHxCAPEN = 1
5、复位计数器 CHANNEL[CR].CNTRST = 1,复位后需要清零释放复位CHANNEL[CR].CNTRST = 0
6、开启计数器,开启计数, CHANNEL[CR].CEN = 1。
7、查看SR寄存器的CHxCAPF输入捕获标志位是否置1,若置1则捕获到上升沿。需要清除输入捕获标志位 SR.CHxCAPF = 1。
8、读取CHANNEL[CAPPOS]值,获取捕获到上升沿时候的计数值。
在input_capture例子中,gptmr_channel_config API就包括了以上配置步骤的1到4。
而config缺省配置使用gptmr_channel_get_default_config API,建议配置之前使用该API进行缺省初始化
在本例子中,需要捕获上升沿,可以设置mode为上升沿捕获模式,根据例子实现:
在步骤5和6的复位计数器和开启计数器,可使用以下API
本例子由于使用了中断方式,需要做以下操作:
当寄存器赋值步骤4的IRQEN.CHxCAPEN = 1,打开通道输入捕获标志位中断使能位,会触发中断通知捕获到输入信号。使用gptmr_enable_irq API
使用中断需要使能PLIC控制器的定时器中断。使用intc_m_enable_irq_with_priority API
使用gptmr_check_status API可检查对应的标志位是否置一
使用gptmr_clear_status API可清除指定的标志位
使用gptmr_channel_get_counter API可获取不同模式下的计数器值,比如输入捕获功能的上升沿捕获。
当输入固定的频率信号时,打印的两个上升沿差值大致一样,符合输入捕获预期效果:
2、复位计数器 CHANNEL[CR].CNTRS =1,复位后需要清零释放复位CHANNEL[CR].CNTRST=0
3、设置CHANNEL[CR].CAPMODE = ‘0b100’,捕获模式为PWM测量模式。
4、关闭通道输入捕获标志位中断使能位 IRQEN.CHxCAPEN = 0。
5、设置CHANNEL[RLD] = 0xFFFFFFFF,配置最大的重载值。
6、开启计数器,开启计数, CHANNEL[CR].CEN = 1。
7、读取SR寄存器的CHxCAPF输入捕获标志位是否置1,若置1则定时器已经测量好输入PWM的周期和占空比。需要清除输入捕获标志位 SR.CHxCAF = 1。
8、读取CHANNEL[CAPPRD]值,获取捕获到PWM周期。读取CHANNEL[CAPDTY]值,获取捕获到PWM占空比。
根据上述上升沿捕获应用,在pwm_measure例子中,设置好缺省值后,设置模式为PWM测量模式即可,之后复位并且开启计数器工作。
在主循环中查询对应的CAPF标志位是否置一,如果置一读取对应的计数器值,并通过上述的转换计算得出占空比和周期。
在pwm_measure例子中,DMA搬运方式只支持XDMA,这是因为频率和占空比分别占用两个32bit寄存器,并且两个寄存器保持连续,而XDMA是64bit宽度,可以搬运64位宽度数据,这样可以一次搬运频率和占空比数据,如果使用HDMA,那么只能搬运频率或者占空比的数据。
除了HPM5300之外其他的MCU都支持XDMA和HDMA。DMA_SOC_MAX_COUNT就是代表有几个DMA设备。
这里gptmr的config除了开启PWM测量模式,也需要开启DMA请求(输入捕获发生DMA请求)
在DMA配置中,需要配置DMA的设备地址指向GPTMR的周期计数器寄存器,并且使用握手模式(只有发生DMA请求才搬运),源地址指向搬运的缓存。并且设置好对应的数据宽度,如果使用XDMA则是64bit,HDMA是32bit。可参考sample的DMA配置
如此一来,当DMA传输指定的PWM脉冲数量时,发生DMA传输完成,这时可批量去处理搬运的信号周期和占空比数据,实现CPU 0参与。