基于霍尔传感器的BLDC控制源码
基于STM32的BLDC无刷直流电机控制其核心原理是“六步换相法”6-Step Commutation。根据转子位置通过霍尔传感器或无感反电动势检测按顺序导通/关断6个MOS管驱动电机旋转。1. 核心宏定义与全局变量 (bldc.h)首先定义电机运行的三种模式以及PWM句柄假设你使用HAL库如果是标准库只需替换TIM_HandleTypeDef。#ifndef__BLDC_H__#define__BLDC_H__#includestm32f1xx_hal.h// 根据实际芯片型号修改如 stm32f4xx_hal.h// 电机运行状态枚举typedefenum{MOTOR_STOP0,MOTOR_RUN,MOTOR_BRAKE}Motor_State_t;// PWM频率与占空比相关#definePWM_PERIOD1000// PWM周期决定分辨率 (0~1000 对应 0%~100%)#defineDEAD_TIME_NS1000// 死区时间单位纳秒根据驱动板调整// 霍尔传感器引脚定义 (示例PB6, PB7, PB8)#defineHALL_GPIO_PORTGPIOB#defineHALL_U_PINGPIO_PIN_6#defineHALL_V_PINGPIO_PIN_7#defineHALL_W_PINGPIO_PIN_8voidBLDC_Init(void);voidBLDC_SetSpeed(uint16_tspeed);voidBLDC_Stop(void);voidBLDC_Brake(void);#endif2. PWM与换相控制核心源码 (bldc.c)这是最核心的部分包含了高级定时器TIM1/TIM8的PWM互补输出配置以及根据霍尔信号进行的6步换相逻辑。#includebldc.h#includemath.h// 定义高级定时器句柄 (在main.c中定义这里用extern声明)externTIM_HandleTypeDef htim1;// 假设使用TIM1作为PWM生成定时器staticuint16_tmotor_speed_target0;staticMotor_State_t motor_stateMOTOR_STOP;/** * brief PWM互补输出初始化 * 配置CH1/CH2/CH3的互补PWM输出并插入死区时间 */voidMX_TIM1_PWM_Init(void){TIM_MasterConfigTypeDef sMasterConfig{0};TIM_OC_InitTypeDef sConfigOC{0};TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig{0};htim1.InstanceTIM1;htim1.Init.Prescaler0;htim1.Init.CounterModeTIM_COUNTERMODE_UP;htim1.Init.PeriodPWM_PERIOD;htim1.Init.ClockDivisionTIM_CLOCKDIVISION_DIV1;htim1.Init.RepetitionCounter0;HAL_TIM_PWM_Init(htim1);sMasterConfig.MasterOutputTriggerTIM_TRGO_RESET;sMasterConfig.MasterSlaveModeTIM_MASTERSLAVEMODE_DISABLE;HAL_TIMEx_MasterConfigSynchronization(htim1,sMasterConfig);sConfigOC.OCModeTIM_OCMODE_PWM1;sConfigOC.Pulse0;// 初始占空比为0sConfigOC.OCPolarityTIM_OCPOLARITY_HIGH;sConfigOC.OCNPolarityTIM_OCNPOLARITY_HIGH;sConfigOC.OCFastModeTIM_OCFAST_DISABLE;sConfigOC.OCIdleStateTIM_OCIDLESTATE_RESET;sConfigOC.OCNIdleStateTIM_OCNIDLESTATE_RESET;// 配置通道1、2、3HAL_TIM_PWM_ConfigChannel(htim1,sConfigOC,TIM_CHANNEL_1);HAL_TIM_PWM_ConfigChannel(htim1,sConfigOC,TIM_CHANNEL_2);HAL_TIM_PWM_ConfigChannel(htim1,sConfigOC,TIM_CHANNEL_3);// 配置死区时间sBreakDeadTimeConfig.OffStateRunModeTIM_OSSR_DISABLE;sBreakDeadTimeConfig.OffStateIDLEModeTIM_OSSI_DISABLE;sBreakDeadTimeConfig.LockLevelTIM_LOCKLEVEL_OFF;sBreakDeadTimeConfig.DeadTime(uint8_t)(DEAD_TIME_NS/1000*72);// 72MHz主频下计算死区sBreakDeadTimeConfig.BreakStateTIM_BREAK_DISABLE;sBreakDeadTimeConfig.BreakPolarityTIM_BREAKPOLARITY_HIGH;sBreakDeadTimeConfig.AutomaticOutputTIM_AUTOMATICOUTPUT_DISABLE;HAL_TIMEx_ConfigBreakDeadTime(htim1,sBreakDeadTimeConfig);// 启动PWM互补输出HAL_TIM_PWM_Start(htim1,TIM_CHANNEL_1);HAL_TIM_PWM_Start(htim1,TIM_CHANNEL_2);HAL_TIM_PWM_Start(htim1,TIM_CHANNEL_3);HAL_TIMEx_PWMN_Start(htim1,TIM_CHANNEL_1);HAL_TIMEx_PWMN_Start(htim1,TIM_CHANNEL_2);HAL_TIMEx_PWMN_Start(htim1,TIM_CHANNEL_3);}/** * brief 核心换相函数 * 根据霍尔传感器的值(U/V/W)决定下一步的导通相序 */voidBLDC_Commutate(void){uint8_thall_state0;// 1. 读取霍尔传感器状态 (组合成 0~7 的值)hall_state|(HAL_GPIO_ReadPin(HALL_GPIO_PORT,HALL_U_PIN)GPIO_PIN_SET)?1:0;hall_state|(HAL_GPIO_ReadPin(HALL_GPIO_PORT,HALL_V_PIN)GPIO_PIN_SET)?2:0;hall_state|(HAL_GPIO_ReadPin(HALL_GPIO_PORT,HALL_W_PIN)GPIO_PIN_SET)?4:0;// 2. 根据霍尔状态进行6步换相switch(hall_state){case0b101:// 霍尔状态5 - 导通 V(上) W(下)__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,motor_speed_target);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,0);break;case0b001:// 霍尔状态1 - 导通 U(上) W(下)__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,motor_speed_target);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,0);break;case0b011:// 霍尔状态3 - 导通 U(上) V(下)__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,motor_speed_target);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,0);break;case0b010:// 霍尔状态2 - 导通 W(上) V(下)__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,motor_speed_target);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,0);break;case0b110:// 霍尔状态6 - 导通 W(上) U(下)__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,motor_speed_target);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,0);break;case0b100:// 霍尔状态4 - 导通 V(上) U(下)__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,motor_speed_target);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,0);break;default:break;}}/** * brief 设置电机目标速度 * param speed 0 ~ PWM_PERIOD (如 0~1000) */voidBLDC_SetSpeed(uint16_tspeed){if(speedPWM_PERIOD)speedPWM_PERIOD;motor_speed_targetspeed;motor_stateMOTOR_RUN;}/** * brief 电机停止 (惰行) */voidBLDC_Stop(void){motor_speed_target0;motor_stateMOTOR_STOP;// 关闭所有PWM输出__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,0);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,0);}/** * brief 电机刹车 (三相下桥臂短路) */voidBLDC_Brake(void){motor_stateMOTOR_BRAKE;// 开启所有下桥臂短接电机三相线圈__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_1,PWM_PERIOD);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_2,PWM_PERIOD);__HAL_TIM_SET_COMPARE(htim1,TIM_CHANNEL_3,PWM_PERIOD);}3. 霍尔传感器外部中断处理 (stm32f1xx_it.c或main.c)当霍尔传感器电平发生变化时代表转子到达了新的换相点需要在中断中立刻调用换相函数。// 在 main.c 中重写 EXTI 回调函数voidHAL_GPIO_EXTI_Callback(uint16_tGPIO_Pin){// 判断是否是霍尔传感器引脚触发的中断if(GPIO_PinHALL_U_PIN||GPIO_PinHALL_V_PIN||GPIO_PinHALL_W_PIN){// 调用换相函数BLDC_Commutate();}}4. 主函数调用示例 (main.c)在main函数中初始化硬件并设定一个目标转速。intmain(void){HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM1_Init();// 初始化高级定时器PWM// 初始化霍尔传感器引脚的外部中断HAL_NVIC_SetPriority(EXTI9_5_IRQn,0,0);HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);// 启动电机转动 (设定速度为 500/1000 50% 占空比)BLDC_SetSpeed(500);while(1){// 主循环中可以做其他事情比如接收串口指令改变速度// BLDC_SetSpeed(new_speed);HAL_Delay(1000);}}参考代码 BLDC 电机控制源码www.youwenfan.com/contentcsu/70150.html知识点补充霍尔接线与换相表匹配代码中的switch(hall_state)换相顺序是基于特定的霍尔安装方式常见的120度间隔霍尔。如果你发现电机在某一个方向震动但不转或者转动时有顿挫感说明你的霍尔UVW线序或者换相表顺序不对。此时只需将霍尔信号的读取顺序调换或者重新排列case里的导通逻辑即可。死区时间Dead Time上下管导通切换时必须留出一个极短的空白时间通常几百纳秒防止上下管直通导致电源对地短路烧毁MOS管。在sBreakDeadTimeConfig.DeadTime中需要根据你的STM32主频精确计算。无感控制反电动势上述代码适用于有霍尔传感器的电机。如果你想做无感Sensorless控制需要将霍尔读取部分替换为三个 ADC通道实时采样电机悬空相的电压反电动势当采样值过零点时由正变负或由负变正触发定时器中断进行换相。无感控制的难点在于启动算法通常采用强行拖拽同步启动。