fssaafdsafd
、主要参考博客https://blog.csdn.net/weixin_44029896/article/details/128006602
基于霍尔传感器通过六步换相控制电机旋转
配置定时器3为霍尔传感器模式,并开启中断
定时器1配置,用于输出PWM,上半桥采用PWM控制,下半桥采用普通GPIO口控制
定义电机的结构体
//方向值的含义
enum DIRECTION
{
Motor_Stop,
Motor_Clockwise,
Motor_AntiClockwise
};
enum SPEED
{
Motor_Speed_0,
Motor_Speed_20,
Motor_Speed_40,
Motor_Speed_60,
Motor_Speed_80,
Motor_Speed_100
};
typedef struct
{
uint8_t Direction; //运动方向: 0 停止;1 顺时针;2 逆时针;
uint8_t Hall_Value; //霍尔值传感器读取的值:0~7
uint8_t Sector; //转子扇区: 1~6
uint8_t Speed; //电机转速: 1~6
uint16_t Compare; //PWM占空比 0~100
}MOTOR;
extern MOTOR Motor1;
新建一个hall.c文件,用于存放霍尔模式有关的函数
//返回转子所在扇区
uint8_t Get_Hall_Sector(void)
{
uint8_t HA_Level,HB_Level,HC_Level;
//读取HALL信号
HA_Level=HAL_GPIO_ReadPin(HA_GPIO_Port,HA_Pin);
HB_Level=HAL_GPIO_ReadPin(HB_GPIO_Port,HB_Pin);
HC_Level=HAL_GPIO_ReadPin(HC_GPIO_Port,HC_Pin);
return ((HA_Level) <<2 | (HB_Level <<1) | (HC_Level));
}
//判断所在扇区,并设定占空比
void HALL_SECTOR_SET(void)
{
uint8_t Control_Order;
//判断电机控制方向
if(Motor1.Direction==Motor_Clockwise)
{
Control_Order=Motor1.Hall_Value;
}else if(Motor1.Direction==Motor_AntiClockwise)
{
Control_Order=7-Motor1.Hall_Value;
}else
{
Control_Order=0;
}
//根据速度设定占空比
switch(Motor1.Speed)
{
case Motor_Speed_0:
Motor1.Compare=0*TIM1_ARR;
break;
case Motor_Speed_20:
Motor1.Compare=10*TIM1_ARR/100;
break;
case Motor_Speed_40:
Motor1.Compare=20*TIM1_ARR/100;
break;
case Motor_Speed_60:
Motor1.Compare=30*TIM1_ARR/100;
break;
case Motor_Speed_80:
Motor1.Compare=40*TIM1_ARR/100;
break;
case Motor_Speed_100:
Motor1.Compare=50*TIM1_ARR/100;
break;
default:
Motor1.Compare=0*TIM1_ARR;
break;
}
//扇区判断,顺时针运动
switch(Control_Order)
{
//C+,B-
case 1:
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,Motor1.Compare);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_RESET);
break;
//A+,B-
case 5:
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,Motor1.Compare);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_RESET);
break;
//A+,C-
case 4:
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,Motor1.Compare);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_RESET);
break;
//B+,C-
case 6:
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,Motor1.Compare);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_RESET);
break;
//B+,A-
case 2:
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,Motor1.Compare);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_RESET);
break;
//C+,A-
case 3:
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,Motor1.Compare);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_RESET);
break;
//出故障,全关了
default:
__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);
HAL_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_RESET);
break;
}
}
//触发中断,霍尔信号发生变化
void HAL_TIM_TriggerCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim3)
{
//获取当前扇区
Motor1.Hall_Value =Get_Hall_Sector();
//根据霍尔信号设定PWM占空比
HALL_SECTOR_SET();
}
}
main函数代码:KEY1启动电机、KEY2停止电机、KEY3加速、KEY4减速、KEY5反向
MOTOR Motor1;
int main(void)
{
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ADC1_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
//开启定时器和定时器更新中断和触发中断(HALL变量检测用)
__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_TRIGGER); //触发:有某个信号触发。
__HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE); //更新:有某个寄存器被更新。
//开启定时器1,输出上半桥的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_GPIO_WritePin(W_N_GPIO_Port,W_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(V_N_GPIO_Port,V_N_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(U_N_GPIO_Port,U_N_Pin,GPIO_PIN_RESET);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
//按键1按下,电机启动
if(Key_Scan(KEY1_GPIO_Port,KEY1_Pin)==KEY_ON)
{
//点亮LED_D11,串口输出电机启动,打开控制端口,设置初始速度(占空比)和初始方向,判断扇区并启动一次
LED_D11_ON;
printf("Motor Running\r\n");
HAL_GPIO_WritePin(MOTOR_SD_GPIO_Port,MOTOR_SD_Pin,GPIO_PIN_SET);
Motor1.Direction=Motor_Clockwise;
Motor1.Speed=Motor_Speed_20;
HAL_TIMEx_HallSensor_Start_IT(&htim3); //不能在初始化那里一直打开,必须在启动时打开,停止时关闭,否则需要手动转一下
HAL_TIM_TriggerCallback(&htim3); //初始执行一次霍尔换相
}else if(Key_Scan(KEY2_GPIO_Port,KEY2_Pin)==KEY_ON) //按键2按下,电机停止
{
//关闭LED_D11,串口输出电机停止,关闭控制端口,设置初始速度(占空比)和初始方向
LED_D11_OFF;
printf("Motor Stop\r\n");
HAL_GPIO_WritePin(MOTOR_SD_GPIO_Port,MOTOR_SD_Pin,GPIO_PIN_RESET);
Motor1.Direction=Motor_Stop;
Motor1.Speed=Motor_Speed_0;
HAL_TIMEx_HallSensor_Stop_IT(&htim3);
}else if(Key_Scan(KEY3_GPIO_Port,KEY3_Pin)==KEY_ON) //按键3按下,电机加速
{
if(Motor1.Speed<Motor_Speed_100)
Motor1.Speed++;
}else if(Key_Scan(KEY4_GPIO_Port,KEY4_Pin)==KEY_ON) //按键4按下,电机减速
{
if(Motor1.Speed>Motor_Speed_20)
Motor1.Speed--;
}else if(Key_Scan(KEY5_GPIO_Port,KEY5_Pin)==KEY_ON) //按键5按下,电机反向
{
if(Motor1.Direction==Motor_Clockwise)
Motor1.Direction=Motor_AntiClockwise;
else if(Motor1.Direction==Motor_AntiClockwise)
Motor1.Direction=Motor_Clockwise;
}
}
/* USER CODE END 3 */
}
这个电机有个奇怪的问题,定时器3(霍尔模式)的开启必须是在电机即将运动前,且电机停转的时候也要关闭定时器3,否则电机转动必须要手动转一下。(我也不知道为啥)