打印
[学习笔记]

AC78系列的PWM通道输出初始状态配置【电机控制极性相关】

[复制链接]
12443|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 wangjj19950516 于 2021-8-26 13:07 编辑

   关于电机驱动的极性,之前写过一篇帖子,介绍了电控的4种极性所需的PWM配置。https://bbs.21ic.com/icview-3044066-1-1.html
  近期发现一点问题,在PWM模块初始化期间会将输出端口的电平拉低,在不同极性下存在烧坏功率器件的风险,比如上桥低有效,下桥低有效。
1.如果驱动极性为上桥高有效,下桥高有效,硬件上会加下拉电阻,上电后在PWM模块初始化之前端口会被拉到低电平,上下桥MOS都处于关闭状态。PWM模块初始化期间也是低电平,不会有导通的风险。
2.如果驱动极性为上桥低有效,下桥低有效,硬件上是加上拉电阻,上电后在PWM模块初始化之前端口被拉到高电平,上下桥MOS处于关闭状态。但在PWM模块初始化期间会将输出拉低,导致上下桥直通,持续时间长的话就会烧坏MOS。
3.如果驱动极性为一高一低,则在PWM模块初始化期间,会同时导通3个上桥或3个下桥,这种情况不会上下桥直通烧坏MOS,但会使电机短暂的处于刹车状态,如果电机处于自由运行状态,会有大电流产生。
下图展示了实际测试波形,配置上下桥都为低有效,外部电路带上拉电阻。黄色为上桥PWM,绿色为下桥PWM,紫色为测试IO口,在PWM模块初始化函数开始时拉高,初始化配置完成后拉低。可以看到在进入PWM初始化之前,两路通道由于外部上拉电阻的原因都为高电平,但在PWM初始化期间被拉低了,持续时间有50us.

既然这样,那在电机应用中就会存在很大的风险。别急,我们的PWM模块考虑到了这种情况,PWM可以配置在初始化期间强制控制通道输出电平,PWM_OUTINIT寄存器配置每个通道的初始输出电平,PWM_FUNCSEL寄存器的INIT位使能该功能
为规避风险,不管电机的驱动极性是哪一种,都应该配置相应的初始输出电平。在使用过程中,应将使能位放在通道输出电平配置的后面,才会生效。



一、AC781X系列配置
下面以上下桥都低有效为例,PWM的CH0,CH2,CH3为上桥,CH1,CH3,CH5为下桥,在初始化配置里最先配置通道初始化并使能,就能在整个初始化期间将通道输出控制为所配置的电平。
void PWM_Initialize(void)
{
  /*首先打开PWM模块时钟 */
        CKGEN_Enable(CLK_PWM2_TIMER, 1);
  CKGEN_Enable(CLK_PWM2_APB, 1);
  CKGEN_SoftReset(SRST_PWM2_APB, 1);
  CKGEN_SoftReset(SRST_PWM2_TIMER, 1);
        /* 根据不同电机极性,配置通道初始输出电平*/
        PWM_OutputInit_Config(PWM2, 0x15);
        /* 使能通道初始输出控制功能 */
        PWM_EnableInitChlOutput(PWM2);
        /* PWM init config*/
    PWM_PWMInit(PWM2, PWM_PWMMODE_COMBINE, PWM_PWM_LOWTRUEPULSE);

    PWM_SetModValue(PWM2, (3000 - 1)); //设置最大计数值
    PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL0, 0);
    PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL2, 0);
    PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL4, 0);
    PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL1, 0);
    PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL3, 0);
    PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL5, 0);

    /* Active Low, down edge input dead time */
    PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL0, 1);
    PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL2, 1);
    PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL4, 1);
    PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL1, 1);
    PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL3, 1);
    PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL5, 1);

    /* 1us Deadtime */
    PWM_PWMDeadtimeSet(PWM2, 2, 24);
    /* PWM Start */
    PWM_ClockSet(PWM2, PWM_CLOCK_SYSTEMCLOCK, 0);
}

二、AC780X系列配置
AC780X系列的驱动库CMSIS1.0.5及以上版本中有该功能的驱动接口,可直接调用,以下版本的需要额外添加几条指令实现,下面一一说明:
1.CMSIS驱动包是1.0.5及以上的:
void Motor_PWM_LOW_LOW(void)
{
         
    PWM_DeInit(PWM1);
    PWM_CombineChConfig chConfig[4];
    PWM_ModulationConfigType pwmConfig;
    PWM_ConfigType config;

    GPIO_SetPinLevel(GPIOC, GPIO_PIN8, 1); //拉高测试端口
   
    /* Config PWM Interface */
    memset(&chConfig, 0, sizeof(chConfig));
    memset(&pwmConfig, 0, sizeof(PWM_ModulationConfigType));
    memset(&config, 0, sizeof(PWM_ConfigType));

    /* channel 0/1 */
    chConfig[0].pairChannel                                     = PWM_CH_0;
    chConfig[0].ch1stValue                                      = 500;
    chConfig[0].ch2ndValue                                      = 500;
    chConfig[0].levelMode                                       = PWM_LOW_TRUE;
    chConfig[0].complementEn                                    = ENABLE;
    chConfig[0].deadtimeEn                                      = ENABLE;
    chConfig[0].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
    chConfig[0].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
    chConfig[0].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[0].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[0].ch1stInitLevel                                  =1;            //配置CH0通道初始输出电平为高电平
    chConfig[0].ch2ndInitLevel                                  =1;           //配置CH1通道初始输出电平为高电平

    /* channel 2/3 */
    chConfig[1].pairChannel                                     = PWM_CH_2;
    chConfig[1].ch1stValue                                      = 500;
    chConfig[1].ch2ndValue                                      = 500;
    chConfig[1].levelMode                                       = PWM_LOW_TRUE;
    chConfig[1].complementEn                                    = ENABLE;
    chConfig[1].deadtimeEn                                      = ENABLE;
    chConfig[1].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
    chConfig[1].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
    chConfig[1].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[1].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[1].ch1stInitLevel                                  =1; //配置CH2通道初始输出电平为高电平
    chConfig[1].ch2ndInitLevel                                  =1;//配置CH3通道初始输出电平为高电平

    /* channel 4/5 */
    chConfig[2].pairChannel                                     = PWM_CH_4;
    chConfig[2].ch1stValue                                      = 500;
    chConfig[2].ch2ndValue                                      = 500;
    chConfig[2].levelMode                                       = PWM_LOW_TRUE;
    chConfig[2].complementEn                                    = ENABLE;
    chConfig[2].deadtimeEn                                      = ENABLE;
    chConfig[2].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
    chConfig[2].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
    chConfig[2].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[2].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[2].ch1stInitLevel                                  =1;//配置CH4通道初始输出电平为高电平
    chConfig[2].ch2ndInitLevel                                  =1;//配置CH5通道初始输出电平为高电平
   
    pwmConfig.initTriggerEn                                     = ENABLE;
    pwmConfig.countMode                                         = PWM_UP_DOWN_COUNT;
    pwmConfig.combineChannelNum                                 = 3;
    pwmConfig.combineChConfig                                   = chConfig;
    pwmConfig.deadtime                                          = 24;
    pwmConfig.deadtimePsc                                       = PWM_DEADTIME_DIVID_4;
    pwmConfig.initChOutputEn                                    =ENABLE; //使能通道初始输出控制功能

    /* pwm config */
    config.mode                                                 = PWM_MODE_MODULATION;
    config.initModeStruct                                       = &pwmConfig;
    config.clkSource                                            = PWM_CLK_SOURCE_NONE;
    config.clkPsc                                               = 1;
    config.maxValue                                             = 1000-1;  //设置最大计数值
    config.interruptEn                                          = ENABLE;
    config.callBack                                             = PWM_Callback;
    PWM_Init(PWM1, &config);

    /* Set interrupt priority */
    NVIC_SetPriority(PWM1_IRQn, 0);
    /* PWM Start */
    PWM_SetClockSource(PWM1, PWM_CLK_SOURCE_APB);
    GPIO_SetPinLevel(GPIOC, GPIO_PIN8, 0); //拉低测试端口
}
2.CMSIS在1.0.5版本以下
  1.0.5以下版本的驱动库,通道初始输出控制的配置存在问题,按上面的配置无法生效,可以在正式配置之前,添加如下如下代码解决
void Motor_PWM_LOW_LOW(void)
{
         
    PWM_DeInit(PWM1);
    PWM_CombineChConfig chConfig[4];
    PWM_ModulationConfigType pwmConfig;
    PWM_ConfigType config;

    GPIO_SetPinLevel(GPIOC, GPIO_PIN8, 1); //拉高测试端口
   
    /* Config PWM Interface */
    memset(&chConfig, 0, sizeof(chConfig));
    memset(&pwmConfig, 0, sizeof(PWM_ModulationConfigType));
    memset(&config, 0, sizeof(PWM_ConfigType));
               
    /*首先打开PWM模块时钟*/
    CKGEN_Enable(CLK_PWM1, ENABLE);
    CKGEN_SoftReset(SRST_PWM1, ENABLE);
   /*根据不同电机驱动极性,配置初始输出电平*/
PWM_SetChannelOutputInitLevel(PWM1, PWM_CH_0, 1); //CH0初始输出高电平
PWM_SetChannelOutputInitLevel(PWM1, PWM_CH_1, 1); //CH1初始输出高电平
PWM_SetChannelOutputInitLevel(PWM1, PWM_CH_2, 1); //CH2初始输出高电平
PWM_SetChannelOutputInitLevel(PWM1, PWM_CH_3, 1); //CH3初始输出高电平
PWM_SetChannelOutputInitLevel(PWM1, PWM_CH_4, 1); //CH4初始输出高电平
PWM_SetChannelOutputInitLevel(PWM1, PWM_CH_5, 1); //CH5初始输出高电平

/* 使能初始输出控制功能*/
PWM_SetInitChannelOutput(PWM1, ENABLE);

     /* channel 0/1 */
    chConfig[0].pairChannel                                     = PWM_CH_0;
    chConfig[0].ch1stValue                                      = 500;
    chConfig[0].ch2ndValue                                      = 500;
    chConfig[0].levelMode                                       = PWM_LOW_TRUE;
    chConfig[0].complementEn                                    = ENABLE;
    chConfig[0].deadtimeEn                                      = ENABLE;
    chConfig[0].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
    chConfig[0].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
    chConfig[0].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[0].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[0].ch1stInitLevel                                  =1;
    chConfig[0].ch2ndInitLevel                                  =1;

    /* channel 2/3 */
    chConfig[1].pairChannel                                     = PWM_CH_2;
    chConfig[1].ch1stValue                                      = 500;
    chConfig[1].ch2ndValue                                      = 500;
    chConfig[1].levelMode                                       = PWM_LOW_TRUE;
    chConfig[1].complementEn                                    = ENABLE;
    chConfig[1].deadtimeEn                                      = ENABLE;
    chConfig[1].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
    chConfig[1].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
    chConfig[1].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[1].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[1].ch1stInitLevel                                  =1;
    chConfig[1].ch2ndInitLevel                                  =1;


    /* channel 4/5 */
    chConfig[2].pairChannel                                     = PWM_CH_4;
    chConfig[2].ch1stValue                                      = 500;
    chConfig[2].ch2ndValue                                      = 500;
    chConfig[2].levelMode                                       = PWM_LOW_TRUE;
    chConfig[2].complementEn                                    = ENABLE;
    chConfig[2].deadtimeEn                                      = ENABLE;
    chConfig[2].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
    chConfig[2].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
    chConfig[2].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[2].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
    chConfig[2].ch1stInitLevel                                  =1;
    chConfig[2].ch2ndInitLevel                                  =1;
   
    pwmConfig.initTriggerEn                                     = ENABLE;
    pwmConfig.countMode                                         = PWM_UP_DOWN_COUNT;
    pwmConfig.combineChannelNum                                 = 3;
    pwmConfig.combineChConfig                                   = chConfig;
    pwmConfig.deadtime                                          = 24;
    pwmConfig.deadtimePsc                                       = PWM_DEADTIME_DIVID_4;
    pwmConfig.initChOutputEn                                    =ENABLE;

    /* pwm config */
    config.mode                                                 = PWM_MODE_MODULATION;
    config.initModeStruct                                       = &pwmConfig;
    config.clkSource                                            = PWM_CLK_SOURCE_NONE;
    config.clkPsc                                               = 1;
    config.maxValue                                             = 1000-1;
    config.interruptEn                                          = ENABLE;
    config.callBack                                             = PWM_Callback;
    PWM_Init(PWM1, &config);

    /* Set interrupt priority */
    NVIC_SetPriority(PWM1_IRQn, 0);
    /* PWM Start */
    PWM_SetClockSource(PWM1, PWM_CLK_SOURCE_APB);
    GPIO_SetPinLevel(GPIOC, GPIO_PIN8, 0); //拉低测试端口
}


按上面的配置,可以测试,在PWM模块初始化期间,通道输出为对应通道的配置电平,在电机应用中可以确保在任何时候都不会出现MOS错误导通的情况。




使用特权

评论回复

相关帖子

沙发
caigang13| | 2021-9-7 07:55 | 只看该作者
楼主写的不错,点赞。

使用特权

评论回复
板凳
两只袜子| | 2021-9-22 10:31 | 只看该作者
赞一个支持一下

使用特权

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

本版积分规则

24

主题

86

帖子

2

粉丝