当前位置: 首页 > news >正文

单片机BLDC基础实验

单片机 :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(10000-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); } }

电机:

typedef struct { __IO uint8_t run_flag; /* 运行标志 */ __IO uint8_t locked_rotor; /* 堵转标记 */ __IO uint8_t step_sta; /* 本次霍尔状态 */ __IO uint8_t hall_single_sta;/* 单个霍尔状态 */ __IO uint8_t hall_sta_edge; /* 单个霍尔状态跳变 */ __IO uint8_t step_last; /* 上次霍尔状态 */ __IO uint8_t dir; /* 电机旋转方向 */ __IO int32_t pos; /* 电机位置 */ __IO int32_t speed; /* 电机速度 */ __IO int16_t current; /* 电机速度 */ __IO uint16_t pwm_duty; /* 电机占空比 */ __IO uint32_t hall_keep_t; /* 霍尔保持时间 */ __IO uint32_t hall_pul_num; /* 霍尔传感器脉冲数 */ __IO uint32_t lock_time; /* 电机堵转时间 */ __IO uint32_t no_single; __IO uint32_t count_j; } _bldc_obj; #define SHUTDOWN_PIN GPIO_PIN_10 /* PF10 */ #define SHUTDOWN_PIN_GPIO GPIOF #define SHUTDOWN_PIN_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */ #define SHUTDOWN_EN HAL_GPIO_WritePin(SHUTDOWN_PIN_GPIO,SHUTDOWN_PIN,GPIO_PIN_SET); /* 使能半桥芯片的SD引脚 */ #define SHUTDOWN_OFF HAL_GPIO_WritePin(SHUTDOWN_PIN_GPIO,SHUTDOWN_PIN,GPIO_PIN_RESET); /* 失能半桥芯片的SD引脚 */ /***************************************** 霍尔传感器接口 *************************************************/ #define HALL1_TIM_CH1_PIN GPIO_PIN_10 /* U */ #define HALL1_TIM_CH1_GPIO GPIOH #define HALL1_U_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0) /* PH口时钟使能 */ #define HALL1_TIM_CH2_PIN GPIO_PIN_11 /* V */ #define HALL1_TIM_CH2_GPIO GPIOH #define HALL1_V_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0) /* PH口时钟使能 */ #define HALL1_TIM_CH3_PIN GPIO_PIN_12 /* W */ #define HALL1_TIM_CH3_GPIO GPIOH #define HALL1_W_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0) /* PH口时钟使能 */ /****************************************** 电机相关系数 **************************************************/ #define MAX_PWM_DUTY (((10000) - 1)*0.96) /* 最大占空比限制 */ #define H_PWM_L_ON #ifndef H_PWM_L_ON #define H_PWM_L_PWM #endif #define CCW (1) /* 逆时针 */ #define CW (2) /* 顺时针 */ #define HALL_ERROR (0xF0) /* 霍尔错误标志 */ #define RUN (1) /* 电机运动标志 */ #define STOP (0) /* 电机停机标志 */
_bldc_obj g_bldc_motor1 = {STOP,0,0,CCW,0,0,0,0,0,0}; /* 电机结构体初始值 */ /** * @brief 无刷电机初始化,包括定时器,霍尔接口以及SD引脚初始化 * @param arr: 自动重装值 * @param psc: 时钟预分频数 * @retval 无 */ void bldc_init(uint16_t arr, uint16_t psc) { GPIO_InitTypeDef gpio_init_struct; SHUTDOWN_PIN_GPIO_CLK_ENABLE(); gpio_init_struct.Pin = SHUTDOWN_PIN; gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; gpio_init_struct.Pull = GPIO_NOPULL; gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(SHUTDOWN_PIN_GPIO, &gpio_init_struct); hall_gpio_init(); /* 霍尔接口初始化 */ atim_timx_oc_chy_init(arr, psc); /* 定时器初始化 */ } /** * @brief BLDC控制函数 * @param dir :电机方向, Duty:PWM占空比 * @retval 无 */ void bldc_ctrl(uint8_t motor_id,int32_t dir,float duty) { if(motor_id == MOTOR_1) { g_bldc_motor1.dir = dir; /* 方向 */ g_bldc_motor1.pwm_duty = duty; /* 占空比 */ } } /************************************ 霍尔接口初始化 ******************************************/ /** * @brief 霍尔传感器接口初始化 * @param 无 * @retval 无 */ 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); } /** * @brief 获取霍尔传感器引脚状态 * @param motor_id : 电机接口号 * @retval 霍尔传感器引脚状态 */ 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; } /************************************* BLDC相关函数 *************************************/ /** * @brief 关闭电机运转 * @param 无 * @retval 无 */ void stop_motor1(void) { /* 关闭半桥芯片输出 */ SHUTDOWN_OFF; /* 关闭PWM输出 */ 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->CCR2 = 0; g_atimx_handle.Instance->CCR1 = 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); } /** * @brief 开启电机运转 * @param 无 * @retval 无 */ 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); } /*************************** 上下桥臂的导通情况,共6种,也称为6步换向(接口一) ****************************/ /* 六步换向函数指针数组 */ 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); }

定时器:

/* 高级定时器 定义 */ /* TIM_CHx通道 上桥臂IO定义 */ #define ATIM_TIMX_PWM_CH1_GPIO_PORT GPIOA #define ATIM_TIMX_PWM_CH1_GPIO_PIN GPIO_PIN_8 #define ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ #define ATIM_TIMX_PWM_CH2_GPIO_PORT GPIOA #define ATIM_TIMX_PWM_CH2_GPIO_PIN GPIO_PIN_9 #define ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ #define ATIM_TIMX_PWM_CH3_GPIO_PORT GPIOA #define ATIM_TIMX_PWM_CH3_GPIO_PIN GPIO_PIN_10 #define ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */ /* 下桥臂IO定义 */ #define M1_LOW_SIDE_U_PORT GPIOB #define M1_LOW_SIDE_U_PIN GPIO_PIN_13 #define M1_LOW_SIDE_U_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */ #define M1_LOW_SIDE_V_PORT GPIOB #define M1_LOW_SIDE_V_PIN GPIO_PIN_14 #define M1_LOW_SIDE_V_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */ #define M1_LOW_SIDE_W_PORT GPIOB #define M1_LOW_SIDE_W_PIN GPIO_PIN_15 #define M1_LOW_SIDE_W_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0) /* PB口时钟使能 */ /* 复用到TIM1 */ #define ATIM_TIMX_PWM_CHY_GPIO_AF GPIO_AF1_TIM1 #define ATIM_TIMX_PWM TIM1 #define ATIM_TIMX_PWM_IRQn TIM1_UP_TIM10_IRQn #define ATIM_TIMX_PWM_IRQHandler TIM1_UP_TIM10_IRQHandler #define ATIM_TIMX_PWM_CH1 TIM_CHANNEL_1 /* 通道1 */ #define ATIM_TIMX_PWM_CH2 TIM_CHANNEL_2 /* 通道2 */ #define ATIM_TIMX_PWM_CH3 TIM_CHANNEL_3 /* 通道3 */ #define ATIM_TIMX_PWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM1_CLK_ENABLE(); }while(0) /* TIM1 时钟使能 */
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); } /** * @brief 定时器底层驱动,时钟使能,引脚配置 此函数会被HAL_TIM_PWM_Init()调用 * @param htim:定时器句柄 * @retval 无 */ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) { if (htim->Instance == ATIM_TIMX_PWM) { GPIO_InitTypeDef gpio_init_struct; ATIM_TIMX_PWM_CHY_CLK_ENABLE(); /* 定时器时钟使能 */ /* 上桥臂的IO时钟使能 */ ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE(); ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE(); ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE(); /* 下桥臂的IO时钟使能 */ M1_LOW_SIDE_U_GPIO_CLK_ENABLE(); M1_LOW_SIDE_V_GPIO_CLK_ENABLE(); M1_LOW_SIDE_W_GPIO_CLK_ENABLE(); /* 下桥臂的IO初始化 */ gpio_init_struct.Pin = M1_LOW_SIDE_U_PIN; gpio_init_struct.Pull = GPIO_NOPULL; gpio_init_struct.Speed = GPIO_SPEED_HIGH; gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出模式 */ HAL_GPIO_Init(M1_LOW_SIDE_U_PORT, &gpio_init_struct); gpio_init_struct.Pin = M1_LOW_SIDE_V_PIN; HAL_GPIO_Init(M1_LOW_SIDE_V_PORT, &gpio_init_struct); gpio_init_struct.Pin = M1_LOW_SIDE_W_PIN; HAL_GPIO_Init(M1_LOW_SIDE_W_PORT, &gpio_init_struct); /* 上桥臂即定时器IO初始化 */ gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN; /* 通道y的GPIO口 */ gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */ gpio_init_struct.Pull = GPIO_NOPULL; /* 上拉 */ gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */ gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF; /* 端口复用 */ HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct); gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN; /* 通道y的CPIO口 */ HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct); gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN; /* 通道y的CPIO口 */ HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct); HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 2, 2); HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); } } /** * @brief 定时器中断服务函数 * @param 无 * @retval 无 */ void ATIM_TIMX_PWM_IRQHandler(void) { HAL_TIM_IRQHandler(&g_atimx_handle); } /** * @brief 定时器中断回调 * @param htim:定时器句柄 * @retval 无 */ 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) { 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 } }

实验结果:

http://www.cnnetsun.cn/news/2925630.html

相关文章:

  • 能源央企校招笔试怎么准备?我用这三套真题库(含中海油/中石化/中石油)一次上岸
  • 避坑指南:FR4板材做2.4G微带天线,这些仿真与实测的误差你遇到了吗?
  • 北森/赛马题库图形推理10分钟速成:互联网技术岗校招必考的行测题怎么破?(附旋转/对称/笔画规律图解)
  • AI Agent Harness Engineering 与人类协作:人机交互的新范式
  • STM32F103C8T6实现USB大容量存储(MSC)的避坑指南:Flash读写、FATFS配置与电脑识别的那些坑
  • 避开这些坑!UDS 0x2F服务开发中的NRC 13/22/31/33错误详解与排查指南
  • 从面试官视角拆解K8s:除了背题,面试官到底想考察你什么?(附真实场景问题)
  • 硬件面试官最爱问的10个电路图:从Buck到SPI时序,手把手教你画对答好
  • PyPDF终极指南:如何在5分钟内掌握Python PDF处理的核心技巧
  • 多智能体系统的死锁预防:资源分配与超时机制设计
  • 5个实战场景掌握unrpyc:高效反编译Ren‘Py游戏脚本
  • 跨模态推理实战:让 Gemini 3.5 看懂示意图并生成代码
  • 办公室员工在岗时间统计系统 以AI重构工时管理
  • (cvpr26) F2Net: A Frequency-Fused Network for Ultra-High Resolution Remote Sensing Segmentation
  • 三分钟掌握Real-ESRGAN-GUI:让模糊图片瞬间变清晰的终极指南
  • Ubuntu新手避坑:arm-linux-gcc命令找不到?可能是你装错了架构(附交叉编译工具链安装指南)
  • linux命令:lsof、uniq
  • 终极SillyTavern角色卡片实战指南:从零打造生动AI伙伴的完整教程
  • 告别追番困扰:Animeko跨平台弹幕播放器的三大核心价值
  • 别再问FAB厂转IC难不难了!手把手教你评估自身条件与制定学习路线(数字验证/版图方向)
  • 指纹浏览器代理中台设计:为每个指纹环境绑定独立出口IP的架构实现
  • 独立开发者必备:5 个能直接赚钱的全栈小产品 Prompt
  • 终极指南:如何构建高效的微信好友安全检测系统 - 从传统协议模拟到Hook技术的完整演进
  • 法考报名流程|报名入口|资料已整理
  • 如何快速掌握Dify工作流:新手友好的完整AI自动化指南
  • 为什么大厂都在用Elasticsearch?我部署一次后终于明白了
  • Browser Use 安装、使用方法详细全解
  • create_agent:LangChain 新版 Agent 的核心入口
  • HSTracker终极指南:macOS炉石传说智能卡组追踪器完全教程
  • MPC8260 MCCs:嵌入式通信硬件加速与SS7协议处理实战解析