STM32+ULN2003驱动28BYJ4步进电机(根据圈数正转、反转)

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

采用STM32驱动28BYJ4步进电机,实现正转反转,完成角度调整。步进电机是一种将电脉冲转化为角位移的执行机构。当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动- -一个固定的角度(及步进角)。可以通过控制脉冲个来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。

一、环境介绍

MCU: STM32F103ZET6

编程软件: Keil5

二、硬件介绍

开发板采用STM32F103ZET6 最小系统板

img

电机驱动板采用的是ULN2003

img

步进电机采用的是28BYJ4 (5V 4相5线步进电机)

img

img

三、驱动代码

img

3.1 motor.c

 #include "motor.h"
 ​
 ​
 //步进电机正反转数组1
 u16 PositiveSequence[4] ={0x0200,0x0100,0x0080,0x0040};// D-C-B-A   
 u16 ReverseOrder[4]={0x0040,0x0080,0x0100,0x0200};// A-B-C-D.
 ​
 ​
 void motor_delay_ms(u32 ms)
 {
  u32 i,j;
     for(i=0;i<ms;i++)
         for(j=0;j<112;j++);
 }
 ​
 void motor_stop(void)  
 {  
     MOTOR_1=0;
     MOTOR_2=0;
     MOTOR_3=0;
     MOTOR_4=0;
 }
 ​
 void motor_init(void)
 {
     RCC->APB2ENR|=1<<4;
     GPIOC->CRL&=0x00FFFFFF;
     GPIOC->CRL|=0x33000000;
     GPIOC->CRH&=0xFFFFFF00;
     GPIOC->CRH|=0x00000033;
     
 // IN4: PC9   d
 // IN3: PC8   c
 // IN2: PC7   b
 // IN1: PC6   a
 }
 ​
 void GPIO_Write(GPIO_TypeDef* GPIOx, u16 PortVal)
 {
   GPIOx->ODR = PortVal;
 }
 ​
 ​
 void motor_just(int speed)  //一个脉冲
 {  
     uint8_t i;  
   
     for(i=0;i<4;i++)  
     {  
         GPIO_Write(GPIOC,PositiveSequence[i]);
         motor_delay_ms(speed);  
     }
 }
 ​
 ​
 void motor_back(int speed)  
 {  
     uint8_t i;  
     for(i=0;i<4;i++)  
     {  
         GPIO_Write(GPIOC,ReverseOrder[i]);  
         motor_delay_ms(speed);  
     } 
 ​
 }
 ​
 ​
 //由于   *一个脉冲*   *输出轴*  转0.08789度(电机实转0.08789*64=5.625度),即步进角为5.625度。则转完A-B-C-D为  *8个脉冲*  
 //,即0.08789*8=0.70312度。若称A-B-C-D为一个周期,则j为需要的转完angle角度所需的周期数。
 //步进电机正转角度函数
 void motor_just_angle(int angle,int speed)
 {
     int i,j;
     j=(int)(angle/0.70312);
     for(i=0;i<j;i++)
     {
         motor_just(speed);
     }
     motor_stop();
 }
 ​
 ​
 ​
 //步进电机反转角度函数
 void motor_back_angle(int angle,int speed)
 {
     int i,j;
     j=(int)(angle/0.70312);
     for(i=0;i<j;i++)
     {
         motor_back(speed);
     }
     motor_stop();
 }
 ​
 ​
 //步进电机反转圈函数
 void motor_back_circle(int ring ,int speed)
 {
     int i;
     for(i=0;i<ring;i++)
     {
         motor_back_angle(360,speed);
     }
 }
 ​
 //步进电机正转圈函数
 void motor_just_circle(int ring,int speed) //步进电机正转角度函数
 {
     int i;
     for(i=0;i<ring;i++)
     {
         motor_just_angle(360,speed);
     }
 }

3.2 motor.h

 #ifndef _MOTOR_H
 #define _MOTOR_H
 #include "sys.h"
 ​
 void motor_delay_ms(u32 x);//延时函数
 void motor_init(void);  //步进电机初始化
 void motor_just(int speed);    //步进电机正转函数
 void motor_back(int speed);   //步进电机反转函数
 void motor_just_angle(int angle,int speed);  //步进电机正转角度函数
 void motor_back_angle(int angle,int speed); //步进电机反转角度函数
 void motor_stop(void);  //步进电机停止函数
 void motor_just_circle(int ring ,int speed); //步进电机正转圈函数
 void motor_back_circle(int ring ,int speed);//步进电机反转圈函数
 ​
 //IN
 #define MOTOR_1  PCout(6)
 #define MOTOR_2  PCout(7)
 #define MOTOR_3  PCout(8)
 #define MOTOR_4  PCout(9)
 ​
 #endif

3.3 main.c

 /*
 ULN2003控制28BYJ-48步进电机接线:
 ​
 ULN2003接线:
 IN4: PC9   d
 IN3: PC8   c
 IN2: PC7   b
 IN1: PC6   a
 +  : 5V
 -  : GND
 */
 ​
 int main()
 {
     u8 time_cnt=0;
     u8 key;
     LED_Init();
     KEY_Init();
     USART1_Init(115200);
     motor_init();  //步进电机初始化
     USART1_Printf("程序初始化.....\r\n");
     
      while(1)
      {
          //按键可以测试开锁和关锁
         key=KEY_Scan(0);
         if(key==1)
         {
             LED1=0;  //亮灯--表示开锁
             motor_just_circle(1,300);   //电机正转1圈
         }
         else if(key==2)
         {
             LED1=1;  //灭灯--表示关锁
             motor_back_circle(1,300);  //电机反转1圈
         } 
 ​
         DelayMs(10);
         time_cnt++;
         if(time_cnt>=50)
         {
             time_cnt=0;
             LED2=!LED2;
         }
      }
 }

猜你喜欢

转载自juejin.im/post/7127449445897076744