szit · 2022年11月18日 · 江苏

【GD32F427开发板试用】BLDC方波驱动测试

0 引

GD32F427V-START开发板采用主控芯片GD32F427VKT6,MCU基于 Arm® Cortex®-M4内核,系统时钟的最大运行时钟频率可以达到240MHz。本次测试利用STM32CubeMX(STM32F427VITx)生成工程代码,完成无刷电机驱动程序输出。GD外设编号从0开始,如TIM0等效STM32的TIM1。本测试目前没有用实际电机测试,用模拟hall时序输出到hall输入引脚的办法,触发换相。外设使用情况如下:

  1. TIM1-CH1/CH1N/CH2/CH2N/CH3/CH3N,三相互补PWM输出;
  2. TIM1-BKN PA6 刹车输入;
  3. TIM3-HALL CH1/CH2/CH3--PB4/PC7/PC8,三相霍尔捕获;
  4. GPIO输出模拟霍尔数字信号输出到TIM3-HALL PC0 /PC1 /PC2
  5. LED-PC6
  6. KEY-PA0

注:本实例需要对有感BLDC驱动硬件与驱动方法有一定理解,比如三相H桥、3相霍尔(120°)、正反转时序等。
GD32F427VK_START.jpg

1 STM32CubeMX配置

  1. 芯片选择STM32F427VITx(其他未测)
  2. SWD配置
  3. RCC时钟:外置HSE- 25MHZ 外置RTC- 32.768KHz
  4. 时钟配置为180MHz
  5. PC0、PC1、PC2、PC6配置为GPIO_Output,高速
  6. PA0配置为GPIO_Input,上拉
  7. TIM1配置前3个通道三路互补20kHz PWM输出,Prescaler=0,Counter Period = 8899;Activate-Break-Input刹车,BRK State使能 极性为low;PWM模式默认mode1,极性均为High,Idle State为Reset,PA6配置为上拉(低电平刹车,高电平工作);
  8. TIM3配置为XOR ON/Hall Sensor Mode,Prescaler=89,Counter Period = 65535;计数脉冲周期为1us,当产生霍尔捕获中断时获取当前时间即可,一次时间不要超过65535*1us即可,否则会溢出后再计数。

2 程序设计

1.启动Keil,芯片选择GD32F427VK,Debug选择CMSIS-DAP Debugger。
2.启动SYSTICK时钟
配置1ms中断SYSTICK时钟。
`void SysTick_Handler(void)
{
/ USER CODE BEGIN SysTick_IRQn 0 /

    HAL_SYSTICK_IRQHandler();

/ USER CODE END SysTick_IRQn 0 /
HAL_IncTick();
/ USER CODE BEGIN SysTick_IRQn 1 /

/ USER CODE END SysTick_IRQn 1 /
}`
3.在SYSTICK回调函数中输出HALL模拟时序
电机正传与反转时,霍尔都有相应的时序被检测到,这里用模拟的方法输出三相霍尔信号PC0/PC1/PC2到霍尔传感器输入引脚(杜邦线)PB4/PC7/PC8.

#define CNT_PSC          100  
uint32_t CounterPSC = CNT_PSC;   
int8_t hal_step_simulate=-1;
uint8_t array_cw[6] = {2,3,1,5,4,6};
uint8_t array_ccw[6] = {5,1,3,2,6,4};
void HAL_SYSTICK_Callback()
{
  CounterPSC--;
  if(!CounterPSC) 
  {        
        hal_step_simulate++;
        if(hal_step_simulate==6)hal_step_simulate=0;    
        if(Motor_Dir == MOTOR_DIR_CW)
        {
            if((array_cw[hal_step_simulate]&0x01)!=0)
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
            else
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);
            
            if((array_cw[hal_step_simulate]&0x02)!=0)
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
            else
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
            
            if((array_cw[hal_step_simulate]&0x04)!=0)
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
            else
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);
        }
        else if(Motor_Dir == MOTOR_DIR_CCW)
        {
            if((array_ccw[hal_step_simulate]&0x01)!=0)
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_SET);
            else
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_0,GPIO_PIN_RESET);
            
            if((array_ccw[hal_step_simulate]&0x02)!=0)
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_SET);
            else
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_1,GPIO_PIN_RESET);
            
            if((array_ccw[hal_step_simulate]&0x04)!=0)
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET);
            else
                HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);    
        }
    CounterPSC = CNT_PSC; 
   // BLDCMotor_PhaseCtrl(&uwStep);// ¿ØÖÆ6²½PWM»»Ïà
  }
}

4.换相
根据三相霍尔状态切换3相6路PWM输出。

#define MOTOR_DIR_CCW 1
#define MOTOR_DIR_CW 2
uint8_t Motor_Dir = 1;
void BLDCMotor_PhaseCtrl(int32_t HALLPhase)
{
  if(MOTOR_DIR_CCW == Motor_Dir)
    HALLPhase = 0x07 ^ HALLPhase;// ½«µÍÈýλÒì»ò 111b ^ 010b -> 101b

  switch(HALLPhase)
  {
    case 5: //B+  A-
    {
      /*  Channe3 configuration */ 
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
    
      /*  Channe2 configuration  */
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);  
      
      /*  Channe1 configuration */
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD +1);
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    }
    break;
    
    case 4:// C+ A-
    {
      /*  Channe2 configuration */ 
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);
 
      /*  Channe3 configuration  */
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);  
      
      /*  Channe1 configuration  */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD +1);
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    }
      break;
    
    case 6://C+ B-
    {
      /*  Channe1 configuration  */ 
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
    
      /*  Channe3 configuration */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);  

      /*  Channe2 configuration  */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,BLDCMOTOR_TIM_PERIOD +1);
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
    }
      break;

    case 2: // A+ B-
    {
      /*  Channe3 configuration */       
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_3);
    
      /*  Channe1 configuration */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);  
      
      /*  Channe2 configuration */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,BLDCMOTOR_TIM_PERIOD +1);
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
    }
      break;
    
    
    case 3:// A+ C-
    {
      /*  Channe2 configuration */ 
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);

      /*  Channe1 configuration */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,BLDCMOTOR_TIM_PERIOD * PWM_Duty);
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);  
      
      /*  Channe3 configuration */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,BLDCMOTOR_TIM_PERIOD +1);    
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
    }
      break;
    case 1: // B+ C-
    {
      /*  Channe1 configuration */ 
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_1);
    
      /*  Channe2 configuration */
      __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2, BLDCMOTOR_TIM_PERIOD * PWM_Duty);
      HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
      HAL_TIMEx_PWMN_Stop(&htim1, TIM_CHANNEL_2);  
      
      /*  Channe3 configuration */
      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, BLDCMOTOR_TIM_PERIOD +1);
      HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
      HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
    }
    break;
  }
}

5.霍尔捕获
霍尔捕获后,获取当前霍尔值,而后根据霍尔值切换H桥PWM输出,每次捕获可以记录2次捕获之间的时间,可以用于计算转速。

uint8_t hal_state = 0;
uint16_t hal_counter=0;
uint16_t  RT_hallcomp=0;//hall period cnt
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    //PB4 PC7 PC8 TIM3
    if(TIM3== htim->Instance){
        
        hal_counter++;//test 
        hal_state = 0;
        hal_state |= HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4);//U(A)
        hal_state <<= 1;
        hal_state |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_7);//V(B)
        hal_state <<= 1;
        hal_state |= HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_8);//W(C)        
        RT_hallcomp = __HAL_TIM_GET_COMPARE(htim,TIM_CHANNEL_1); // for speed
        
        BLDCMotor_PhaseCtrl(hal_state);// update phase
    }
}

6.其他
在main函数中启动hall定时器
HAL_TIMEx_HallSensor_Start_IT(&htim3);

3 波形测试

刹车低电平刹车,高电平可以正常输出,逻辑分析仪测量6路PWM输出,
JBYB%1SYT7WRIZ)X`APWP$V.png

4 后续

先发布后修改。在使用过程中,好像TIM2的hall有一路不行,一直跳变,后改用TIM3,GPIO输出有一路需要设置为高速,原因未深究,后发现可能硬件冲突,部分使用的口连接到USB了。

推荐阅读
关注数
10707
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息