ARM技术论坛
直播中

王超

7年用户 1247经验值
私信 关注
[经验]

在GD32F427开发板上完成BLDC方波驱动测试

GD32F427V-START开发板采用主控芯片GD32F427VKT6,MCU基于 Arm® Cortex®-M4内核,系统时钟的最大运行时钟频率可以达到240MHz。

本次测试利用STM32CubeMX(STM32F427VITx)生成工程代码,完成无刷电机驱动程序输出。GD外设编号从0开始,如TIM0等效STM32的TIM1。

本测试目前没有用实际电机测试,用模拟hall时序输出到hall输入引脚的办法,触发换相。外设使用情况如下:

TIM1-CH1/CH1N/CH2/CH2N/CH3/CH3N,三相互补PWM输出;
TIM1-BKN PA6 刹车输入;
TIM3-HALL CH1/CH2/CH3--PB4/PC7/PC8,三相霍尔捕获;
HALL模拟霍尔数字信号输出到TIM3 HU-PC0 HV-PC1 HW-PC2
LED-PC6
KEY-PA0
DAC...待测试
ADC...待测试

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

1 STM32CubeMX配置

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

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 波形测试

![JBYB%1SYT7WRIZ)XAPWP$V.png](https://aijishu.com/img/bVbHMg "JBYB%1SYT7WRIZ)XAPWP$V.png")

4 后续

先发布后修改。有时间研究后可能会逐渐增加ADC/PID,COM事件等功能。

在使用过程中,好像TIM2的hall有一路不行,后改用TIM3,GPIO输出有一路需要高速,原因未深究,可能修改代码即可。

原作者:szit

更多回帖

发帖
×
20
完善资料,
赚取积分