打印
[综合信息]

【分享】HC32F072 两路互补带死区PWM输出

[复制链接]
1561|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
今天和大家分享的内容有两点:1.互补pwm驱动;
2.pwm输出运行过程中,周期变换瞬间产生的不稳定高电平的解决办法。
#include "bsp_pwm.h"
#include "bsp_led.h"

//Timer0 配置
static void App_Timer0Cfg(uint16_t u16Period, en_bt_cr_timclkdiv_t pclk_div, uint16_t u16CHxACompare, uint16_t DeadTime)
{
    uint16_t                   u16CntValue;
    uint8_t                    u8ValidPeriod;
    stc_bt_mode23_cfg_t        stcBtBaseCfg;
    stc_bt_m23_compare_cfg_t   stcBtPortCmpCfg;
    stc_bt_m23_adc_trig_cfg_t  stcBtTrigAdc;
    stc_bt_m23_dt_cfg_t        stcBtDeadTimeCfg;

        stc_bt_m23_bk_input_cfg_t  stcBtBrakeCfg;
       
    DDL_ZERO_STRUCT(stcBtBaseCfg);
    DDL_ZERO_STRUCT(stcBtPortCmpCfg);
    DDL_ZERO_STRUCT(stcBtTrigAdc);
    DDL_ZERO_STRUCT(stcBtDeadTimeCfg);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE);   //Base Timer外设时钟使能      
        
    stcBtBaseCfg.enWorkMode    = BtWorkMode3;              //三角波模式
    stcBtBaseCfg.enCT          = BtTimer;                  //定时器功能,计数时钟为内部PCLK
    stcBtBaseCfg.enPRS         = pclk_div;//BtPCLKDiv16;   //PCLK/x 分频
    //stcBtBaseCfg.enCntDir    = BtCntUp;                  //向上计数,在三角波模式时只读
    stcBtBaseCfg.enPWMTypeSel  = BtComplementaryPWM;       //互补输出PWM
    stcBtBaseCfg.enPWM2sSel    = BtSinglePointCmp;         //单点比较功能
    stcBtBaseCfg.bOneShot      = FALSE;                    //循环计数
    stcBtBaseCfg.bURSSel       = FALSE;                    //上下溢更新
   
    Bt_Mode23_Init(TIM0, &stcBtBaseCfg);                   //TIM0 的模式23功能初始化
   
    Bt_M23_ARRSet(TIM0, u16Period, TRUE);                  //设置重载值,并使能缓存

    Bt_M23_CCR_Set(TIM0, BtCCR0A, u16CHxACompare);         //设置比较值A,(PWM互补模式下只需要设置比较值A)
   
    stcBtPortCmpCfg.enCH0ACmpCtrl   = BtPWMMode2;          //OCREFA输出控制OCMA:PWM模式2
    stcBtPortCmpCfg.enCH0APolarity  = BtPortPositive;      //正常输出
    stcBtPortCmpCfg.bCh0ACmpBufEn   = TRUE;                //A通道缓存控制
    stcBtPortCmpCfg.enCh0ACmpIntSel = BtCmpIntNone;        //A通道比较控制:无
   
    stcBtPortCmpCfg.enCH0BCmpCtrl   = BtPWMMode2;          //OCREFB输出控制OCMB:PWM模式2(PWM互补模式下也要设置,避免强制输出)
    stcBtPortCmpCfg.enCH0BPolarity  = BtPortPositive;      //正常输出
    //stcBtPortCmpCfg.bCH0BCmpBufEn   = TRUE;              //B通道缓存控制使能
    stcBtPortCmpCfg.enCH0BCmpIntSel = BtCmpIntNone;        //B通道比较控制:无
               
    Bt_M23_PortOutput_Cfg(TIM0, &stcBtPortCmpCfg);         //比较输出端口配置

        stcBtBrakeCfg.bEnBrake = TRUE;  /*刹车使能*/
        stcBtBrakeCfg.enBkCH0AStat = BtCHxBksLow; /*IO输出为低*/
        stcBtBrakeCfg.enBkCH0BStat = BtCHxBksLow; /*IO输出为低*/
        Bt_M23_BrakeInput_Cfg(TIM0, &stcBtBrakeCfg);
       
    u8ValidPeriod = 1;                                     //事件更新周期设置,0表示三角波每半个周期更新一次,每+1代表延迟半个周期
    Bt_M23_SetValidPeriod(TIM0,u8ValidPeriod);             //间隔周期设置
   
    stcBtDeadTimeCfg.bEnDeadTime      = TRUE;
    stcBtDeadTimeCfg.u8DeadTimeValue  = DeadTime;
    Bt_M23_DT_Cfg(TIM0, &stcBtDeadTimeCfg);             //死区配置
   
    u16CntValue = 0;
   
    Bt_M23_Cnt16Set(TIM0, u16CntValue);                    //设置计数初值
   
    Bt_ClearAllIntFlag(TIM0);                              //清中断标志
    Bt_Mode23_EnableIrq(TIM0,BtUevIrq);                    //使能TIM0 UEV更新中断
    EnableNvic(TIM0_IRQn, IrqLevel0, TRUE);                //TIM0中断使能   
}

//端口配置初始化
static void BSP_Timer0PortCfg(void)
{
    stc_gpio_cfg_t             stcTIM0Port;
   
    //结构体初始化清零
    DDL_ZERO_STRUCT(stcTIM0Port);
   
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //GPIO 外设时钟使能
  
    stcTIM0Port.enDir  = GpioDirOut;
   
    Gpio_Init(GpioPortA, GpioPin0, &stcTIM0Port);
    Gpio_SetAfMode(GpioPortA,GpioPin0,GpioAf7);            //PA00设置为TIM0_CHA
   
    Gpio_Init(GpioPortA, GpioPin1, &stcTIM0Port);
    Gpio_SetAfMode(GpioPortA,GpioPin1,GpioAf3);            //PA01设置为TIM0_CHB
}

/*带死区的周期4ms的互补PWM*/
void BSP_PWM_Config(void)
{          
        App_Timer0Cfg(6000, BtPCLKDiv16,3000,0x80);  //Timer0 配置:周期 6000(T= 4ms); 通道A比较值2400; 通道B比较值互补模式不需要设置   
    BSP_Timer0PortCfg();                                    //Timer0 Port端口配置   
        Bt_M23_EnPWM_Output(TIM0, TRUE, FALSE);              //TIM0 端口输出使能  
    Bt_M23_Run(TIM0);                             //TIM0 运行
}


/*带死区的2路互补pwm输出(250ms+150usHighPuls)*/
void BSP_2Comp_PWM_Config(void)
{
        uint16_t BCompare = 100; // 理论计算值为15
        App_Timer0Cfg(23700, BtPCLKDiv256, 23700 - BCompare, 0x80);  // 通道B比较值互补模式不需要设置   
    BSP_Timer0PortCfg();                                  //Timer0 Port端口配置      
    Bt_M23_EnPWM_Output(TIM0, TRUE, FALSE);    //TIM0 端口输出使能  
    Bt_M23_Run(TIM0);                          //TIM0 运行
}

/*duty : 0~99*/
void BSP_PWM_SetDuty(uint8_t duty)
{                       
        Bt_M23_CCR_Set(TIM0, BtCCR0A, 6000 - 6000*duty/100); //设置通道A比较值
}


/*******************************************************************************
* TIM0中断服务函数
******************************************************************************/
void Tim0_IRQHandler(void)
{
    //Timer0 模式23 更新中断
    if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))
    {  
        Bt_ClearIntFlag(TIM0,BtUevIrq);  //清中断标志               
    }
}


pwm周期变换的时候我们想到的做法是:
1. 使能PWm刹车;
2. 重新初始化IO并拉低;
3.再初始化PWM定时器(更改了分频系数);
按顺序执行后,并不奏效,切换瞬间还是有杂乱偶现的高电平。

使用特权

评论回复
沙发
caizhiwei|  楼主 | 2020-6-10 20:28 | 只看该作者
解决办法是,从新复位定时器外设即可。
Reset_RstPeripheral0(ResetMskBaseTim);

使用特权

评论回复
板凳
wkei007| | 2020-6-23 17:18 | 只看该作者
caizhiwei 发表于 2020-6-10 20:28
解决办法是,从新复位定时器外设即可。

这个复位函数,不是BSP提供的?你自己定的复位吗?

使用特权

评论回复
地板
caizhiwei|  楼主 | 2020-6-23 18:00 | 只看该作者
wkei007 发表于 2020-6-23 17:18
这个复位函数,不是BSP提供的?你自己定的复位吗?

是driver目录下的,直接调用。

使用特权

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

本版积分规则

100

主题

857

帖子

14

粉丝