霍尔无刷电机控制-代码简单化1

前言

网上对与有感无刷电机资料较多,代码也不少,但是我感觉代码阅读还是难以理解,在此写下这个系列,希望可以向江科大一样,让代码简单易读,不要让简单事情复杂化,增加知识获取难度。

内容简介

目的:让有感无刷电机旋转起来,可以进行运行,停止两个按键对电机进行响应控制

环境:KEIL5:版本V5.24.2.0

          芯片:STM32F103RCT6

原理:检测霍尔值,控制电机换向。

通电方式:H-PWM_L-ON,(上三个MOS管采用PWM输出,下三个MOS管采用导通模式,但是一次只能开上三路一个和下三路一个,如下图Q1和Q5,Q1采用PWM,Q5导通,其他MOS管全部关闭,注意:如Q1和Q4为一路,不能同时导通,否则可能会烧毁设备)

一.线路连接

1.电机6个MOS管连接

HO1--PA8 U                   LO1--PB13  U

HO2--PA9 V                LO2--PB14  V

HO3--PA10 W                LO3--PB15 W

2.霍尔线及按键连接

HALL  A--PC6

HALL  B--PC7

HALL  C--PC8

按键采用上拉电阻,默认高电平,按下为低电平

RUN--PC5

STOP--PB1

二.GPIO 初始化

初始化控制电机的6个MOS管的IO口,注意控制PWM三路的输出模式

void TIM1_Gpio(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;  
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8| GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//因为采用TIM1的PEWM输出,所以采用AF_PP模式
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
 
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//正常输出,所以和上面有点区别
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

}

初始化霍尔线,正常IO口输入初始化

void Hall_State_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
}

按键和霍尔线一样

三.主要代码

1.霍尔值的获取

在这些函数上方先定义一下值:

uint16_t Hall_A,Hall_B,Hall_C,Hall_State_Val;//ABC 为单个值Hall_State_Val为霍尔总值

int Get_Hall_A_State(void)
{
	if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == 0)
	{
		Hall_A=0;
	}
	else
	{
		Hall_A=1;
	}
	return Hall_A;
}

如上分别写出B,C

Hall_State_Val计算:

HALL_STATE=(HALL_A+(HALL_B<<=1)+(HALL_C<<=2));//霍尔值格式为二进制,所以要进行移位计算

2.PWM初始化

因为要输出PWM,所以还要初始化PWM

代码如下:

void  Tim1_PWM_Init(void)
{
	TIM1_Gpio();
	TIM_InternalClockConfig(TIM1);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = 20;		//CCR
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);
	TIM_OC2Init(TIM1, &TIM_OCInitStructure);
	TIM_OC3Init(TIM1, &TIM_OCInitStructure);
	TIM_CtrlPWMOutputs(TIM1,ENABLE);//TIM1必须要有的开启函数	
	TIM_Cmd(TIM1, ENABLE);
}

说明:ARR和PSC根据需要可以自行设置,但是ARR为100好计算占空比

CRR值这儿没有用,无所谓随便设置(默认为0)

注意:使用TIM1 必须要有这行:

TIM_CtrlPWMOutputs(TIM1,ENABLE);//TIM1必须要有的开启函数  。新人切记

3.运行

换向

在运行前还要对换向进行设置,旋转时霍尔值为546231,这资料网上很多

如值为5的代码

case 0x5:
		{
			TIM1->CCR2 = 0;
			TIM1->CCR1 = shijian;	//CCR1 捕获、比较寄存器		
			TIM1->CCR3 = 0;
			GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15); 
			GPIO_SetBits(GPIOB, GPIO_Pin_14); 
		}
		break;

值为5为V-U+;所以开启低三路中PB14,关闭PB13,PB15即V-

高三路中开启PA8输出,其他两路值为0,所以等于关闭

TIM1->CCR1 = shijian;
void TIM_SetCompare1(TIM1, shijian);//这两行代码他们一样

这里shijian 为要设置的占空比,自行设置(0-100),实际情况在5以下转不起来

运行代码

void RUN(void)
{

	switch(Get_Hall_State_Val())
	{
		case 0x5:
		{
			TIM1->CCR2 = 0;
			TIM1->CCR1 = shijian;	//CCR1 捕获、比较寄存器		
			TIM1->CCR3 = 0;
			GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15); 
			GPIO_SetBits(GPIOB, GPIO_Pin_14); 
		}
		break;
		case 0x1:
		{
			GPIO_ResetBits(GPIOB, GPIO_Pin_15 | GPIO_Pin_13); //
			GPIO_SetBits(GPIOB, GPIO_Pin_14); //V-
			TIM1->CCR2 = 0;
			TIM1->CCR1 = shijian;					  
			TIM1->CCR3 = 0;
			GPIO_ResetBits(GPIOB, GPIO_Pin_15 | GPIO_Pin_14); 
			GPIO_SetBits(GPIOB, GPIO_Pin_14); 
		}
		break;
		case  0x3:    
		{
			TIM1->CCR2 = shijian;
			TIM1->CCR1 = 0;					  
			TIM1->CCR3 = 0;
			GPIO_ResetBits(GPIOB, GPIO_Pin_15 | GPIO_Pin_14);			
			GPIO_SetBits(GPIOB, GPIO_Pin_13);
		}
		break;
		case 0x2:
		{
			TIM1->CCR2 = shijian;
			TIM1->CCR1 = 0;					  
			TIM1->CCR3 = 0;
			GPIO_ResetBits(GPIOB, GPIO_Pin_14 | GPIO_Pin_15); 
			GPIO_SetBits(GPIOB, GPIO_Pin_13);
		}
		break;
		case  0x6:   
		{
			TIM1->CCR2 = 0;
			TIM1->CCR1 = 0;					  
			TIM1->CCR3 = shijian;
			GPIO_ResetBits(GPIOB, GPIO_Pin_15 | GPIO_Pin_13); 
			GPIO_SetBits(GPIOB, GPIO_Pin_13);	
		}
		break;

		case  0x4:
		{
			TIM1->CCR2 = 0;
			TIM1->CCR1 = 0;					  
			TIM1->CCR3 = shijian;
			GPIO_ResetBits(GPIOB, GPIO_Pin_13 | GPIO_Pin_15); 
			GPIO_SetBits(GPIOB, GPIO_Pin_14); 	
		}
		break;

	}
}

main函数:

int main(void)
{
	OLED_Init();//显示函数初始化,按自己喜好写
	Key_Init();
	Tim1_PWM_Init();
	while(1)
	{			
		OLED_Display();//显示函数,按自己喜好写,不影响电机运行
		Key_GetNum();//检测按键函数
	}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值