打印
[技术问答]

华大HC32F130在使用TIM4/5/6高级定时器时,PWM极性不受控

[复制链接]
2045|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
doublesan|  楼主 | 2020-5-24 20:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
大家好,我在使用HC32F130和HC32F030的TIM4/5/6定时器做PWM功能时,使用了缓存,发出的PWM信号的极性不受控,有时候是高有效,有时候是低有效,完全不受控,用起来很受伤,炸了好几次管子,求玩过的行家指点迷津!

使用特权

评论回复
沙发
martinhu| | 2020-5-25 08:57 | 只看该作者
中途停止定时器又启动了吗?贴一下代码看看?

使用特权

评论回复
板凳
doublesan|  楼主 | 2020-5-25 09:22 | 只看该作者
martinhu 发表于 2020-5-25 08:57
中途停止定时器又启动了吗?贴一下代码看看?

没有停止定时器呢,基本是按照华大案例库给的代码来做的,太邪门了,都不敢用他的所谓的高级定时器了,用其他厂家芯片从来没遇到过这种问题。相关代码如下。
/******************************************************************************
Function Name               :        ISR_Timer5ForInvCfg
--------------------------------------------------------------------------------
Function Descriptions        :        Timer5端口初始化,用于驱动信号
Parameter Name list         :
ReturnType                  :
Refer documents             :
******************************************************************************/
void ISR_Timer5ForInvCfg(uint16_t u16Period, uint16_t u16CHA_PWMDuty, uint16_t u16CHB_PWMDuty)
{
    en_adt_compare_t          enAdtCompare;
    stc_adt_basecnt_cfg_t     stcAdtBaseCntCfg;
    stc_adt_irq_trig_cfg_t    stcAdtIrqTrigCfg;
//    stc_adt_CHxX_port_cfg_t   stcAdtTIM5ACfg;
//    stc_adt_CHxX_port_cfg_t   stcAdtTIM5BCfg;

    DDL_ZERO_STRUCT(stcAdtBaseCntCfg);
    DDL_ZERO_STRUCT(stcAdtIrqTrigCfg);
    DDL_ZERO_STRUCT(stcAdtTimer5ACfg);
    DDL_ZERO_STRUCT(stcAdtTimer5BCfg);
   
    Sysctrl_SetPeripheralGate(SysctrlPeripheralAdvTim, TRUE);     //ADT外设时钟使能

    stcAdtBaseCntCfg.enCntMode = AdtTriangleModeA;                //三角波A
    stcAdtBaseCntCfg.enCntDir = AdtCntUp;
    stcAdtBaseCntCfg.enCntClkDiv = AdtClkPClk0;     // AdtClkPClk0Div2
   
    Adt_Init(M0P_ADTIM5, &stcAdtBaseCntCfg);                      //ADT载波、计数模式、时钟配置
   
    Adt_SetPeriod(M0P_ADTIM5, u16Period);                         //周期值

    enAdtCompare = AdtCompareA;
    Adt_SetCompareValue(M0P_ADTIM5, enAdtCompare, u16CHA_PWMDuty);    //通用比较基准值寄存器A设置

    enAdtCompare = AdtCompareB;
    Adt_SetCompareValue(M0P_ADTIM5, enAdtCompare, u16CHB_PWMDuty);    //通用比较基准值寄存器B设置
   
    enAdtCompare = AdtCompareC;
    Adt_SetCompareValue(M0P_ADTIM5, enAdtCompare, u16CHA_PWMDuty);    //通用比较基准值寄存器C设置

    Adt_EnableValueBuf(M0P_ADTIM5, AdtCHxA, TRUE);    //缓存传送A使能 GCMCR--->GCMAR,三角波A模式在下溢点传送
    //Adt_EnableValueBuf(M0P_ADTIM5, AdtCHxB, TRUE);  //缓存传送B不需要设置,因为GCMBR由GCMAR和死区时间计算得到

    stcAdtTimer5ACfg.enCap = AdtCHxCompareOutput;    //比较输出模式
    stcAdtTimer5ACfg.bOutEn = FALSE;                  //CHA输出使能
    stcAdtTimer5ACfg.enPerc = AdtCHxPeriodKeep;      //计数值与周期匹配时CHA电平保持不变
    stcAdtTimer5ACfg.enCmpc = AdtCHxCompareInv;      //计数值与比较值A匹配时,CHA电平翻转
    stcAdtTimer5ACfg.enStaStp = AdtCHxStateSelSS;    //CHA起始结束电平由STACA与STPCA控制
    stcAdtTimer5ACfg.enStaOut = AdtCHxPortOutLow;    //CHA起始电平为低
    stcAdtTimer5ACfg.enStpOut = AdtCHxPortOutLow;    //CHA结束电平为低
    Adt_CHxXPortCfg(M0P_ADTIM5, AdtCHxA, &stcAdtTimer5ACfg);   //端口CHA配置

    stcAdtTimer5BCfg.enCap = AdtCHxCompareOutput;
    stcAdtTimer5BCfg.bOutEn = FALSE;
    stcAdtTimer5BCfg.enPerc = AdtCHxPeriodKeep;
    stcAdtTimer5BCfg.enCmpc = AdtCHxCompareInv;
    stcAdtTimer5BCfg.enStaStp = AdtCHxStateSelSS;
    stcAdtTimer5BCfg.enStaOut = AdtCHxPortOutHigh;   //CHB起始电平为高(为了上下桥互补)
    stcAdtTimer5BCfg.enStpOut = AdtCHxPortOutLow;    //CHB结束电平为低
    Adt_CHxXPortCfg(M0P_ADTIM5, AdtCHxB, &stcAdtTimer5BCfg);   //端口CHB配置

    Adt_SetDTUA(M0P_ADTIM5, INV_PWM_DB);  //CNT向上计数时的死区时间,GCMBR = GCMAR - DTUAR
    Adt_SetDTDA(M0P_ADTIM5, INV_PWM_DB);  //CNT向下计数时的死区时间,GCMBR = GCMAR - DTDAR
    Adt_CfgDT(M0P_ADTIM5, TRUE, TRUE); //中断使能,并且DTUAR和DTDAR自动相等
   
//    Adt_ClearAllIrqFlag(M0P_ADTIM5);          //清标志位
//    Adt_CfgIrq(M0P_ADTIM5, AdtUDFIrq, TRUE);  //下溢中断配置
//    EnableNvic(ADTIM5_IRQn, IrqLevel3, TRUE); //使能AdvTimer4 中断

    stcAdtIrqTrigCfg.bAdtOverFlowTrigEn = TRUE;
    Adt_IrqTrigCfg(M0P_ADTIM5, &stcAdtIrqTrigCfg);          // 上溢中断触发ADC  
}

void PPINV_InvEnable()
{
    stcAdtTimer5ACfg.bOutEn = TRUE;                  //CHAÊä³öʹÄÜ FALSE;
    stcAdtTimer5BCfg.bOutEn = TRUE;  
    stcAdtTimer6ACfg.bOutEn = TRUE;                  //CHAÊä³öʹÄÜ FALSE;
    stcAdtTimer6BCfg.bOutEn = TRUE;

        Gpio_ClrIO(GpioPortA,GpioPin9);
    Gpio_ClrIO(GpioPortB,GpioPin0);
    Gpio_ClrIO(GpioPortA,GpioPin10);
        Gpio_ClrIO(GpioPortB,GpioPin1);
       
    Adt_CHxXPortCfg(M0P_ADTIM5, AdtCHxA, &stcAdtTimer5ACfg);   //¶Ë¿ÚCHAÅäÖÃ
    Adt_CHxXPortCfg(M0P_ADTIM5, AdtCHxB, &stcAdtTimer5BCfg);   //¶Ë¿ÚCHBÅäÖÃ
    Adt_CHxXPortCfg(M0P_ADTIM6, AdtCHxA, &stcAdtTimer6ACfg);   //¶Ë¿ÚCHAÅäÖÃ
    Adt_CHxXPortCfg(M0P_ADTIM6, AdtCHxB, &stcAdtTimer6BCfg);   //¶Ë¿ÚCHBÅäÖÃ
}

void PPINV_InvDisable(void)
{
    stcAdtTimer5ACfg.bOutEn = FALSE;                  //CHAÊä³öʹÄÜ FALSE;
    stcAdtTimer5BCfg.bOutEn = FALSE;  
    stcAdtTimer6ACfg.bOutEn = FALSE;                  //CHAÊä³öʹÄÜ FALSE;
    stcAdtTimer6BCfg.bOutEn = FALSE;

    Adt_CHxXPortCfg(M0P_ADTIM5, AdtCHxA, &stcAdtTimer5ACfg);   //¶Ë¿ÚCHAÅäÖÃ
    Adt_CHxXPortCfg(M0P_ADTIM5, AdtCHxB, &stcAdtTimer5BCfg);   //¶Ë¿ÚCHBÅäÖÃ
    Adt_CHxXPortCfg(M0P_ADTIM6, AdtCHxA, &stcAdtTimer6ACfg);   //¶Ë¿ÚCHAÅäÖÃ
    Adt_CHxXPortCfg(M0P_ADTIM6, AdtCHxB, &stcAdtTimer6BCfg);   //¶Ë¿ÚCHBÅäÖÃ
    Gpio_ClrIO(GpioPortA,GpioPin9);
    Gpio_ClrIO(GpioPortB,GpioPin0);
    Gpio_ClrIO(GpioPortA,GpioPin10);
        Gpio_ClrIO(GpioPortB,GpioPin1);
}

更新PWM信号是下面这一段
        Adt_SetCompareValue(M0P_ADTIM5, AdtCompareC, INV_PWM_PEROND - g_sInvPwmDuty);
        Adt_SetCompareValue(M0P_ADTIM6, AdtCompareC, g_sInvPwmDuty);  

使用特权

评论回复
地板
martinhu| | 2020-5-25 09:35 | 只看该作者
这几个初始化的值是多少?? 初始化的时候,不可以设置为0xFFFF
    enAdtCompare = AdtCompareA;
    Adt_SetCompareValue(M0P_ADTIM5, enAdtCompare, u16CHA_PWMDuty);    //通用比较基准值寄存器A设置
    enAdtCompare = AdtCompareB;
    Adt_SetCompareValue(M0P_ADTIM5, enAdtCompare, u16CHB_PWMDuty);    //通用比较基准值寄存器B设置
   
    enAdtCompare = AdtCompareC;
    Adt_SetCompareValue(M0P_ADTIM5, enAdtCompare, u16CHA_PWMDuty);    //通用比较基准值寄存器C设置

使用特权

评论回复
5
martinhu| | 2020-5-25 09:44 | 只看该作者
如果是L130或者F030的话,我觉得用Timer3比较好,timer3_m23_pwm_adc这个例子。

使用特权

评论回复
评论
doublesan 2020-5-25 11:04 回复TA
@martinhu :我之前是在开发板上验证过发波这些问题的,后面就做了自己的板子,结果拿回来遇到这个问题,很头疼啊,Timer0/1/2现在也复用不上了,所以只能是把TIM4/5/6的应用问题解决。不然改板的周期很长,很不划算。 
martinhu 2020-5-25 10:36 回复TA
@doublesan :还有Timer0/1/2 
doublesan 2020-5-25 09:56 回复TA
是啊,后面我被迫改为了TIMER3来做了,但是只能改一组,另外一组PWM信号的频率不一样,不能两组都用TIMER3来处理。 
6
doublesan|  楼主 | 2020-5-25 09:50 | 只看该作者
martinhu 发表于 2020-5-25 09:35
这几个初始化的值是多少?? 初始化的时候,不可以设置为0xFFFF
    enAdtCompare = AdtCompareA;
    Adt_ ...

给的都是0呢,周期和占空比设置一般很少会设到0xFFFF,都是根据自己需要的频率进行相应的计算得到的
        ISR_Timer5PortCfg();
        ISR_Timer5ForInvCfg(INV_PWM_PEROND, 0, 0);
        ISR_Timer6PortCfg();
        ISR_Timer6ForInvCfg(INV_PWM_PEROND, 0, 0);

使用特权

评论回复
评论
martinhu 2020-5-25 11:22 回复TA
@doublesan :功能很强大,不过需要结合手册,多用用例子,以加深理解。 
doublesan 2020-5-25 10:59 回复TA
@martinhu :好的,先按您说的方法试验一下,看是否有效果!另外,我比较好奇华大的这个TIM4/5/6功能是不完善吗?用户手册里这方便的框图给的也不完善,没什么指导性! 
martinhu 2020-5-25 10:33 回复TA
也不要给0 ,给一个中间的数值,启动时候,先让timer跑起来,然后可以赋值0xFFFF,然后再使能PWM输出 
7
sgrtf661| | 2020-5-25 15:07 | 只看该作者
我是代理 可以加我qq:409946461做技术支持

使用特权

评论回复
8
晓伍| | 2020-6-8 15:22 | 只看该作者
会不会有一个时效的问题

使用特权

评论回复
9
磨砂| | 2020-6-8 15:24 | 只看该作者
不使用缓存的话有改善吗

使用特权

评论回复
10
木木guainv| | 2020-6-8 15:24 | 只看该作者
还没有用过这个

使用特权

评论回复
11
OKWEI98| | 2020-11-23 09:17 | 只看该作者
看来不是我一个遇到这问题了

使用特权

评论回复
12
wqh317954897| | 2020-11-23 09:22 | 只看该作者
下桥臂采样 同样遇到极性变化的问题

使用特权

评论回复
13
中子家| | 2020-11-23 09:46 | 只看该作者
martinhu 发表于 2020-5-25 09:35
这几个初始化的值是多少?? 初始化的时候,不可以设置为0xFFFF
    enAdtCompare = AdtCompareA;
    Adt_ ...

这个是什么原理呢?为啥初始的时候不能设置0xffff,有点好奇

使用特权

评论回复
评论
martinhu 2020-12-3 13:28 回复TA
@中子家 :是应用笔记,不是用户手册,另外,如果你是定时器运行过程中改变占空比,那么一定要使能缓存传送,不然就会发生极性反转的现象。这个是由ADT的输出电平逻辑特性决定的。 
中子家 2020-12-2 14:17 回复TA
@martinhu :我没开硬件死区也有这个现象,请问是什么原因?另外,我看到的手册并没有说明这个问题,请问在哪一页 
martinhu 2020-12-2 10:39 回复TA
@中子家 :你可以自己测试一下,在应用笔记里面有描述 
中子家 2020-11-30 10:28 回复TA
@martinhu :这个好像在手册里没有说吧 
martinhu 2020-11-28 21:44 回复TA
开了硬件死区之后有这个限制 
14
laocuo1142| | 2020-11-24 13:49 | 只看该作者
这个问题很奇怪,没遇到过

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

18

主题

54

帖子

1

粉丝