0 引
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,三相霍尔捕获;
- GPIO输出模拟霍尔数字信号输出到TIM3-HALL PC0 /PC1 /PC2
- LED-PC6
- KEY-PA0
注:本实例需要对有感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即可,否则会溢出后再计数。
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输出,
4 后续
先发布后修改。在使用过程中,好像TIM2的hall有一路不行,一直跳变,后改用TIM3,GPIO输出有一路需要设置为高速,原因未深究,后发现可能硬件冲突,部分使用的口连接到USB了。