STM32F407-用TB6600驱动器驱动57步进电机(代码+连线)

2023-05-16

一、硬件

1.硬件准备

57步进电机(型号57CM18),驱动器TB6600,开发板STM32F407ZGT6

2.电气特性

 

3.连线

驱动器右边分有两个区域

Signal:用于驱动器与开发板连接,进行电机的控制驱动。

  • ENA接口:当此信号有效时,驱动器将自动切断电机绕组电流,使电机处于自由状态(无保持转矩)。当此信号不连接时默认为无效状态,这时电机绕组通以电流,可正常工作。
  • DIR接口:控制电机旋转方向,信号有效时电机顺时针旋转,无效时逆时针旋转。
  • PUL接口:步进电机驱动器把控制器发出的脉冲信号转化为步进电机的角位移,驱动器每接受一个脉冲信号 PUL,就驱动步进电机旋转一个步距角,PUL 的频率和步进电机的转速成正比。对于最佳输入要求,此信号占空比最好 1:1,脉冲信号的频率不大于100KHz

连接方式有两种方法:

(1)共阳极连接

将驱动器的ENA+,DIR+,PUL+接地, 阴极接电,也就是开发板的相对应的控制管脚。

(2)共阴极连接

如STM32F407接线如下:

ENA+ (驱动器)   PE6 (开发板)
DIR+ (驱动器)  PE5 (开发板)
PUL+ (驱动器)  PC7 (开发板)
ENA- DIR- PUL- (驱动器) GND (开发板)
 

4. High Voltage区域

 
该区域用于驱动器与步进电机连接。
和下图类似:
 

 

电机接法: 

 

这里我采用的是驱动器接法是共阴极接法 

对于电源,开发板使用3.3v,电机使用12v,1A,可根据实际情况调整。 

5.细分

拨码开关有六位,分别为S1-S6,定义如下:

 

根据需求,该驱动器最多支持32细分,根据指示的S1,S2,S3开关状态调整驱动器侧面的dip拨码进行细分选择,同样可以通过S4,S5,S6三个开关控制电流大小,最大支持3.5A,峰值电流为4.0A。

我这里采用了4细分。具体如下图:

5.故障问题

PWR :绿灯,电源指示灯。
ALARM :红灯,故障(过流、过热和欠压)时亮。红灯亮起时,表明驱动器出故障了,
请立即切断驱动器电源,排除故障后再继续操作。
 

二、代码

 1.主要函数

主要用到了四个函数

void Driver_Init(void);//驱动器初始化

void TIM8_OPM_RCR_Init(u16 arr, u16 psc);//TIM8_CH2 初始化 单脉冲+重复计数模式

void Locate_Rle(long num, u32 frequency, DIR_Type dir) //相对定位函数

void Locate_Abs(long num, u32 frequency);/绝对定位函数

 

2.驱动初始化

 

由于ENA和DIR使用的引脚为PE6,PE5,因此在初始化中对它们进行相关的初始化即可。

整体流程:

定义GPIO结构体

使能GPIOE时钟

对结构体进行相关初始化,推挽输出,上拉等

设置PE5,输出为高电平沿顺时针方向

设置PE6,输出为低电平,使能输出

 
 
void Driver_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOE,GPIO_Pin_5);
	GPIO_ResetBits(GPIOE,GPIO_Pin_6);
}

3.定时器

定时器的时基单元主要有三个寄存器组成:16位计数器,自动重转载寄存器(包括一个影子寄存器),预分频器(控制计数器时钟),其中预分频计数器的时钟频率1——65535。

16位向上、向下、向上/向下自动装载计数器
● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意
数值
● 4个独立通道:
─ 输入捕获
─ 输出比较
─ PWM生成(边缘或中间对齐模式)
─ 单脉冲模式输出
● 使用外部信号控制定时器和定时器互连的同步电路
● 如下事件发生时产生中断/DMA: ─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
─ 输入捕获
─ 输出比较
● 支持针对定位的增量(正交)编码器和霍尔传感器电路
● 触发输入作为外部时钟或者按周期的电流管理

因为用到TIME8与GPIOC(进行端口复用),所以使能对应的时钟。将GPIOC的Pin7复用为TIME8,对TIME8的结构体进行变量初始化,查开发手册可以知道,PC7复用功能为TIME8的CH2。

整体流程 

  • 配置TIME8,GPIOC时钟。
  • 初始化TIM8,设置ARR(自动装填值即周期),PSC(时钟预分频系数)
  • 设置TIM8_CH2的PWM模式,使能TIM2_CH2输出

 使能TIM2

/***********************************************
//TIM8_CH2(PC7) 单脉冲输出+重复计数功能初始化
//TIM8 时钟频率 84*2=168MHz
//arr:自动重装值
//psc:时钟预分频数
************************************************/
void TIM8_OPM_RCR_Init(u16 arr,u16 psc)
{		 					 
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);  	//TIM8时钟使能    
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 	//使能PORTC时钟	                                                                     	

	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM8); //GPIOC7复用为定时器8
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;           //GPIOC7
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;      //下拉
	GPIO_Init(GPIOC,&GPIO_InitStructure);               //初始化PF9
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值   
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
	TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	TIM_ClearITPendingBit(TIM8,TIM_IT_Update);

	TIM_UpdateRequestConfig(TIM8,TIM_UpdateSource_Regular); /********* 设置只有计数溢出作为更新中断 ********/
	TIM_SelectOnePulseMode(TIM8,TIM_OPMode_Single);/******* 单脉冲模式 **********/
 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出2使能
	TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; /****** 比较输出2N失能 *******/
	TIM_OCInitStructure.TIM_Pulse = arr>>1; //设置待装入捕获比较寄存器的脉冲值,右移一位
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
	TIM_OC2Init(TIM8, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

	TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);  //CH2预装载使能	 
	TIM_ARRPreloadConfig(TIM8, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_ITConfig(TIM8, TIM_IT_Update ,ENABLE);  //TIM8   使能或者失能指定的TIM中断
 
	NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;  //TIM8中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级1级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级1级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
	
	TIM_ClearITPendingBit(TIM8, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源
	TIM_Cmd(TIM8, ENABLE);  //使能TIM8											  
}

4.中断服务函数

void TIM8_UP_TIM13_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM8,TIM_FLAG_Update)!=RESET)//更新中断
	{
		TIM_ClearITPendingBit(TIM8,TIM_FLAG_Update);//清除更新中断标志位		
		if(is_rcr_finish==0)//重复计数器未设置完成
		{
			if(rcr_integer!=0) //整数部分脉冲还未发送完成
			{
				TIM8->RCR=RCR_VAL;//设置重复计数值
				rcr_integer--;//减少RCR_VAL+1个脉冲				
			}else if(rcr_remainder!=0)//余数部分脉冲 不为0
			{
				TIM8->RCR=rcr_remainder-1;//设置余数部分
				rcr_remainder=0;//清零
				is_rcr_finish=1;//重复计数器设置完成				
			}else goto out;   //rcr_remainder=0,直接退出			 
			TIM_GenerateEvent(TIM8,TIM_EventSource_Update);//产生一个更新事件 重新初始化计数器
			TIM_CtrlPWMOutputs(TIM8,ENABLE);	//MOE 主输出使能	
			TIM_Cmd(TIM8, ENABLE);  //使能TIM8			
			if(motor_dir==CW) //如果方向为顺时针   
				current_pos+=(TIM8->RCR+1);//加上重复计数值
			else          //否则方向为逆时针
				current_pos-=(TIM8->RCR+1);//减去重复计数值			
		}else
		{
out:		is_rcr_finish=1;//重复计数器设置完成
			TIM_CtrlPWMOutputs(TIM8,DISABLE);	//MOE 主输出关闭
			TIM_Cmd(TIM8, DISABLE);  //关闭TIM8				
			printf("当前位置=%ld\r\n",current_pos);//打印输出
		}	
	}
}

5.相对定位函数

首先判断脉冲如果小于0就停止运行。频率的取值在20-100000Hz之间,如果不在这个范围内就终止。

通过传入的参数dir可以知道旋转方向,若为顺时针,就用当前位置加上一个脉冲对应的步距,如果是逆时针就减去。

最后获取重复计数器的整数和余数部分,开启TIM8

/********************************************
//相对定位函数 
//num 0~2147483647
//frequency: 20Hz~100KHz
//dir: CW(顺时针方向)  CCW(逆时针方向)
*********************************************/
void Locate_Rle(long num,u32 frequency,DIR_Type dir) //相对定位函数
{
	if(num<=0) //数值小等于0 则直接返回
	{
		printf("\r\nThe num should be greater than zero!!\r\n");
		return;
	}
	if(TIM8->CR1&0x01)//上一次脉冲还未发送完成  直接返回
	{
		printf("\r\nThe last time pulses is not send finished,wait please!\r\n");
		return;
	}
	if((frequency<20)||(frequency>100000))//脉冲频率不在范围内 直接返回
	{
		printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");
		return;
	}
	motor_dir=dir;//得到方向	
	DRIVER_DIR=motor_dir;//设置方向
	
	if(motor_dir==CW)//顺时针
		target_pos=current_pos+num;//目标位置
	else if(motor_dir==CCW)//逆时针
		target_pos=current_pos-num;//目标位置
	
	rcr_integer=num/(RCR_VAL+1);//重复计数整数部分
	rcr_remainder=num%(RCR_VAL+1);//重复计数余数部分
	is_rcr_finish=0;//重复计数器设置完成
	TIM8_Startup(frequency);//开启TIM8
}

6.绝对定位函数

绝对定位函数很简单,也就是说给定一个位置,固定的让电机转到这个位置即可。

当给定目标位置与当前位置不同时,先判断旋转方向然后复制给DIR,因为不确定给的位置是正值还是负值,所以最后求重复计数器的时候加了一个abs绝对值。

/********************************************
//绝对定位函数 
//num   -2147483648~2147483647
//frequency: 20Hz~100KHz
*********************************************/
void Locate_Abs(long num,u32 frequency)//绝对定位函数
{
	if(TIM8->CR1&0x01)//上一次脉冲还未发送完成 直接返回
	{
		printf("\r\nThe last time pulses is not send finished,wait please!\r\n");
		return;
	}
	if((frequency<20)||(frequency>100000))//脉冲频率不在范围内 直接返回
	{
		printf("\r\nThe frequency is out of range! please reset it!!(range:20Hz~100KHz)\r\n");
		return;
	}
	target_pos=num;//设置目标位置
	if(target_pos!=current_pos)//目标和当前位置不同
	{
		if(target_pos>current_pos)
			motor_dir=CW;//顺时针
		else
			motor_dir=CCW;//逆时针
		DRIVER_DIR=motor_dir;//设置方向
		
		rcr_integer=abs(target_pos-current_pos)/(RCR_VAL+1);//重复计数整数部分
		rcr_remainder=abs(target_pos-current_pos)%(RCR_VAL+1);//重复计数余数部分
		is_rcr_finish=0;//重复计数器未设置完成
		TIM8_Startup(frequency);//开启TIM8
	}
}

7.main函数

主函数也很简单,先进行相关初始化,通过按键操控电机,按下wkup就通过绝对定位函数回到零点,按下key0就以500hz的频率顺时针发送200脉冲,假如不设置细分,该操作就是顺时针旋转一圈,key1也是一样,逆时针发送500脉冲。这里设置了一个计数器i,工作了50次后led会有一个提示。

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);      //初始化延时函数
	uart_init(115200);		//初始化串口波特率为115200
	usmart_dev.init(84); 	//初始化USMART			
	Driver_Init();			//驱动器初始化
	TIM8_OPM_RCR_Init(999,168-1); //1MHz计数频率  单脉冲+重复计数模式  
	while(1) 
	{		 	  
	Locate_Rle(800,400,CW);
	delay_ms(10);
	Locate_Rle(800,400,CCW);
	delay_ms(10);	
	}
}

8.测试

最终运行程序,电机就会转动起来,同时驱动器下面的led灯会闪烁蓝色的灯光,通过脉冲加频率可以调整速度,也可以通过细分设定去调节。我这里用到了两个步进电机和四个限位传感器,整个运行过程如下:

根据调用相对定位函数Locate_RleUD控制一号步进电机的旋转,顺时针旋转时通过齿轮带动履带,进行上升动作,当到达一号限位传感器(保上沿)的检测范围内后停止转动,然后开始进行工作。同理,使用Locate_RleUD控制一号步进电机逆时针旋转,当到达二号限位传感器(下沿)时,进行下降。

调用Locate_RleLR控制二号步进电机的旋转,同上面一号电机一样,通过改变参数来控制电机的旋转速度和方向,来进行左右转动,左右分别有三号和四号限位传感器,用于防止左右旋转角度过大,当到达传感器感知范围内时,限位传感器对应的IO口会输出高电平,函数中实时监测该IO口,当电平发生跳变时就停止电机的旋转。

补充一个,如何控制三个电机去走自定义的空间曲线,或者两个电机控制上下左右。

完整项目(步进电机驱动+限位传感器)

下载地址:https://download.csdn.net/download/qq_41573860/12657848

有问题或者哪里写的不对欢迎留言私信指出,一起探讨,可能回复不及时,但看见了就会回的。

github:vanbou/STM32F407_Motor: 本项目为控制42,57两个步进电机,带动齿轮,进行上下左右转动,四个限位金属传感器限制位置。 (github.com)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32F407-用TB6600驱动器驱动57步进电机(代码+连线) 的相关文章

  • KEIL5 调试STM32F407 停在LDR R0=SystemInit,不能进入main()函数

    点击魔术棒 xff0c 点击Debug 点击Setting Reset不要用Autodetect xff0c 选择SYSRESETREQ
  • 基于stm32f407通过USB配置CH340

    1 在设备枚举的case ENUM SET CONFIGURATION 设置配置 状态后 xff0c 配置CH340的波特率 xff0c 然后跳过CBW和CSW协议 xff1b 直接采用批量传输的方式进行数据传输
  • STM32F407-用TB6600驱动器驱动57步进电机(代码+连线)

    一 硬件 1 硬件准备 57步进电机 xff08 型号57CM18 xff09 xff0c 驱动器TB6600 xff0c 开发板STM32F407ZGT6 2 电气特性 3 连线 驱动器右边分有两个区域 Signal xff1a 用于驱动
  • STM32F407-串口通信基本原理

    1 处理器与外部设备通信的两种方式 xff1a 并行通信 传输原理 xff1a 数据各个位同时传输 优点 xff1a 速度快 缺点 xff1a 占用引脚资源多 串行通信 传输原理 xff1a 数据按位顺序传输 优点 xff1a 占用引脚资源
  • stm32f407 FreeRTOS+LVGL移植

    参考资料 xff1a 正点原子 littleVGL 开发指南 正点原子 STM32F407 FreeRTOS 开发指南 硬件平台 xff1a stm32f407开发板 xff08 或最小系统 xff09 4 3寸TFTLCD 以正点原子的例
  • STM32F407的LCD1602液晶显示程序

    LCD1602 H ifndef LCD1602 H define LCD1602 H include sys h include stm32f4xx h unsigned char message 20 unsigned char mes
  • STM32F407 Flash操作笔记

    简述 STM32F4XX的闪存擦除方式分为两种 xff1a 扇区擦除 xff08 最小单元16K xff09 和整片擦除 在实际应用中 xff0c 为满足重要信息的存储 xff0c 需将信息存入FLASH中 xff0c 针对以上两种擦除方式
  • STM32F407 串口编程USART1,USART2,USART3,UART4

    串口设置的一般步骤可以总结为如下几个步骤 xff1a 1 串口时钟使能 xff0c GPIO时钟使能 2 设置引脚复用器映射 xff1a 调用GPIO PinAFConfig函数 3 GPIO初始化设置 xff1a 要设置模式为复用功能 4
  • 成功解决keil识别不到单片机芯片,下载不了程序

    成功解决keil识别不到单片机芯片 下载不了程序 我的芯片是STM32F429 正点原子的阿波罗 今天使用开发板做实验 突然找不到芯片了 以前下载的PWM波也运行不了 查找了好久 原来是芯片锁了 终于解决了 我是第二种办法实现给芯片解锁的
  • STM32F103C8T6单片机IAP升级

    关于IAP升级的方法和原理 网上已经有很多资料了 这块就不再说了 现在就将bootloader和app配置方法整理如下 APP程序就是一个简单的LED闪烁 APP设置为从FLASH中启动 STM32F103C8T6单片机flash有64K
  • STM32F103 UART4串口使用DMA接收不定长数据和DMA中断发送

    一 前言 使用DMA通信的好处是 不占用单片机资源 不像普通串口中断 发送一个字节触发一次中断 发送100个字节触发100次中断 接收一个字节触发一次中断 接收200个字节触发200次中断 数据接收完毕触发一次DMA中断 发送数据完毕触发一
  • 步进电机基本原理及驱动方式详解

    步进电机基本原理及驱动方式详解 步进电机相关概念 基本原理 类型和结构 转子结构 定子结构 励磁方式 ATD9800 驱动使用实例 参考文献 步进电机相关概念 步进电机是一种常用于控制和定位应用的电动机 其独特的工作方式使其在许多领域中都具
  • STM32F407+ESP8266连接机智云过程详解

    工程创建 代码调试过程参见 STM32F407 ESP8266 程序源码下载 STM32F407 ESP8266连接机智云程序源码
  • STM32 之五 Core Coupled Memory(CCM)内存

    写在前面 今天在搞STM32F4时 用到了一部分特殊内存 CCM 搜了搜网上没多少介绍 索性自己查手册 某些芯片没有CCM 基本架构 废话少说 先看看这块内存特殊在哪里 官方的基本架构说明如下 The main system consist
  • Micropython应用篇四---F407VE Black开发板IIC OLED1306

    Micropython应用篇四 F407VE Black开发板IIC OLED1306显示 最近一段时间做Keil例程比Micropython多很多 无论如何 Micropython Arduino作为嵌入式入门篇也发过一些文章 包括公司的
  • STM32 之八 在线升级(IAP)超详细图解 及 需要注意的问题解决

    IAP 是啥 IAP In Application Programming 即在应用编程 也就是用户可以使用自己的程序对MCU的中的运行程序进行更新 而无需借助于外部烧写器 其实ST官网也给出了IAP的示例程序 感兴趣的可以直接去官网搜索
  • STM32F407移植FATFS文件系统(版本 R0.09b)支持长文件名和中文名称

    FatFs文件系统 默认是不支持长文件名和中文名称的 要想支持长文件名和中文名称 需要打开ffconf h文件进行配置 一 支持长文件名 FatFs文件系统 默认是不支持长文件名的 要想支持长文件名 需要打开ffconf h文件进行配置 找
  • 按键精准控制步进电机起保停,正反转(Arduino+TB6600驱动器)

    精准控制步进电机起保停 正反转 Arduino TB6600驱动器 步进电机和驱动器相关的资料 https pan baidu com s 1udb4MyEOXk4CTO7TKRHj6w 提取码 fuea 步进电机 TB6600驱动器 接线
  • STM32F407 USART3串口使用DMA接收不定长数据和DMA中断发送

    一 前言 使用DMA通信的好处是 不占用单片机资源 不像普通串口中断 发送一个字节触发一次中断 发送100个字节触发100次中断 接收一个字节触发一次中断 接收200个字节触发200次中断 数据接收完毕触发一次DMA中断 发送数据完毕触发一
  • Micropython开发篇三--基于F411 CE的移植编译

    Micropython开发篇三 基于F411 CE的移植编译 最近在学操作系统 RTOS与Linux 对Micropython有些新的认知 回头又复习了一下Micropython 简直要不要这么优秀 希望通过这篇文章能带给大家不一样的Mic

随机推荐