STM32驱动步进电机(HAL库)

一、基础配置

首先完成cubemx的基础配置。如下图所示

二、定时器配置

这里采用定时器2通道1来产生PWM波,配置如下。

定时器PWM的计算方法如下。

为方便代码函数的封装先采用84-1的预分频,即84MHZ除以84得到1MHZ。自动重装载值先随便写一个20000-1后续代码会更改,然后占空比是不影响步进电机的速度的,我们默认百分之五十即可,即下方PWM选择自动重装载值的一半即可。我们还要打开定时器中断,方便后续计数控制圈数。

接着,步进电机需要一个使能引脚和一个方向引脚,这里选择两个GPIO口输出就行了。这里选择PA2和PC0,可以根据需要更改IO口,然后直接生成代码就行。

三、步进电机

步进电机需要驱动器来驱动,这里我选择的是ATK-2MD5050这种驱动器。这种驱动器右侧有拨码开关,我们可以通过拨码开关的不同来选择模式。上面的Microstep是细分步数,下面我将解释一下,我们的步进电机上面会有信息,我这里使用的1.8°四线两相的步进电机,电流为1.7A。1.8°的意思就是满足一些脉冲数其转动的角度,即步距角。

我们知道一圈的度数是360°,那么360°除以1.8°得到200,这个200就是我们转一圈所需要的脉冲数,就是需要200个高低电平的PWM。即200个周期的PWM。这里我选择了16细分,即200乘以16=3200,3200才是我所需要的脉冲个数,即3200个脉冲信号。后续代码我也是以16细分来编写的。即SW1 SW2 SW3 SW4 满足ON OFF ON ON

接着,电机额定电流是1.7A,将开关打成2A即可 就是SW5 SW6 SW7 SW8 满足ON OFF OFF OFF

然后是驱动器右侧一栏,我们看控制信号那一栏,其中ENA+ DIR+ PUL+我们接上5V的电压就行了,然后ENA-的意思就是使能引脚,我们选择上面配置的GPIO口,这里我选择的是PC0来控制,高电平使能,低电平失能。

那么同理,大家应该就知道DIR-就是控制方向的了,我选择的是PA2来控制,高电平和低电平分别控制正转和反转。

最下面的呢,A+ A- B+ B- 是接步进电机四根线的,其中一相就是两根线,如果电机上有信息直接接上就行了对应的线。如果没有,大家可以把其中的线两两接触,如果转不动,那么就是一相的,接上去就行了。

到这里驱动器和步进电机就介绍完了。

四、代码编写

代码这里只讲解主要部分。

如果我们想要写一个驱动去控制步进电机转动的速度,我们就要明白,控制步进电机速度的是PWM波形的频率,那么上面的公式我们已经知道如何计算频率和周期了,这里我写的是让步进电A机转一圈需要多少秒来控制步进电机的速度的。我们不改变预分频系数和驱动器的细分步长来控制变量,那么现在未知量就是用户输入的几秒钟,我们设为X变量,还有通过X得到需要改变的ARR即重装载值,设为Y,两个变量满足什么关系呢?不难得到PWM波形频率的倒数就是周期T,我们已知3200的脉冲数是固定的,那么就有以下的关系式,从而得到X与Y的关系,我们写成代码即可。其中的X是我们要输入的参数即多少秒转一圈,其中的Y就是我们需要更改的重装载值,从而去改变PWM输入的周期,从而改变转速。

上面,我们已经实现了如何控制速度,那么如何控制圈数呢?我们只需要在定时中断里面,进行计数就可以了,因为3200个脉冲转一圈是固定的数,我们只需要读取定时器中断里面的数值除以3200,就知道现在过去了几圈。再进行比较的if语句,就能实现控制了。这里我用KE1表示按键按下,大家知道即可。记得使能中断函数。

这里只介绍主要函数的由来,代码放在下面自取。

http://通过网盘分享的文件:Paper count.zip 链接: https://pan.baidu.com/s/1SJf5ogEy3rZhWaAnjx-uoQ?pwd=94y6 提取码: 94y6 --来自百度网盘超级会员v4的分享

#ifndef  __motor_H__
#define __motor_H__

#include "stm32f4xx_hal.h"
#include "tim.h"
#include "gpio.h"

extern int num;
extern float arr;
extern int key1;
	
void Motro1_PWM_Start(void);//初始化PWM
				
void Motor1_enable(void);//PC0使能

void Motor1_disable(void);//PC0失能

void Motor1_course(char course_mod);//PA2正转反转

void Motor1_Speed(float speed);//1圈所耗时间 使用16细分计算 占空比默认百分之五十

void Motro1_angle(int Angle,float TTIME);  //参数1为圈数 参数2为速度


#endif

#include "motor.h"
#include "tim.h"
int num=0;
int key1=1;//按键按下给标志位1 先默认为0 后续更改
float arr=0;
TIM_OC_InitTypeDef Motor_PWM_sConfigOC = {0};
//TIM_HandleTypeDef htim2;
//初始化步进电机PWM
void Motro1_PWM_Start(void)
{
	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); //串口2通道1 可修改其他串口
	
}

//步进电机使能 PC0
void Motor1_enable(void)
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET); 
	
}
//步进电机失能 PC0
void Motor1_disable(void)
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); 
	
}
//步进电机正转反转 PA2正转反转
void Motor1_course(char course_mod)
{
	if(course_mod == 1){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);}		// 正转
	else if(course_mod == 0){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);}			// 反转
}
//控制电机速度 1圈几秒
void Motor1_Speed(float time)
{
	arr = 312.5f*time;
	__HAL_TIM_SET_AUTORELOAD(&htim2, arr);
	__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, arr/2);
}
//参数1圈数 参数2速度
void Motro1_angle(int Angle,float TTIME)
{	
	if(key1==1)
	{
		Motor1_Speed(TTIME);
		if(Angle<=(num/3200))
		{
			HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); 
			num=0;
			key1=0;
		}
	}
}

//定时器中断函数 用于计算圈数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim == (&htim2))
    {
			if(key1==1)
			{
				num ++;
			}
    }
}

### 使用HAL实现步进电机驱动及控制 通过使用STM32HAL可以方便地完成步进电机驱动与控制。以下是基于提供的引用以及专业知识整理的内容。 #### 1. 系统初始化 在`main.c`文件中,首先需要进行系统的初始化操作,包括时钟配置、GPIO设置以及其他外设初始化。随后调用自定义函数`Motor_Init()`来初始化步进电机的相关参数[^1]。 ```c #include "motor.h" int main(void) { // 系统初始化代码... // 初始化电机 Motor_Init(); while (1) { Motor_Update(); // 更新电机状态 HAL_Delay(2); // 控制电机速度 } } ``` #### 2. 步进电机初始化 (`Motor_Init`) 此部分主要负责配置用于驱动步进电机的硬件资源,例如定时器和GPIO引脚。通常会涉及以下几个方面: - **GPIO 配置**: 将ULN2003模块连接到指定的GPIO引脚上。 - **TIM 定时器配置**: 利用PWM信号生成所需的脉冲序列以驱动步进电机转动。 具体实现如下所示: ```c void Motor_Init() { GPIO_InitTypeDef GPIO_InitStruct = {0}; TIM_HandleTypeDef htim; // 启用相关外设时钟 __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_TIM2_CLK_ENABLE(); // 配置GPIO模式为推挽输出 GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 设置定时器参数 htim.Instance = TIM2; htim.Init.Prescaler = 84 - 1; // 假设系统频率为84MHz,则预分频系数为84 htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 999; // 自动重装载值 htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(&htim); HAL_TIM_PWM_Init(&htim); // 配置通道并启动PWM TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_TOGGLE; sConfigOC.Pulse = Toggle_Pulse; // 脉宽初始值 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; HAL_TIM_OC_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_OC_Start_IT(&htim, TIM_CHANNEL_1); } ``` 上述代码片段展示了如何利用HAL中的功能接口对GPIO端口及时序器进行必要的设定过程[^2]。 #### 3. 中断回调处理 为了精确控制步进电机的动作轨迹,在每次中断触发之后都需要调整相应的比较寄存器值(`CCR`)以便改变占空比从而影响转子位置变化情况。下面给出了一种可能的做法: ```c void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { static uint16_t count = 0; if(htim->Instance == TIM2){ count += Increment_Value; // 根据需求动态调节增量大小 __HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_1, count); } } ``` 这里采用了累加的方式逐步修改比较匹配值,进而达到连续供给不同宽度方波的目的,最终促使步进马达按照预定规律运转起来。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值