[综合信息] 【分享】HC32F072 两路互补带死区PWM输出

[复制链接]
 楼主| caizhiwei 发表于 2020-6-10 20:26 | 显示全部楼层 |阅读模式
今天和大家分享的内容有两点:1.互补pwm驱动;
2.pwm输出运行过程中,周期变换瞬间产生的不稳定高电平的解决办法。
  1. #include "bsp_pwm.h"
  2. #include "bsp_led.h"

  3. //Timer0 配置
  4. static void App_Timer0Cfg(uint16_t u16Period, en_bt_cr_timclkdiv_t pclk_div, uint16_t u16CHxACompare, uint16_t DeadTime)
  5. {
  6.     uint16_t                   u16CntValue;
  7.     uint8_t                    u8ValidPeriod;
  8.     stc_bt_mode23_cfg_t        stcBtBaseCfg;
  9.     stc_bt_m23_compare_cfg_t   stcBtPortCmpCfg;
  10.     stc_bt_m23_adc_trig_cfg_t  stcBtTrigAdc;
  11.     stc_bt_m23_dt_cfg_t        stcBtDeadTimeCfg;

  12.         stc_bt_m23_bk_input_cfg_t  stcBtBrakeCfg;
  13.        
  14.     DDL_ZERO_STRUCT(stcBtBaseCfg);
  15.     DDL_ZERO_STRUCT(stcBtPortCmpCfg);
  16.     DDL_ZERO_STRUCT(stcBtTrigAdc);
  17.     DDL_ZERO_STRUCT(stcBtDeadTimeCfg);

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

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

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

  65. //端口配置初始化
  66. static void BSP_Timer0PortCfg(void)
  67. {
  68.     stc_gpio_cfg_t             stcTIM0Port;
  69.    
  70.     //结构体初始化清零
  71.     DDL_ZERO_STRUCT(stcTIM0Port);
  72.    
  73.     Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //GPIO 外设时钟使能
  74.   
  75.     stcTIM0Port.enDir  = GpioDirOut;
  76.    
  77.     Gpio_Init(GpioPortA, GpioPin0, &stcTIM0Port);
  78.     Gpio_SetAfMode(GpioPortA,GpioPin0,GpioAf7);            //PA00设置为TIM0_CHA
  79.    
  80.     Gpio_Init(GpioPortA, GpioPin1, &stcTIM0Port);
  81.     Gpio_SetAfMode(GpioPortA,GpioPin1,GpioAf3);            //PA01设置为TIM0_CHB
  82. }

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


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

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


  105. /*******************************************************************************
  106. * TIM0中断服务函数
  107. ******************************************************************************/
  108. void Tim0_IRQHandler(void)
  109. {
  110.     //Timer0 模式23 更新中断
  111.     if(TRUE == Bt_GetIntFlag(TIM0, BtUevIrq))
  112.     {  
  113.         Bt_ClearIntFlag(TIM0,BtUevIrq);  //清中断标志               
  114.     }
  115. }


pwm周期变换的时候我们想到的做法是:
1. 使能PWm刹车;
2. 重新初始化IO并拉低;
3.再初始化PWM定时器(更改了分频系数);
按顺序执行后,并不奏效,切换瞬间还是有杂乱偶现的高电平。
260545ee0d1662bd8f.png
 楼主| caizhiwei 发表于 2020-6-10 20:28 | 显示全部楼层
解决办法是,从新复位定时器外设即可。
  1. 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

帖子

16

粉丝
快速回复 返回顶部 返回列表