【专题STM32F103】步进电机控制 stm32 hal库版本

步进电机工作原理简介(28BYJ-48)

https://www.bilibili.com/read/cv11379422?spm_id_from=333.999.0.0

内有详细介绍,要先看!!!

 

驱动例程代码 

头文件

复制代码
#ifndef __MOTOR_H
#define __MOTOR_H
#include "main.h"

////位带操作,实现51类似的GPIO控制功能
////具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
////IO口操作宏定义
//#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
//#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
//#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
////IO口地址映射
//#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
//#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
//#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
//#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
//#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
//#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
//#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

//#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
//#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
//#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
//#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
//#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
//#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
//#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
// 
////IO口操作,只对单一的IO口!
////确保n的值小于16!
//#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
//#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

//#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
//#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

//#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
//#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

//#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
//#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

//#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
//#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

//#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
//#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

//#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
//#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入


void motor_init(void);// 初始化
void motor_single_four_beat(uint8_t direction);// 单四拍 控制电机
void motor_double_four_beat(uint8_t direction);// 双四拍 控制电机
void motor_four_phase_eight_beat(uint8_t direction);// 四相八拍 控制电机


void motor_stop(void);

void motor_start_run(uint16_t angle, uint8_t direction, uint8_t mode) ; //电机角度,0顺时针,1逆时针,节拍模式
#endif
头文件
复制代码

源文件

复制代码
#include "motor.h"

void motor_init(void)// 初始化
{
   GPIO_InitTypeDef GPIO_InitStruct = {0};
  __HAL_RCC_GPIOA_CLK_ENABLE (  );
     
    GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull  = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

/*****************************************************************/

#define MOTOR_A_H PAout(4) = 1
#define MOTOR_A_L PAout(4) = 0

#define MOTOR_B_H PAout(5) = 1
#define MOTOR_B_L PAout(5) = 0

#define MOTOR_C_H PAout(6) = 1
#define MOTOR_C_L PAout(6) = 0

#define MOTOR_D_H PAout(7) = 1
#define MOTOR_D_L PAout(7) = 0
/*****************************************************************/
void motor_start_run(uint16_t angle, uint8_t direction, uint8_t mode) //电机角度
{
    int i = 0;
    // 查看28BYJ-48步进电机, 步距角=5.625°/64,其意思就是
    // 每64个脉冲步进电机集成的变速器输出轴就会转5.625度。
    int pulse = (int)((double)(angle/5.625)*64); 
        if( mode == 0x48)    // 四相八拍
        {
            for(i=0; i<pulse; i++){
                motor_four_phase_eight_beat(direction);
                HAL_Delay(2);//延时2ms,修改延时可改变电机转动速度。即修改了脉冲频率
            }
        }
        if( mode == 0x14)    // 单四拍
        {
             pulse = pulse/2;// 脉冲数折半
            for(i=0; i<pulse; i++){
                motor_single_four_beat(direction);
                HAL_Delay(2);//延时2ms,修改延时可改变电机转动速度。即修改了脉冲频率
            }
        }
        if( mode == 0x24)    // 双四拍
        {             
            pulse = pulse/2;// 脉冲数折半
            for(i=0; i<pulse; i++){
                motor_double_four_beat(direction);
                HAL_Delay(2);//延时2ms,修改延时可改变电机转动速度。即修改了脉冲频率
           }    
      }            
}
        
/*****************************************************************/        
void motor_four_phase_eight_beat(uint8_t direction)// 四相八拍 控制电机
{
    static uint8_t step = 0;
    if(1 == direction){//反转,逆时针
        if(0 == step) step = 8;
        step--;
    }
    if(0 == step){//步序1
        MOTOR_A_H;
        MOTOR_B_L;
        MOTOR_C_L;
        MOTOR_D_L;
    }else if(1 == step){//步序2
        MOTOR_A_H;
        MOTOR_B_H;
        MOTOR_C_L;
        MOTOR_D_L;
    }else if(2 == step){//步序3
        MOTOR_A_L;
        MOTOR_B_H;
        MOTOR_C_L;
        MOTOR_D_L;
    }else if(3 == step){//步序4
        MOTOR_A_L;
        MOTOR_B_H;
        MOTOR_C_H;
        MOTOR_D_L;
    }else if(4 == step){//步序5
        MOTOR_A_L;
        MOTOR_B_L;
        MOTOR_C_H;
        MOTOR_D_L;
    }else if(5 == step){//步序6
        MOTOR_A_L;
        MOTOR_B_L;
        MOTOR_C_H;
        MOTOR_D_H;
    }else if(6 == step){//步序7
        MOTOR_A_L;
        MOTOR_B_L;
        MOTOR_C_L;
        MOTOR_D_H;
    }else if(7 == step){//步序8
        MOTOR_A_H;
        MOTOR_B_L;
        MOTOR_C_L;
        MOTOR_D_H;
    }
    if(0 == direction){//正转,顺时针
        step++; if(8 == step) step = 0;
    }
}

/*****************************************************************/
void motor_single_four_beat(uint8_t direction)// 单四拍 控制电机
{
    static uint8_t step = 0;
    if(1 == direction){//反转
        if(0 == step) step = 4;
        step--;
    }
    if(0 == step){//步序1
        MOTOR_A_H;
        MOTOR_B_L;
        MOTOR_C_L;
        MOTOR_D_L;
    }else if(1 == step){//步序2
        MOTOR_A_L;
        MOTOR_B_H;
        MOTOR_C_L;
        MOTOR_D_L;
    }else if(2 == step){//步序3
        MOTOR_A_L;
        MOTOR_B_L;
        MOTOR_C_H;
        MOTOR_D_L;
    }else if(3 == step){//步序4
        MOTOR_A_L;
        MOTOR_B_L;
        MOTOR_C_L;
        MOTOR_D_H;
    }
    if(0 == direction){//正转
        step++; if(4 == step) step = 0;
    }
}

/*****************************************************************/
void motor_double_four_beat(uint8_t direction)// 双四拍 控制电机
{
    static uint8_t step = 0;
    if(1 == direction){//反转
        if(0 == step) step = 4;
        step--;
    }
    if(0 == step){//步序1
        MOTOR_A_H;
        MOTOR_B_L;
        MOTOR_C_L;
        MOTOR_D_H;
    }else if(1 == step){//步序2
        MOTOR_A_H;
        MOTOR_B_H;
        MOTOR_C_L;
        MOTOR_D_L;
    }else if(2 == step){//步序3
        MOTOR_A_L;
        MOTOR_B_H;
        MOTOR_C_H;
        MOTOR_D_L;
    }else if(3 == step){//步序4
        MOTOR_A_L;
        MOTOR_B_L;
        MOTOR_C_H;
        MOTOR_D_H;
    }
    if(0 == direction){//正转
        step++; if(4 == step) step = 0;
    }
}

/*****************************************************************/
void motor_stop(void)
{
    //四相输出都为低电平是,电机停止工作
    MOTOR_A_L;
    MOTOR_B_L;
    MOTOR_C_L;
    MOTOR_D_L;
}
源代码
复制代码

测试代码

复制代码
    /**步进电机测试**/    
    motor_init();// 初始化
    motor_start_run(90, 1, 0x14); //电机角度90,逆时针,单四拍
    motor_start_run(90, 0, 0x48); //电机角度90,顺时针,四相八拍
    motor_start_run(90, 1, 0x24); //电机角度90,逆时针,双四拍
    motor_start_run(90, 0, 0x48); //电机角度90,顺时针,四相八拍
    
    motor_stop();
    /**END 步进电机测试**/    
复制代码

 

posted @   辛河  阅读(365)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示