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

[复制链接]
 楼主| wangjj19950516 发表于 2021-8-26 11:50 | 显示全部楼层 |阅读模式
本帖最后由 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.
dso_1(1).jpg
既然这样,那在电机应用中就会存在很大的风险。别急,我们的PWM模块考虑到了这种情况,PWM可以配置在初始化期间强制控制通道输出电平,PWM_OUTINIT寄存器配置每个通道的初始输出电平,PWM_FUNCSEL寄存器的INIT位使能该功能
为规避风险,不管电机的驱动极性是哪一种,都应该配置相应的初始输出电平。在使用过程中,应将使能位放在通道输出电平配置的后面,才会生效。
PWM_OUTINIT寄存器.jpg
PWM_FUNCSEL.jpg

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

  14.     PWM_SetModValue(PWM2, (3000 - 1)); //设置最大计数值
  15.     PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL0, 0);
  16.     PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL2, 0);
  17.     PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL4, 0);
  18.     PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL1, 0);
  19.     PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL3, 0);
  20.     PWM_SetChannelValue(PWM2, PWM_CHANNEL_CHANNEL5, 0);

  21.     /* Active Low, down edge input dead time */
  22.     PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL0, 1);
  23.     PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL2, 1);
  24.     PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL4, 1);
  25.     PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL1, 1);
  26.     PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL3, 1);
  27.     PWM_OutputPolaritySet(PWM2, PWM_CHANNEL_CHANNEL5, 1);

  28.     /* 1us Deadtime */
  29.     PWM_PWMDeadtimeSet(PWM2, 2, 24);
  30.     /* PWM Start */
  31.     PWM_ClockSet(PWM2, PWM_CLOCK_SYSTEMCLOCK, 0);
  32. }

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

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

  14.     /* channel 0/1 */
  15.     chConfig[0].pairChannel                                     = PWM_CH_0;
  16.     chConfig[0].ch1stValue                                      = 500;
  17.     chConfig[0].ch2ndValue                                      = 500;
  18.     chConfig[0].levelMode                                       = PWM_LOW_TRUE;
  19.     chConfig[0].complementEn                                    = ENABLE;
  20.     chConfig[0].deadtimeEn                                      = ENABLE;
  21.     chConfig[0].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
  22.     chConfig[0].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
  23.     chConfig[0].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  24.     chConfig[0].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  25.     chConfig[0].ch1stInitLevel                                  =1;            //配置CH0通道初始输出电平为高电平
  26.     chConfig[0].ch2ndInitLevel                                  =1;           //配置CH1通道初始输出电平为高电平

  27.     /* channel 2/3 */
  28.     chConfig[1].pairChannel                                     = PWM_CH_2;
  29.     chConfig[1].ch1stValue                                      = 500;
  30.     chConfig[1].ch2ndValue                                      = 500;
  31.     chConfig[1].levelMode                                       = PWM_LOW_TRUE;
  32.     chConfig[1].complementEn                                    = ENABLE;
  33.     chConfig[1].deadtimeEn                                      = ENABLE;
  34.     chConfig[1].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
  35.     chConfig[1].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
  36.     chConfig[1].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  37.     chConfig[1].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  38.     chConfig[1].ch1stInitLevel                                  =1; //配置CH2通道初始输出电平为高电平
  39.     chConfig[1].ch2ndInitLevel                                  =1;//配置CH3通道初始输出电平为高电平

  40.     /* channel 4/5 */
  41.     chConfig[2].pairChannel                                     = PWM_CH_4;
  42.     chConfig[2].ch1stValue                                      = 500;
  43.     chConfig[2].ch2ndValue                                      = 500;
  44.     chConfig[2].levelMode                                       = PWM_LOW_TRUE;
  45.     chConfig[2].complementEn                                    = ENABLE;
  46.     chConfig[2].deadtimeEn                                      = ENABLE;
  47.     chConfig[2].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
  48.     chConfig[2].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
  49.     chConfig[2].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  50.     chConfig[2].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  51.     chConfig[2].ch1stInitLevel                                  =1;//配置CH4通道初始输出电平为高电平
  52.     chConfig[2].ch2ndInitLevel                                  =1;//配置CH5通道初始输出电平为高电平
  53.    
  54.     pwmConfig.initTriggerEn                                     = ENABLE;
  55.     pwmConfig.countMode                                         = PWM_UP_DOWN_COUNT;
  56.     pwmConfig.combineChannelNum                                 = 3;
  57.     pwmConfig.combineChConfig                                   = chConfig;
  58.     pwmConfig.deadtime                                          = 24;
  59.     pwmConfig.deadtimePsc                                       = PWM_DEADTIME_DIVID_4;
  60.     pwmConfig.initChOutputEn                                    =ENABLE; //使能通道初始输出控制功能

  61.     /* pwm config */
  62.     config.mode                                                 = PWM_MODE_MODULATION;
  63.     config.initModeStruct                                       = &pwmConfig;
  64.     config.clkSource                                            = PWM_CLK_SOURCE_NONE;
  65.     config.clkPsc                                               = 1;
  66.     config.maxValue                                             = 1000-1;  //设置最大计数值
  67.     config.interruptEn                                          = ENABLE;
  68.     config.callBack                                             = PWM_Callback;
  69.     PWM_Init(PWM1, &config);

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

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

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

  27.      /* channel 0/1 */
  28.     chConfig[0].pairChannel                                     = PWM_CH_0;
  29.     chConfig[0].ch1stValue                                      = 500;
  30.     chConfig[0].ch2ndValue                                      = 500;
  31.     chConfig[0].levelMode                                       = PWM_LOW_TRUE;
  32.     chConfig[0].complementEn                                    = ENABLE;
  33.     chConfig[0].deadtimeEn                                      = ENABLE;
  34.     chConfig[0].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
  35.     chConfig[0].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
  36.     chConfig[0].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  37.     chConfig[0].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  38.     chConfig[0].ch1stInitLevel                                  =1;
  39.     chConfig[0].ch2ndInitLevel                                  =1;

  40.     /* channel 2/3 */
  41.     chConfig[1].pairChannel                                     = PWM_CH_2;
  42.     chConfig[1].ch1stValue                                      = 500;
  43.     chConfig[1].ch2ndValue                                      = 500;
  44.     chConfig[1].levelMode                                       = PWM_LOW_TRUE;
  45.     chConfig[1].complementEn                                    = ENABLE;
  46.     chConfig[1].deadtimeEn                                      = ENABLE;
  47.     chConfig[1].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
  48.     chConfig[1].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
  49.     chConfig[1].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  50.     chConfig[1].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  51.     chConfig[1].ch1stInitLevel                                  =1;
  52.     chConfig[1].ch2ndInitLevel                                  =1;


  53.     /* channel 4/5 */
  54.     chConfig[2].pairChannel                                     = PWM_CH_4;
  55.     chConfig[2].ch1stValue                                      = 500;
  56.     chConfig[2].ch2ndValue                                      = 500;
  57.     chConfig[2].levelMode                                       = PWM_LOW_TRUE;
  58.     chConfig[2].complementEn                                    = ENABLE;
  59.     chConfig[2].deadtimeEn                                      = ENABLE;
  60.     chConfig[2].ch1stMatchDir                                   = PWM_MATCH_DIR_UP;
  61.     chConfig[2].ch2ndMatchDir                                   = PWM_MATCH_DIR_DOWN;
  62.     chConfig[2].ch1stPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  63.     chConfig[2].ch2ndPolarity                                   = PWM_OUTPUT_POLARITY_ACTIVE_LOW;
  64.     chConfig[2].ch1stInitLevel                                  =1;
  65.     chConfig[2].ch2ndInitLevel                                  =1;
  66.    
  67.     pwmConfig.initTriggerEn                                     = ENABLE;
  68.     pwmConfig.countMode                                         = PWM_UP_DOWN_COUNT;
  69.     pwmConfig.combineChannelNum                                 = 3;
  70.     pwmConfig.combineChConfig                                   = chConfig;
  71.     pwmConfig.deadtime                                          = 24;
  72.     pwmConfig.deadtimePsc                                       = PWM_DEADTIME_DIVID_4;
  73.     pwmConfig.initChOutputEn                                    =ENABLE;

  74.     /* pwm config */
  75.     config.mode                                                 = PWM_MODE_MODULATION;
  76.     config.initModeStruct                                       = &pwmConfig;
  77.     config.clkSource                                            = PWM_CLK_SOURCE_NONE;
  78.     config.clkPsc                                               = 1;
  79.     config.maxValue                                             = 1000-1;
  80.     config.interruptEn                                          = ENABLE;
  81.     config.callBack                                             = PWM_Callback;
  82.     PWM_Init(PWM1, &config);

  83.     /* Set interrupt priority */
  84.     NVIC_SetPriority(PWM1_IRQn, 0);
  85.     /* PWM Start */
  86.     PWM_SetClockSource(PWM1, PWM_CLK_SOURCE_APB);
  87.     GPIO_SetPinLevel(GPIOC, GPIO_PIN8, 0); //拉低测试端口
  88. }


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



caigang13 发表于 2021-9-7 07:55 来自手机 | 显示全部楼层
楼主写的不错,点赞。
两只袜子 发表于 2021-9-22 10:31 来自手机 | 显示全部楼层
赞一个支持一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

86

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部