|
这篇文章将来测评HC32F448的高级定时器6输出任意频率和占空比的PWM波、一组互补的PWM波、一组互补的带死区PWM波。
首先Timer6支持的时钟为200MHz,理论上在锯齿波计数模式下,最高能输出单边对齐的占空比50%的100MHz方波;在三角波计数模式下,最高能输出对称的占空比50%的50MHz方波。原因在于在锯齿波计数模式下,周期值可以设置为2,对比值为1,当上溢到周期值后,一个PWM波就生成完毕了。而在锯齿波计数模式下,周期值可以设置为2,对比值为1,当上溢到周期值后,只生成了半个PWM波,当下溢到周期值后,又生成了半个,这样才是完整的PWM波。(以计数值从0到溢出再到0为例)
这里需要知道人家通用周期基准值寄存器有3个(TMR6_PERAR、TMR6_PERBR、TMR6_PERCR),通用比较基准值寄存器有6个(TMR6_GCMAR、TMR6_GCMBR、TMR6_GCMCR、TMR6_GCMDR、TMR6_GCMER、TMR6_GCMFR)
而单缓存的作用在于在发生递加计数上溢点或递减计数下溢点等缓存传送节点时将PERBR的值更新至PERAR,将GCMCR的值更新至GCMAR,将GCMDR的值更新至GCMBR。
双缓存是在缓存传送节点时将PERCR的值更新至PERBR,将PERBR的值更新至PERAR,将GCMER的值更新至GCMCR,将GCMCR的值更新至GCMAR,将GCMFR的值更新至GCMDR。将GCMDR的值更新至GCMBR。
上面说的是比较输出,捕获输入的方向与之相反。
我认为缓存的意义在于可以快速的准确的更新比较值大小,也就是占空比,因为它是在一个完整的PWM波过后更新的,不会影响前一个PWM波的完整性。但经过实际测试,我感觉优势不大,或者说在我这种使用常见下并没有什么用,下面我会说的。
---------------------------------------------------------------------------------------开始移植------------------------------------------------------------------------------------------
这里需要用到的资源包括定时器6。
首先,在Hardware文件夹中新建Timer6.c等C文件及其对应的h头文件。同时还要添加hc32_ll_tmr6.c的库函数。还要记得使能hc32f4xx_conf.h的对应组件。
Timer6的初始化大致分为
这里我挑几个讲,其他可以看我提供的测试程序。
首先是设置时钟源,这个设置合适的分频数和周期数,因为周期基准寄存器(如TMR6_PERAR)只有16位,PeriodValue最多设置65536,所以你的最低频率是200MHz / ClockDiv / 65536,最低频率是200MHz / ClockDiv ,我这里就选择不分频,这样好计算一些,同时频率可以设置较高。然后设置周期数PeriodValue,也就是决定输出频率,有两种方式,如下图所示,我推荐第2种,这样修改起来更方便。还有一点需要注意,在三角波计数模式下,实际输出的频率为200MHz / (2*PeriodValue),具体原因如开头介绍的。
缓存模式我这里选择不使能,具体原因我下面会测试。
缓存时间配置有下面4种,下图1,具体寄存器及定义如下图2
设置PWM的起始、溢出等极性,个人觉得比较重要的是CompareValue、StartPolarity、StopPolarity、CountUpMatchAPolarity、CountDownMatchAPolarity、CountUpMatchBPolarity、CountDownMatchBPolarity。CompareValue也就是比较值也有两种方式,推荐第二种
StartPolarity、StopPolarity决定了起始和停止的输出极性,
如果StartPolarity=TMR6_PWM_HIGH,StopPolarity=TMR6_PWM_HIGH,
那么你设置的比较值决定了正占空比;
如果StartPolarity=TMR6_PWM_LOW,StopPolarity=TMR6_PWM_LOW,
那么你设置的比较值决定了负占空比;
CountUpMatchAPolarity、CountDownMatchAPolarity、CountUpMatchBPolarity、CountDownMatchBPolarity这4个参数决定了上溢或者下溢时的PWM极性。有以下4种配置
#define TMR6_PWM_LOW (0x00U)
#define TMR6_PWM_HIGH (0x01U)
#define TMR6_PWM_HOLD (0x02U)
#define TMR6_PWM_INVT (0x03U)
对于PWMA,其对应的比较值寄存器为GCMAR时,当溢出时要翻转,当比较值寄存器GCMBR溢出时要保持;同样的,对于PWMB,其对应的比较值寄存器为GCMBR时,当溢出时要翻转,当比较值寄存器GCMAR溢出时要保持,具体程序如下图。
-------------------------------------------------------------------------------------------实际测试-----------------------------------------------------------------------------------------
1、首先输出10KHz的PWM波,PWMA也就是PA8输出正占空比为40%;PWMB也就是PA7输出负占空比为40%
TMR6_SetPeriodValue(CM_TMR6_1, TMR6_PERIOD_REG_A, 10000);
TMR6_SetCompareValue(CM_TMR6_1, TMR6_CMP_REG_A, 4000U);
TMR6_SetCompareValue(CM_TMR6_1, TMR6_CMP_REG_B, 4000U);
还可以通过按键来切换成输出100KHz的PWM波,PWMA输出正占空比为20%;PWMB输出负占空比为90%
这里也测试了一下缓存传送,
设置stcBufConfig.u32BufTransCond = TMR6_BUF_TRANS_UDF;
然后在初始化程序和按键中关于TMR6_SetCompareValue函数改成
TMR6_SetCompareValue(CM_TMR6_1, TMR6_CMP_REG_C, 2000U);
TMR6_SetCompareValue(CM_TMR6_1, TMR6_CMP_REG_D, 9000U);
还有使能对应缓存传送
TMR6_GeneralBufCmd(CM_TMR6_1, TMR6_CH_A, ENABLE);
TMR6_GeneralBufCmd(CM_TMR6_1, TMR6_CH_B, ENABLE);
其他保持一致,发现实效果跟不开启缓存是一致,我个人觉得还不如不开启缓存传送来的方便,还不需要配置缓存模式,直接修改更方便。
这里需要注意,如果要使用周期基准的缓存传送,需要用到TMR6_PeriodBufConfig()和TMR6_PeriodBufCmd(),上面的程序只配置比较值基准的缓存传送。
然后测试一下死区,具体配置如下
实际测量死区时间为500 *1/200M=2.5us,符合设置。PWMB的负占空比变为了35%。但是我发现不开启死区时间设定,直接将PWMB的比较值改成3500是同样的效果,所以说实际上硬件死区就是确定了PWMA的比较值和死区时间,系统自动算PWMB的比较值,其实道理都一样的。
至此,定时器6和PWM输出就测评好啦,功能还是很强的。