STM32驱动步进电机(附原工程)

2023-12-13 20:14:05

一、引言

本文旨在分享STM32对步进电机的驱动方法和代码工程(文末附工程连接)。初衷是我刚开始学者使用STM32驱动步进电机时,在CSDN上查阅了很多资料,好多都是只分享部分代码,有原工程的资源都需要付费!!!所以在我成功驱动步进电机后,我决定把驱动工程开源,以供和我一样的学者学习指导!

二、硬件准备?

1、单片机

这里我使用的是STM32F103C8T6,学者使用其他单片机也是可以的,关键看代码中的思路!

2、驱动模块

关于这个驱动模块的接线图,请看下图:

3、步进电机?

三、驱动的详细操作说明

这里我把搜集到的有关驱动如何使用的详细说明再列举一下,以方便大家加深理解,同时也是我对自己所学知识点的总结共享。

?四、关键代码

1、电机的初始化配置,相关引脚配置

#include "sm.h"

//num用于对引脚的索引,j用于计算步数,fx为电机旋转方向
unsigned short int num=0,j,fx;

void dj_GPIO_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口时钟
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB
 GPIO_ResetBits(GPIOB,GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8);						 //PB.5/6/7/8 输出低电平
}

void TIM3_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 计数到5000为500ms
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

	TIM_ITConfig(  //使能或者失能指定的TIM中断
		TIM3, //TIM
		TIM_IT_Update ,
		ENABLE  //使能
		);
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级0级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
	NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

	TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设
							 
}

static uint8_t GPIO_list[] = {0x01,0x02,0x04,0x08};     //对应驱动器4引脚,即电机4相

void TIM3_IRQHandler(void)   //TIM3中断
{
	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源 
		{
			TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源 
			if(judge == 0)
			{
			  judge=0;
			}
			if(judge == 1)
			{
				 if(fx == 0)  //fx为电机旋转方向,fx=0时电机正转,fx=1时电机反转
		     {
					 dj_GPIO1 = ~(GPIO_list[num]&GPIO_list[0])>>0;  //判断是否为引脚1,然后将其数值向右移动0位至第1位,得到unsigned int类型时的1或0
					 dj_GPIO2 = ~(GPIO_list[num]&GPIO_list[1])>>1;  //判断是否为引脚2,然后将其数值向右移动1位至第1位,得到unsigned int类型时的1或0
					 dj_GPIO3 = ~(GPIO_list[num]&GPIO_list[2])>>2;  //判断是否为引脚3,然后将其数值向右移动2位至第1位,得到unsigned int类型时的1或0
					 dj_GPIO4 = ~(GPIO_list[num]&GPIO_list[3])>>3;  //判断是否为引脚4,然后将其数值向右移动3位至第1位,得到unsigned int类型时的1或0
			 	 }
				 if(fx == 1)
				 {
					 dj_GPIO4 = ~(GPIO_list[num]&GPIO_list[0])>>0;  //上述的反转
					 dj_GPIO3 = ~(GPIO_list[num]&GPIO_list[1])>>1;
					 dj_GPIO2 = ~(GPIO_list[num]&GPIO_list[2])>>2;
					 dj_GPIO1 = ~(GPIO_list[num]&GPIO_list[3])>>3;
				 }
				 num += 1;  //num用于对引脚的索引
				 j += 1;  //j用于计算步数
				 if(num == 4)  //到第4个GPIO后回到第1个GPIO
				 {
				   num = 0;
				 }
		     if(j == 2048&fx == 0)  //走完一圈同时是正转结束,对参数进行修改
		     {
					 j = 0;
					 fx = 1;
					 num = 0;
		     }
				 if(j == 2048&fx == 1)  //走完一圈同时是反转结束,对参数进行修改
				 {
					 j = 0;
					 fx = 0;
					 start = 0;
					 num = 0;
				 }
			}
		}
}

?2、主函数

/*

硬件连接方式如下:
		驱动器ULN2003:IN1-->PB8
									 IN2-->PB7
									 IN3-->PB6
									 IN4-->PB5
									 +、-连接电源5-12v
									 连接电机
		CH340:TXD-->PA10
		       RXD-->PA9
					 GND-->单片机GND
					 5V-->单片机5V

*/

#include "usart.h"
#include "delay.h"
#include "sm.h"
#include "Decode.h"

u8 judge = 0;  //judge为1时电机开始旋转,为0时停止
u8 start = 0;  //start为1时启动电机程序,为0时关闭

void run(void)  //电机启动程序
{
	if(start == 1) {judge = 1;}
	else {judge = 0;}
}

int main(void)
{
	delay_init();	    	 // 延时函数初始化
  dj_GPIO_Init();      // 电机初始化
	
	uart_init(115200);  //串口初始化
	
	judge = 0;  //电机停止运作
	start = 0;  //电机启动程序停止运作
	TIM3_Int_Init(19,7199);   //电机运行使用的定时器,72MHz,时间: 2ms = 20*7200/72000000s

	while(1)
	{
	 if(USART_RX_STA&0x8000)  //USART_RX_STA标志最高位置1(接收完成了)
	 {
		 Code_Analysis((u8*)USART_RX_BUF);  //判断接收数据是否正确
	 }
    run();  //电机启动程序
  }
}

?五、工程分享

链接:https://pan.baidu.com/s/1lUbV6sZAKrkNrclyVxGXlQ?pwd=zxf1?
提取码:zxf1?
--来自百度网盘超级会员V3的分享

链接:https://pan.baidu.com/s/1_aJUMeylCoUgCcGTQBda7A?pwd=zxf1?
提取码:zxf1?
--来自百度网盘超级会员V3的分享

文章来源:https://blog.csdn.net/m0_73931287/article/details/134976923
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。