单片机驱动BLDC带hall六步法
·
单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
主函数:
int main(void)
{
uint8_t key,t;
char buf[32];
int16_t pwm_duty_temp = 0;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
key_init(); /* 初始化按键 */
lcd_init(); /* 初始化LCD */
bldc_init(100000-1,0);
bldc_ctrl(MOTOR_1,CCW,0); /* 初始无刷电机接口1速度 */
HAL_TIM_Base_Start_IT(&g_atimx_handle); /* 启动高级定时器1 */
/* 显示提示信息 */
g_point_color = WHITE;
g_back_color = BLACK;
lcd_show_string(10, 10, 200, 16, 16, "BLDC Motor Test",g_point_color);
lcd_show_string(10, 30, 200, 16, 16, "KEY0:Start forward", g_point_color);
lcd_show_string(10, 50, 200, 16, 16, "KEY1:Start backward", g_point_color);
lcd_show_string(10, 70, 200, 16, 16, "KEY2:Stop", g_point_color);
printf("按下KEY0 开始正转加速\r\n");
printf("按下KEY1 开始反转加速\r\n");
printf("按下KEY2 停止电机\r\n");
while (1)
{
t++;
if(t % 20 == 0)
{
sprintf(buf,"PWM_Duty:%.1f%%",(float)((g_bldc_motor1.pwm_duty/MAX_PWM_DUTY)*100));/* 显示控制PWM占空比 */
lcd_show_string(10,110,200,16,16,buf,g_point_color);
LED0_TOGGLE(); /* LED0(红灯) 翻转 */
}
key = key_scan(0);
if(key == KEY0_PRES) /* 按下KEY0设置比较值+500 */
{
pwm_duty_temp += 500;
if(pwm_duty_temp >= MAX_PWM_DUTY/2) /* 限速 */
pwm_duty_temp = MAX_PWM_DUTY/2;
if(pwm_duty_temp > 0) /* 通过判断正负号设置旋转方向 */
{
g_bldc_motor1.pwm_duty = pwm_duty_temp;
g_bldc_motor1.dir = CW;
}
else
{
g_bldc_motor1.pwm_duty = -pwm_duty_temp;
g_bldc_motor1.dir = CCW;
}
g_bldc_motor1.run_flag = RUN; /* 开启运行 */
start_motor1(); /* 开启运行 */
}
else if(key == KEY1_PRES) /* 按下KEY1设置比较值-500 */
{
pwm_duty_temp -= 500;
if(pwm_duty_temp <= -MAX_PWM_DUTY/2)
pwm_duty_temp = -MAX_PWM_DUTY/2;
if(pwm_duty_temp < 0) /* 通过判断正负号设置旋转方向 */
{
g_bldc_motor1.pwm_duty = -pwm_duty_temp;
g_bldc_motor1.dir = CCW;
}
else
{
g_bldc_motor1.pwm_duty = pwm_duty_temp;
g_bldc_motor1.dir = CW;
}
g_bldc_motor1.run_flag = RUN; /* 开启运行 */
start_motor1(); /* 运行电机 */
}
else if(key == KEY2_PRES) /* 按下KEY2关闭电机 */
{
stop_motor1(); /* 停机 */
g_bldc_motor1.run_flag = STOP; /* 标记停机 */
pwm_duty_temp = 0; /* 数据清0 */
g_bldc_motor1.pwm_duty = 0;
}
delay_ms(10);
}
}
hall配置
void hall_gpio_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
HALL1_U_GPIO_CLK_ENABLE();
HALL1_V_GPIO_CLK_ENABLE();
HALL1_W_GPIO_CLK_ENABLE();
/* 霍尔通道 1 引脚初始化 */
gpio_init_struct.Pin = HALL1_TIM_CH1_PIN;
gpio_init_struct.Mode = GPIO_MODE_INPUT;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(HALL1_TIM_CH1_GPIO, &gpio_init_struct);
/* 霍尔通道 2 引脚初始化 */
gpio_init_struct.Pin = HALL1_TIM_CH2_PIN;
HAL_GPIO_Init(HALL1_TIM_CH2_GPIO, &gpio_init_struct);
/* 霍尔通道 3 引脚初始化 */
gpio_init_struct.Pin = HALL1_TIM_CH3_PIN;
HAL_GPIO_Init(HALL1_TIM_CH3_GPIO, &gpio_init_struct);
}
读取hall
uint32_t hallsensor_get_state(uint8_t motor_id)
{
__IO static uint32_t state ;
state = 0;
if(motor_id == MOTOR_1)
{
if(HAL_GPIO_ReadPin(HALL1_TIM_CH1_GPIO,HALL1_TIM_CH1_PIN) != GPIO_PIN_RESET) /* 霍尔传感器状态获取 */
{
state |= 0x01U;
}
if(HAL_GPIO_ReadPin(HALL1_TIM_CH2_GPIO,HALL1_TIM_CH2_PIN) != GPIO_PIN_RESET) /* 霍尔传感器状态获取 */
{
state |= 0x02U;
}
if(HAL_GPIO_ReadPin(HALL1_TIM_CH3_GPIO,HALL1_TIM_CH3_PIN) != GPIO_PIN_RESET) /* 霍尔传感器状态获取 */
{
state |= 0x04U;
}
}
return state;
}
定时器配置
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* TIMX 时钟使能 */
g_atimx_handle.Instance = ATIM_TIMX_PWM; /* 定时器x */
g_atimx_handle.Init.Prescaler = psc; /* 定时器分频 */
g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1; /* 分频因子 */
g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /*使能TIMx_ARR进行缓冲*/
g_atimx_handle.Init.RepetitionCounter = 0; /* 开始时不计数*/
HAL_TIM_PWM_Init(&g_atimx_handle); /* 初始化PWM */
g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */
g_atimx_oc_chy_handle.Pulse = 0;
g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
/* 开启定时器通道1输出PWM */
HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_1);
/* 开启定时器通道2输出PWM */
HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_2);
/* 开启定时器通道3输出PWM */
HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_3);
}
启动电机
void start_motor1(void)
{
SHUTDOWN_EN;
/* 使能PWM输出 */
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);
}
六步法:
/* 六步换向函数指针数组 */
pctr pfunclist_m1[6] =
{
&m1_uhwl, &m1_vhul, &m1_vhwl,
&m1_whvl, &m1_uhvl, &m1_whul
};
/**
* @brief U相上桥臂导通,V相下桥臂导通
* @param 无
* @retval 无
*/
void m1_uhvl(void)
{
g_atimx_handle.Instance->CCR1 = g_bldc_motor1.pwm_duty; /* U相上桥臂PWM */
g_atimx_handle.Instance->CCR2 = 0;
g_atimx_handle.Instance->CCR3 = 0;
HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_SET); /* V相下桥臂导通 */
HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET); /* U相下桥臂关闭 */
HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET); /* W相下桥臂关闭 */
}
/**
* @brief U相上桥臂导通,W相下桥臂导通
* @param 无
* @retval 无
*/
void m1_uhwl(void)
{
g_atimx_handle.Instance->CCR1 = g_bldc_motor1.pwm_duty;
g_atimx_handle.Instance->CCR2 = 0;
g_atimx_handle.Instance->CCR3 = 0;
HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_SET);
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);
}
/**
* @brief V相上桥臂导通,W相下桥臂导通
* @param 无
* @retval 无
*/
void m1_vhwl(void)
{
g_atimx_handle.Instance->CCR1=0;
g_atimx_handle.Instance->CCR2 = g_bldc_motor1.pwm_duty;
g_atimx_handle.Instance->CCR3=0;
HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_SET);
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);
}
/**
* @brief V相上桥臂导通,U相下桥臂导通
* @param 无
* @retval 无
*/
void m1_vhul(void)
{
g_atimx_handle.Instance->CCR1 = 0;
g_atimx_handle.Instance->CCR2 = g_bldc_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);
}
/**
* @brief W相上桥臂导通,U相下桥臂导通
* @param 无
* @retval 无
*/
void m1_whul(void)
{
g_atimx_handle.Instance->CCR1 = 0;
g_atimx_handle.Instance->CCR2 = 0;
g_atimx_handle.Instance->CCR3 = g_bldc_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);
}
/**
* @brief W相上桥臂导通,V相下桥臂导通
* @param 无
* @retval 无
*/
void m1_whvl(void)
{
g_atimx_handle.Instance->CCR1 = 0;
g_atimx_handle.Instance->CCR2 = 0;
g_atimx_handle.Instance->CCR3 = g_bldc_motor1.pwm_duty;
HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_SET);
HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);
HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}
调用
int watchtemp=0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == ATIM_TIMX_PWM) /* 55us */
{
#ifdef H_PWM_L_ON
if(g_bldc_motor1.run_flag == RUN)
{
watchtemp++;
if(g_bldc_motor1.dir == CW) /* 正转 */
{
g_bldc_motor1.step_sta = hallsensor_get_state(MOTOR_1); /* 顺序6,2,3,1,5,4 */
}
else /* 反转 */
{
g_bldc_motor1.step_sta = 7 - hallsensor_get_state(MOTOR_1); /* 顺序5,1,3,2,6,4 。使用7减完后可与数组pfunclist_m1对应上顺序 实际霍尔值为:2,6,4,5,1,3*/
}
if((g_bldc_motor1.step_sta <= 6)&&(g_bldc_motor1.step_sta >= 1))/* 判断霍尔组合值是否正常 */
{
pfunclist_m1[g_bldc_motor1.step_sta-1](); /* 通过数组成员查找对应的函数指针 */
}
else /* 霍尔传感器错误、接触不良、断开等情况 */
{
stop_motor1();
g_bldc_motor1.run_flag = STOP;
}
}
#endif
}
}
实验结果:



定时器中断时间加大,需要更大的占空比才能启动。

更多推荐

所有评论(0)