直流无刷电机驱动基于STM32F302R8+X-NUCLEO-IHM07M1(一)


前言

主控板STM32F302R8+驱动板X-NUCLEO-IHM07M1+直流无刷电机WR36BL61,采用六步换相法实现电机的正反转驱动。
关于X-NUCLEO-IHM07M1驱动板的介绍,请阅读:
直流有刷电机驱动基于STM32F302R8+X-NUCLEO-IHM07M1(一)
直流无刷电机的驱动原理请阅读:
直流无刷电机及Matlab/Simulink驱动仿真

一、STM32F302R8+X-NUCLEO-IHM07M1驱动直流无刷电机

1.1.功能需求

驱动直流无刷电机转动,并实现直流无刷电机的换向控制;按下一次按键电机正转;再按一次按键电机停止;再按一次按键电机反转;再按一次按键电机停止,以此循环。

1.2.硬件设计

在这里插入图片描述
控制板:STM32F302R8
驱动板:X-NUCLEO-IHM07M1
直流无刷电机:WR36BL61,额定功率10W,额定电压24V,额定电流0.5A,转速2000RMP,极对数2。
在这里插入图片描述

1.3.软件设计

1.3.1.STM32CubeMX底层配置

为了更直观简单的实现直流无刷电机的六步换相控制,将所用引脚均设置为普通I/O口模式。
1、RCC设置为外接时钟,72MHz
2、PA8、PA9、PA10、PC10、PC11、PC12设置为推挽输出、无上下拉电阻、高速,初始化状态设为0;PA15、PB3、PB10设置为输入,无上下拉电阻;PB13设置为推挽输出,下拉电阻、高速,初始化状态为0;PC13设置为输入,无上下拉电阻。
3、使能USART2,异步模式,波特率115200,8位数据位,1位停止位,无奇偶校验位
3、IDE设置为MDK-RAM,在Keil环境中编写应用层程序
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3.2.应用层开发

在Keil环境中编写应用层程序,实现功能需求。

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  if(Key_Scany(KEY_GPIO_Port,KEY_Pin)==1)
	  {
		  Mode++;
		  if(Mode>3)
			  Mode=0;
	  }
	  
	  switch(Mode)
	  {
		  case 0:
			  BLDC_Stop();
			  LED_Stop();
		  break;
		  
		  case 1:
			  BLDC_Driver(1);
			  LED_Driver();
		  break;
		  
		  case 2:
			  BLDC_Stop();
			  LED_Stop();
		  break;
		  
		  case 3:
			  BLDC_Driver(0);
		      LED_Driver();
		  break;
	  }
  }
  /* USER CODE END 3 */
}

按键扫描函数Key_Scany()

/* USER CODE BEGIN 2 */
uint8_t Key_Scany(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	if(HAL_GPIO_ReadPin(GPIOx, GPIO_Pin)==0)
	{
		while(HAL_GPIO_ReadPin(GPIOx, GPIO_Pin)==0);
		return 1;
	}
	else 
		return 0;
}
/* USER CODE END 2 */

电机驱动函数BLDC_Driver()

/**************************************************/
/**WR36BL61的换相表,不同于正常直流无刷电机两两导通的
换相表,为尽大可能的利用资源,WR36BL61的换相表为每时刻
三个桥臂均有一个管子开启,厂家提供的换相表如下*******/
/*电机正转换相表**T为1代表桥臂上开下闭,T为0表示桥臂上闭下开*/
/*
 H1  H2  H3  T1  T2  T3
  0   0   1   1   0   1
  1   0   1   1   0   0
  1   0   0   1   1   0
  1   1   0   0   1   0
  0   1   0   0   1   1
  0   1   1   0   0   1
*************************************************/
/*电机反转换相表******
  0   0   1   0   1   0
  1   0   1   0   1   1
  1   0   0   0   0   1
  1   1   0   1   0   1
  0   1   0   1   0   0
  0   1   1   1   1   0
**************************************************/

void BLDC_Driver(uint8_t Direction)
{
	static uint8_t Pre_HallState=0;  //前一个霍尔状态值
	uint8_t HallState;
	HallState=Get_HallState();
	
	if(Pre_HallState!=HallState)  //霍尔状态发生改变,进行电机换相
	{
		HAL_GPIO_WritePin(GPIOC, EN1_Pin, GPIO_PIN_SET);  //使能三个桥臂
		HAL_GPIO_WritePin(GPIOC, EN2_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOC, EN3_Pin, GPIO_PIN_SET);
		
		HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  //三路桥臂的使能输入设置为0(每路桥臂上闭下开)
		HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
		
		if(Direction==1)  //电机正转
		{
			switch(HallState)  //根据霍尔状态值进行电机的换相
			{
				case 1:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
				break;
				
				case 5:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
				break;
				
				case 4:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
				break;
				
				case 6:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
				break;
				
				case 2:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
				break;
				
				case 3:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
				break;
				
				default:
					break;
			}
		}
		else  //电机反转
		{
			switch(HallState)  //根据霍尔状态值进行电机的换相
			{
				case 1:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
				break;
				
				case 5:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
				break;
				
				case 4:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
				break;
				
				case 6:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_SET);
				break;
				
				case 2:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
				break;
				
				case 3:
					HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_SET);  
					HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_SET);
					HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
				break;
				
				default:
					break;
			}
		}
		Pre_HallState=HallState;
	}	
}

霍尔状态函数Get_HallState()

uint8_t Get_HallState(void) //获取当前霍尔传感器的状态
{
	uint8_t HallState;      //算法为 H1<<2+H2<<1+H3
	    
	HallState=HAL_GPIO_ReadPin(H1_GPIO_Port, H1_Pin);
	HallState<<=1;
	HallState|=HAL_GPIO_ReadPin(GPIOB, H2_Pin);
	HallState<<=1;
	HallState|=HAL_GPIO_ReadPin(GPIOB, H3_Pin);
	
	return HallState;
}

电机停止函数BLDC_Stop()

void BLDC_Stop(void)
{
	HAL_GPIO_WritePin(GPIOC, EN1_Pin, GPIO_PIN_RESET);  //非能三个桥臂
	HAL_GPIO_WritePin(GPIOC, EN2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOC, EN3_Pin, GPIO_PIN_RESET);
	
	HAL_GPIO_WritePin(GPIOA, IN1_Pin, GPIO_PIN_RESET);  //三路桥臂的使能输入设置为0(每路桥臂上闭下开)
	HAL_GPIO_WritePin(GPIOA, IN2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, IN3_Pin, GPIO_PIN_RESET);
}

1.4.编译下载观察试验现象

在这里插入图片描述

总结

主控板STM32F302R8+驱动板X-NUCLEO-IHM07M1+直流无刷电机WR36BL61,采用六步换相法实现电机的正反转驱动,为后续章节的分析奠定基础。

  • 3
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值