基于STM32之控制步进电机,学到即赚到!(含主代码)

目录

前言

一、关于步进电机那点事

二、接线问题

三、主要代码

四、总结


前言

最近发现电机类的步进电机挺有趣的,于是趁快开学了有空再码一篇,分享一下自己的学习心得,有哪里写的不好欢迎随时指正。

一、关于步进电机那点事

这次使用的是二相步进电机,博客上也有许多关于步进电机的博文啊,质量也是参差不齐,今天就给大家仔细的介绍一下该电机,我主要还是继承以往的风格,资料方面我也讲的少,主要还是侧重实操方向,希望能够带给大家帮助

下面是图: 

首先要认识一下步进电机上的几条线:

四条线(红、蓝、绿、黑)

正常来说对应A+、A-、B+、B-,在电机上基本上也都会标明代表含义,其实步进电机的原理其实都差不多,主要就是学会使用和了解原理就基本上达到我们的目的了,如果想要深入学习,那可以再继续研究······

那么怎么使用呢?首先就要搭配一款步进电机的驱动器了,网上随便都可以买到,如图:

 这里我们很明显可以看到它有12个接口,这里再详细介绍一下如何使用接口:

V+:连接电源正极(注意电压在9V~32V之间即可,过大的话你懂得)

GND:连接电源负极

A+:连接电机绕组A+相

A- : 连接电机绕组A-相

B+:连接电机绕组B+相

B- : 连接电机绕组B-相

CP+:脉冲信号输入正 ( PUL+ )(取决于共阴、共阳接法再来接线,共阴的话CP-接地,CP+接脉冲信号即定时器PWM输出)

CP-:脉冲信号输入负  ( PUL-)

DIR+:电机正、反转控制正(同样取决于共阴共阳接法)

DIR-:电机正、反转控制负

EN+:电机脱机控制正(可以不接)

EN-:电机脱机控制负

二、接线问题

上面到这可能对它的接线有了一个想法了,那么具体如何接线呢?嘿嘿,这里有共阴和共阳的常见的两种接法,具体参照下图:

 这里我采用了共阴极的接法

那么我的接线:

DIR+:PA8(随便一个端口即可)

DIR-:GND

CP+:PA1(TIM2通道2)

CP-:GND

ENA不接

三、主要代码

这里的代码搬运后修改一些的,即可上手即可用

主函数

#include "stm32f10x.h"
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "key.h"
#include "led.h"	 
#include "usmart.h"	
#include "driver.h"

//共阴
/*
CP+->PA.1   CP-接GND
DIR+->PA.8  DIR-接GND
*/

int main(void)
{	 
	delay_init();	    	 	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 	
	uart_init(115200);	     
	KEY_Init();			
	Driver_Init();			
	TIM2_Init(999,72-1);       
	while(1) 
	{	
			Locate_Rle2(500,CW);
			delay_ms(5000);
			delay_ms(5000);
			delay_ms(5000);
			Locate_Rle2(500,CCW);
			delay_ms(5000);
			delay_ms(5000);
			delay_ms(5000);
		}

}	

 定时器函数:

#include "stm32f10x.h"
#include "driver.h"
#include "delay.h"
#include "usart.h"

long current_pos[2]={0,0}; 
int motor_dir2=0;
u8 count[2]={0,0};

void Driver_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_Init(GPIOA, &GPIO_InitStructure);					
	GPIO_SetBits(GPIOA,GPIO_Pin_8);						
}


void TIM2_Init(u16 arr,u16 psc)
{		 					 
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);                                                                      	

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;				//TIM2_CH2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;			
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
	
	TIM_TimeBaseStructure.TIM_Period = arr;					 
	TIM_TimeBaseStructure.TIM_Prescaler =psc;				
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 			
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); 		
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);				

	TIM_UpdateRequestConfig(TIM2,TIM_UpdateSource_Regular); 
	TIM_SelectOnePulseMode(TIM2,TIM_OPMode_Single);			
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;		
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
	TIM_OCInitStructure.TIM_Pulse = arr>>1; 				
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
	TIM_OC2Init(TIM2, &TIM_OCInitStructure); 				

	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);  		
	TIM_ARRPreloadConfig(TIM2, ENABLE); 					
	
	TIM_ITConfig(TIM2, TIM_IT_Update ,ENABLE);  			
 
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  		
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; 		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 	
	NVIC_Init(&NVIC_InitStructure);  						
	
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  			
	TIM_Cmd(TIM2, DISABLE);  															  
}
/******* TIM2*********/
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_FLAG_Update)!=RESET)
	{
		TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update);	
		count[0]++; 
		TIM_GenerateEvent(TIM2,TIM_EventSource_Update);
	
		TIM_Cmd(TIM2, ENABLE);  					  

		if(count[0]==200)
		{
			if(motor_dir2==CW) 						  
				current_pos[0]+=count[0];
			else          							  
				current_pos[0]-=count[0];
			TIM_Cmd(TIM2, DISABLE);  				  		
			printf("motor2µ±Ç°Î»ÖÃ=%ld\r\n",current_pos[0]);
			count[0]=0;
		}
	
	}
}

void TIM2_Startup(u32 frequency)   
{
	u16 temp_arr=1000000/frequency-1; 
	TIM_SetAutoreload(TIM2,temp_arr);
	TIM_SetCompare2(TIM2,temp_arr>>1); 
	
	TIM_SetCounter(TIM2,0);
	TIM_Cmd(TIM2, ENABLE);  
}


void Locate_Rle2(u32 frequency,DIR_Type dir) 
{
	
	if(TIM2->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_dir2=dir;
	
	DRIVER_DIR2=motor_dir2;				
	TIM2_Startup(frequency);			
}

 到这里你就会发现其实原理还是相当简单的,剩下的也不再深入了,希望能够对大家帮助哈哈

实现目的:

该程序就是实现正转后隔一会再反转,大家可以根据自己需求设置到自己想要的转动情况,同时要让他停下来,只需要在自己需要的地方设置一个TIM_SetCompare2(TIM2,0)即可停下,可以自由设置。

四、总结

今天关于步进电机就暂且介绍到这里,后面有需要会再特别介绍一下,文章写得还是比较简单,相信对于你还是可以很轻松入手的,到这里别忘了给点个赞,收藏一波,顺道关注一下,厚着脸皮求三连哈哈。

有需要代码可以随时评论留下邮箱即可,看到即回,其他博文也一样,有需要即可评论带上邮箱,同时欢迎交流学习

 

题外话:

挺喜欢彭于晏说的一句话:“我就是没有才华,所以才用命去拼!”

学习32之路固然辛苦,但要是坚持下来了,那不是很酷?哈哈哈

版权声明:本文为CSDN博主「不说二话的自家人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45930808/article/details/120070066

生成海报
点赞 0

不说二话的自家人

我还没有学会写个人说明!

暂无评论

相关推荐

趣聊51之串口通信(概念篇)

对于刚刚接触单片机的同学们来说,串口通信似乎是一个神秘感十足的东西,笔者在刚刚开始学习51单片机时,读的是郭天祥先生的那本著名的《新概念51单片机教程》,贼厚的一本书,但是等

stm32小车红外对管的循迹

为了参加校内赛写了分技术报告和相关代码 但是不想就这么浪费了 https://www.yuque.com/docs/share/a64051d0-cc1e-4e45-a704-db7a9af5cb76?# 《电控技术报告》 电控技术报告

嵌入式体系结构复习笔记

寄存器表示C语言的对应关系 R0: 存储C语言函数返回值R14 : 存储C的函数返回地址R15 : 当前执行程序的代码地址 ARM的常用指令 将数据加载到寄存器:MOV/LDR子程序调用指令: BL软中断调用指