正点原子——直流无刷电机-霍尔传感基本实现流程
直流无刷电机-霍尔传感实现流程
初始化TIM以及IO
霍尔状态读取函数
uint32_t hallsersor(void)
{uint32_t state = 0;if(HAL_GPIO_ReadPin(HALL1_TIM_CH1_GPIO,HALL_TIM_CH1_PIN)!=RESET){state |=0x01;}if(HAL_GPIO_ReadPin(HALL1_TIM_CH2_GPIO,HALL_TIM_CH2_PIN)!=RESET){state |=0x02;}if(HAL_GPIO_ReadPin(HALL1_TIM_CH1_GPIO,HALL_TIM_CH1_PIN)!=RESET){state |=0x04;}return state;}
上下桥臂的导通情况,及六步换向
void ml_uhvl(void)
{/*上桥臂*/g_atimx_handle.Instance -> CCR1 = g_blbc_motor1.pwm_duty;g_atimx_handle.Instance -> CCR2 = 0;g_atimx_handle.Instance -> CCR3 = 0;/*下桥臂*/HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_SET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}
void ml_uhwl(void)
{/*上桥臂*/g_atimx_handle.Instance -> CCR1 = g_blbc_motor1.pwm_duty;g_atimx_handle.Instance -> CCR2 = 0;g_atimx_handle.Instance -> CCR3 = 0;/*下桥臂*/HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_SET);
}
void ml_vhul(void)
{/*上桥臂*/g_atimx_handle.Instance -> CCR1 = 0;g_atimx_handle.Instance -> CCR2 = g_blbc_motor1.pwm_duty;g_atimx_handle.Instance -> CCR3 = 0;/*下桥臂*/HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_SET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}
void ml_vhwl(void)
{/*上桥臂*/g_atimx_handle.Instance -> CCR1 = 0;g_atimx_handle.Instance -> CCR2 = g_blbc_motor1.pwm_duty;g_atimx_handle.Instance -> CCR3 = 0;/*下桥臂*/HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_SET);
}
void ml_whul(void)
{/*上桥臂*/g_atimx_handle.Instance -> CCR1 = 0;g_atimx_handle.Instance -> CCR2 = 0;g_atimx_handle.Instance -> CCR3 = g_blbc_motor1.pwm_duty;/*下桥臂*/HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_SET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}
void ml_whvl(void)
{/*上桥臂*/g_atimx_handle.Instance -> CCR1 = 0;g_atimx_handle.Instance -> CCR2 = 0;g_atimx_handle.Instance -> CCR3 = g_blbc_motor1.pwm_duty;/*下桥臂*/HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_SET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}
设置旋转方向以及脉冲占空比,编写无刷启停函数
/*关闭电机函数,SHUTDOWN 拉低*,PWM_TIM1关闭,上桥臂关闭,下桥臂关闭*/
void stop_motor(void)
{SHUTDOWN_OFF;HAL_TIM_PWM_Stop(&g_atimx_handle,TIM_CHANNEL_1);HAL_TIM_PWM_Stop(&g_atimx_handle,TIM_CHANNEL_2);HAL_TIM_PWM_Stop(&g_atimx_handle,TIM_CHANNEL_3);g_atimx_handle.Instance -> CCR1 = 0;g_atimx_handle.Instance -> CCR2 = 0;g_atimx_handle.Instance -> CCR3 = 0;HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);}
/*开启电机函数,SHUTDOWN 拉高*,PWM_TIM1打开,*/
void start_motor(void)
{SHUTDOWN_EN;HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_1);HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_2);HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_3);}
在main.c中设置旋转方向以及脉冲占空比
int main(void)
{uint8_t key,t;//定义变量存放占空比int16_t pwm_dy = 0;HAL_Init();sys_stm32_clock_init(336,8,2,7);delay_init();usart_int(115200);led_init();key_init();lcd_init();bldc_init(1000-1,0);while(1){t++;if(t % 20 == 0){LED0_TOGGLE();}key = key_scan(0);if(key == KEY0_PRES){pwm_dy += 500;if(pwm_dy >= MAX_PWM_DUTY){pwm_dy = MAX_PWM_DUTY;}if(pwm_dy >0){g_bldc_motorl.dir = CW;g_bldc_motorl.pwm_duty = pwm_dy; }else{g_bldc_motor1.dir = CCW;g_bldc_motorl.pwm_duty = -pwm_dy;}start_motor();g_bldc_motorl.run_flag = RUN;}else if(key == KEY1_PRES){pwm_dy -= 500;if(pwm_dy <= MAX_PWM_DUTY){pwm_dy = MAX_PWM_DUTY;}if(pwm_dy <0){g_bldc_motorl.dir = CCW;g_bldc_motorl.pwm_duty = -pwm_dy; }else{g_bldc_motor1.dir = CW;g_bldc_motorl.pwm_duty = pwm_dy;}start_motor();g_bldc_motorl.run_flag = RUN;}else if(key == KEY2_PRES){stop_motor();g_bldc_motorl.run_flag = STOP; g_bldc_motorl.pwm_duty = 0;pwm_dy = 0;}delay_ms(10);}
}
在中断函数中读取霍尔状态,根据方向以及霍尔状态依次导通上下桥臂
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim->Instance == ATIM_TIMX_PWM){if(g_bldc_motor1.run_flag == RUN){//读取霍尔位置g_bldc_motor1.step_sta = hallsersor();if(g_bldc_motor1.step_sta >=1 && g_bldc_motor1.step_sta <=6){//正转时,CWif(g_bldc_motor1.dir == CW){switch(g_bldc_motor1.step_sta){case 0x01: mi_uhwl(); break;case 0x02: mi_vhul(); break;case 0x03: mi_vhwl(); break;case 0x04: mi_whvl(); break;case 0x05: mi_uhvl(); break;case 0x06: mi_whul(); break;default : break;} }}else if(g_bldc_motor1.dir == CCW){switch(g_bldc_motor1.step_sta){case 0x01:ml_whul();break;case 0x02:ml_uhvl();break;case 0x03:ml_whvl();break;case 0x04:ml_vhwl();break;case 0x05:ml_vhul();break;case 0x06:ml_uhwl();break;default : break;} }else{stop_motor();g_bldc_motor1.run_flag = STOP;}}}