主控板STM32F302R8+驱动板X-NUCLEO-IHM07M1+直流无刷电机WR36BL61,采用六步换相法实现电机的正反转驱动。
关于X-NUCLEO-IHM07M1驱动板的介绍,请阅读:
直流有刷电机驱动基于STM32F302R8+X-NUCLEO-IHM07M1(一)
直流无刷电机的驱动原理请阅读:
直流无刷电机及Matlab/Simulink驱动仿真
驱动直流无刷电机转动,并实现直流无刷电机的换向控制;按下一次按键电机正转;再按一次按键电机停止;再按一次按键电机反转;再按一次按键电机停止,以此循环。
控制板:STM32F302R8
驱动板:X-NUCLEO-IHM07M1
直流无刷电机:WR36BL61,额定功率10W,额定电压24V,额定电流0.5A,转速2000RMP,极对数2。
为了更直观简单的实现直流无刷电机的六步换相控制,将所用引脚均设置为普通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环境中编写应用层程序
在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);
}
主控板STM32F302R8+驱动板X-NUCLEO-IHM07M1+直流无刷电机WR36BL61,采用六步换相法实现电机的正反转驱动,为后续章节的分析奠定基础。