野火STM32F407(骄阳)+无刷直流驱动板+永磁同步电机控制学习记录(二)(基于HAL库)

本文详细描述了如何使用霍尔传感器进行电机的六步换相控制,包括配置定时器3监控霍尔信号、定时器1生成PWM信号以及电机状态的控制逻辑。特别提到定时器3的开启和关闭时机对电机运行的影响。
摘要由CSDN通过智能技术生成

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,否则电机转动必须要手动转一下。(我也不知道为啥)
 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值