[GPTMR]PWM生成
gptmr每个通道能够通道输出比较器支持可以生成边沿对齐PWM或者中心对齐PWM;每个通道通过软件和硬件同步支持可以生成互补或者同步PWM;GPTMR支持事件触发DMA请求(比如重装载事件、计数器比较事件、输入捕获事件),通过DMA请求更改GPTMR的RLD重载载值或者比较器值,可以实现类似加减速脉冲功能。
本PWM生成的文章主要参考hpm_sdk以下例子:
counter_sync: 定时器同步计数器产生两路同步PWM
pwm_generate: 定时器生成PWM
二、GPTMR定时器PWM功能讲解
寄存器说明参考先楫用户手册,这里不做截图和阐述。
在使用GPTMR输出PWM之前,必须做以下初始化
1、确保打开了GPTMR的工作时钟,保证GPTMR正常工作
比如打开gptmr3的工作时钟即可,在sdk中可以参考:
这里的工作时钟的时钟源来源于默认pll,比如HPM5300系列,对于gptmr的时钟源默认就是PLL1CLK0,8分频得到100MHz工作时钟,故也可不用设置pll。
若需要手工更改pll,也可使用先楫的clock tool配置:
链接:https://tools.hpmicro.com/clock
比如以下,选择使用PLL0CLK2作为时钟源,经过四分频后也可以得到gptmr的100M工作频率。最后配置完成点击生成clock代码即可。
2、使能对应的输出引脚的Pinmux功能为compare比较输出
在sdk中可参考每个board的pinmux的gptmr pins初始化,比如对应的hpm5300evk。
这里就是设置了PB07的pimmux功能为GPTMR0的通道0比较输出
如果不想自己动手,也可以使用使用先楫的pinmux tool 配置:
链接:https://tools.hpmicro.com/pinmux
比如使用GPTMR0的四个通道。最后配置完成点击生成pinmux代码即可。
参考先楫用户手册以及HPM_SDK对于PWM生成的配置,可以总结以下步骤:
1、设置两个比较器CHANNEL[CMP]寄存器缺省初始值,确保输出正常。
2、设置CHANNEL[CR]寄存器的CEN位,配置关闭计数器。
3、设置CHANNEL[CR]寄存器的CNTRST位,复位计数器。
4设置IRQEN寄存器的CHxCMPxEN位,中断使能配置。
5、设置CHANNEL[CR]寄存器的CMPINIT位,配置输出通道的初始极性逻辑高或者低。
6、设置CHANNEL[CR]寄存器的CMPEN位,配置通道输出使能。
7、设置CHANNEL[RLD]的寄存器值,配置PWM的周期。
8、设置CHANNEL[CMP]的寄存器值,配置PWM的占空比。
9、设置CHANNEL[CR]寄存器的CEN位,配置启动计数器。
使用比较器的比较输出功能生成PWM波,配置GPTMR的工作时钟为100MHz。
假设计数频率为TMR_FREQ,需要生成的PWM频率为PWM_FREQ,那么配置CHANNEL[RLD] 为:
使用GPTMR定时器生成100Khz,50%占空比的边沿对齐PWM波, 初始输出电平为高电平。
1、设置两个比较器CHANNEL[CMP]寄存器缺省初始值:CHANNEL[CMP0] = 0xFFFFFFF0,CHANNEL[CMP1] = 0xFFFFFFF0。
3、复位计数器 CHANNEL[CR].CNTRST = 1,复位后需要清零释放复位CHANNEL[CR].CNTRST = 0。
4、关闭通道比较器0和比较器1标志位中断使能位 IRQEN.CHxCMP0EN = 0,IRQEN.CHxCMP1EN = 0。
5、设置输出通道的初始极性逻辑高 CHANNEL[CR].CMPINT = 1。
6、使能通道输出比较 CHANNEL[CR].CMPEN = 1。
7、设置重载值 CHANNEL[RLD] = 999(100MHz/100KHz - 1,计数器从0开始),配置PWM的周期频率为100Khz。
8、设置CHANNEL[CMP1] = CHANNEL[RLD] = 999,配置CMP1值等于RLD值。
9、设置CHANNEL[CMP0] = ((CHANNEL[RLD] + 1) * 50)/ 100 - 1 = 499, 配置PWM的占空比为50%。
10、开启计数器,开启计数, CHANNEL[CR].CEN = 1。
在hpm_sdk中的gptmr的例子pwm_generate中,使用的就是边沿对齐PWM,例子中封装了频率生成和占空比生成的接口,频率和占空比参数转换为gptmr对应的reload重装载值和输出比较值
使用GPTMR定时器生成1Mhz,40%占空比的中心对齐PWM波, 初始输出电平为低电平。
两个比较器的差值需要满足以下: 0 < CHANNEL[CMP0] < CHANNEL[CMP1] < CHANNEL[RLD]
1、设置两个比较器CHANNEL[CMP]寄存器缺省初始值:CHANNEL[CMP0] = 0xFFFFFFF0,CHANNEL[CMP1] = 0xFFFFFFF0。
3、复位计数器 CHANNEL[CR].CNTRST = 1,复位后需要清零释放复位CHANNEL[CR].CNTRST = 0。
4、关闭通道比较器0和比较器1标志位中断使能位 IRQEN.CHxCMP0EN = 0,IRQEN.CHxCMP1EN = 0。
5、设置输出通道的初始极性逻辑低 CHANNEL[CR].CMPINT = 0。
6、使能通道输出比较 CHANNEL[CR].CMPEN = 1。
7、设置重载值 CHANNEL[RLD] = 99(100MHz/1MHz - 1,计数器从0开始),配置PWM的周期频率为1Mhz。
8、设置占空比为40%,两个比较值的差值应该为:(RLD + 1) * 40 / 100 = 40,比如可以设置为以下:
9、开启计数器,开启计数, CHANNEL[CR].CEN = 1。
定时器支持同步触发输入(SYNCI),分为软件同步和硬件同步,用来同步计数器开始计数的时刻,当同步输入触发时,对应的通道计数器发生重载,也随之从0开始计数。
这里利用软件同步实现通道0和通道1的PWM同步输出,如下框图所示:
寄存器配置步骤:以sdk中的gptmr的例子counter_sync为参考
2、设置CHANNEL[CR].SWSYNCIEN = 1,使能软件计数器同步。
3、设置GCR.SWSYNCTx = '0b0011',设置通道0和通道1计计数器重载。使用gptmr_trigger_channel_software_sync API
运行counter_sync例子查看波形,可看到两个通道波形是同步的
若要两个通道输出的PWM是互补的,只需要设置输出初始化极性电平两者相反即可,在sdk的驱动中,cmp_initial_polarity_high的成员就是设置初始化极性电平。