外设模块学习(3)——28BYJ-48步进减速电机

28BYJ-48 步进减速电机详解

一、概述

28BYJ-48 是一种常见的小型 永磁式单极步进电机,因为价格低廉、易于驱动、扭矩适中,经常作为入门学习电机控制和单片机实践的首选。它的型号含义是:

  • 28:定子直径约 28mm;
  • BYJ:表示永磁单极步进电机系列;
  • 48:该系列中的具体型号编号,表示四拍和八拍都可以运行。

与普通直流电机不同,步进电机不是连续旋转的,而是每接收一个脉冲,按照设定的步距角"跳动"到下一个位置,因此非常适合需要精确控制角度和位置的场合。


二、关键概念

2.1 步距角

  • 定义:电机转子每走一步时转过的角度。
  • 28BYJ-48 电机的步距角为 5.625°

2.2

  • 指电机每响应一个控制脉冲时的最小转动单位。
  • 步数多少,取决于电机本身的步距角和驱动方式。

2.3

  • 指绕组通电的方式。
  • 常见模式有:
    • 四拍整步驱动 :每次点亮两个相邻绕组。电机本体每步转 11.25°
    • 八拍半步驱动 :单相和双相交替通电。电机本体每步转 5.625°

关系小结:

  • 步距角决定了电机单步的角度;
  • 拍决定了我们选择让电机每次走"大步"(整步)还是"小步"(半步);
  • 步就是电机走出来的实际动作。

三、电机本体的步数

根据 28BYJ-48 的步距角:

  • 整步驱动(四拍) :每步 11.25° → 一圈 = 360 ÷ 11.25 = 32 步
  • 半步驱动(八拍) :每步 5.625° → 一圈 = 360 ÷ 5.625 = 64 步

因此,"电机本体一圈约 32 步"指的是采用 四拍整步驱动时的情况。如果改用八拍半步驱动,本体一圈就是 64 步。


四、减速齿轮组

28BYJ-48 并不是直接输出电机本体的轴,而是经过了一组 减速齿轮

  • 实际减速比1/63.68395(通常近似为 1/64)。
  • 作用:降低转速、增加扭矩,使电机能驱动小型机械负载。

加上减速齿轮后,输出轴一圈所需的步数大幅增加:

  • 整步驱动

    32×64≈2048 步/圈

  • 半步驱动

    64×64≈4096 步/圈


五、驱动控制方式

28BYJ-48 一般通过 ULN2003 晶体管阵列驱动板连接到单片机(如 STM32),如下图所示。

控制方法就是让单片机的 4 个 IO 引脚按照一定的励磁顺序输出高低电平,从而依次给电机线圈通电。

  • 四拍整步:控制简单,每步 11.25°(电机本体),输出轴约 2048 步/圈。
  • 八拍半步:精度更高,每步 5.625°(电机本体),输出轴约 4076 步/圈。

在 STM32 程序中,只需要按照 励磁顺序表循环输出,就能让电机转动,并且通过控制步数来精确决定旋转角度。

六、控制原理

控制 28BYJ-28 就是控制它的 线圈通电顺序。常见的驱动方式有两种:

  1. 单相激励:一次只给一个线圈通电,省电但力矩小。
  2. 双相激励:同时给两个线圈通电,力矩大,转动更平稳。
  3. 半步模式:单相和双相交替,既保证力矩又能提高精度。

半步模式为例,通电顺序如下(对应 IN1-IN4):

复制代码
1 0 0 0  
1 1 0 0  
0 1 0 0  
0 1 1 0  
0 0 1 0  
0 0 1 1  
0 0 0 1  
1 0 0 1

这 8 个状态循环一次,就是电机转动 8 步。

七、控制与 STM32 的结合

7.1 硬件连接

  • 28BYJ-48 电机一般配套 ULN2003 晶体管驱动板使用。
  • 电机的 5 根线接到驱动板,驱动板再接到 STM32 的 4 个 GPIO 引脚。

7.2 控制方式

  • STM32 按照 励磁顺序表循环输出高低电平,驱动板放大电流,从而按步驱动电机。
  • 选择整步还是半步模式,取决于励磁方式:
    • 整步模式:每步走得大,输出轴约 2048 步一圈。
    • 半步模式:每步走得细,输出轴约 4076 步一圈。

7.3 角度和圈数计算

  • 需要电机转一整圈:输出 2048(整步)或 4096(半步)个脉冲
  • 需要电机转 90°:输出轴一圈步数 ÷ 4 → 512(整步)或 1024(半步)。

这样,你就可以精确地控制电机到达某个角度或转动指定圈数。

7.4 程序设计

  1. 定义一个数组存放步进电机的控制序列(如上面的 8 步)
  2. 依次循环输出序列到 GPIO
  3. 每输出一次延时一段时间,电机就转一步
  4. 通过改变延时长短,可以控制电机转速
  5. 通过控制循环次数,可以控制旋转角度

7.5 举例

  • 如果需要电机正转一圈:
    • 需要 4096 步
    • 循环执行 4096 次控制序列即可
  • 如果需要反转,则按逆序执行序列

八、基础案例------按键控制步进电机

8.1 项目概述

基于STM32F103C8T6微控制器,使用寄存器开发方式 实现通过按键控制28BYJ-48步进电机的转动

核心功能:

  • 初始状态:电机停在0度位置
  • 按键功能:每按一次,电机转动90度
  • 循环逻辑:正转一周(0→90→180→270→360)后,自动反向,再反转一周(360→270→180→90→0),如此循环往复

8.2 硬件接线说明

外设模块 引脚连接 (STM32F103C8T6) 接线细节
ULN2003驱动板 IN1 → PA0 IN2 → PA1 IN3 → PA2 IN4 → PA3 驱动板的4个控制信号输入端,连接到STM32的GPIO输出口
28BYJ-48电机 线圈A/B/A-/B- → ULN2003 OUT1~OUT4 公共端(COM) → 5V电源 电机线圈必须通过驱动板驱动,公共端需接外部5V电源
轻触按键 一端 → PB7 另一端 → GND 按键一端接PB7,另一端接地。代码中已启用STM32内部上拉电阻
电源 5V/1A 为ULN2003驱动板和步进电机供电,务必与STM32共地(GND)
ST-Link V2 SWDIO, SWCLK, GND, 3.3V 严格对应引脚连接,为单片机提供调试和烧录接口

⚠️ 特别注意:

  • 电机和驱动板的电源必须与STM32的GND连接在一起(共地),否则无法通信。
  • 28BYJ-48电机的公共端(通常是红色线)必须接到5V电源,而不是3.3V。

8.3 核心代码

8.3.1 步进电机控制部分
c 复制代码
#include "includes.h"

uint8_t g_motorDir = 1; // 电机方向,1正转,0反转

// 四相八拍通电顺序表
uint8_t stepSequence[8][4] =
    {
        {1, 0, 0, 0},
        {1, 1, 0, 0},
        {0, 1, 0, 0},
        {0, 1, 1, 0},
        {0, 0, 1, 0},
        {0, 0, 1, 1},
        {0, 0, 0, 1},
        {1, 0, 0, 1}};

// 步进电机初始化
void STEPMOTOR_Init(void)
{
    // 使能GPIOA时钟
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;

    // 配置为推挽输出模式(50MHz)mode-11 cnf-00
    GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1 | GPIO_CRL_CNF2 | GPIO_CRL_CNF3);
    GPIOA->CRL |= (GPIO_CRL_MODE0 | GPIO_CRL_MODE1 | GPIO_CRL_MODE2 | GPIO_CRL_MODE3);

    // 初始状态全部置低
    GPIOA->ODR &= ~(GPIO_ODR_ODR0 | GPIO_ODR_ODR1 | GPIO_ODR_ODR2 | GPIO_ODR_ODR3);
}

// 步进电机运行函数
// dir: 1=正转, 0=反转; angle: 转动角度
void STEPMOTOR_Run(uint8_t dir, float angle)
{
    // 28BYJ-48实际每圈需要4096步(360/5.625=64 *64)
    // 90度 = 4096 / 4 = 1024步
    uint16_t totalSteps = (uint16_t)(angle * 4096 / 360);

    uint8_t stepIndex = 0;

    for (uint16_t i = 0; i < totalSteps; i++)
    {
        // 清除当前输出
        GPIOA->ODR &= ~(GPIO_ODR_ODR0 | GPIO_ODR_ODR1 | GPIO_ODR_ODR2 | GPIO_ODR_ODR3);

        // 设置当前步的电平
        if (stepSequence[stepIndex][0])
            GPIOA->ODR |= GPIO_ODR_ODR0;
        if (stepSequence[stepIndex][1])
            GPIOA->ODR |= GPIO_ODR_ODR1;
        if (stepSequence[stepIndex][2])
            GPIOA->ODR |= GPIO_ODR_ODR2;
        if (stepSequence[stepIndex][3])
            GPIOA->ODR |= GPIO_ODR_ODR3;

        // 控制方向
        if (dir)
        {
            stepIndex = (stepIndex + 1) % 8; // 正转
        }
        else
        {
            stepIndex = (stepIndex + 7) % 8; // 反转(避免负数)
        }

        Delay_ms(2); // 控制转速,可根据需要调整
    }

    // 停止后全部置低
    GPIOA->ODR &= ~(GPIO_ODR_ODR0 | GPIO_ODR_ODR1 | GPIO_ODR_ODR2 | GPIO_ODR_ODR3);
}
8.3.2 按键控制部分
c 复制代码
// FileName:key.h

#include "includes.h"

uint8_t count = 0;

/**
 * @brief 按键初始化(PB7,外部中断,下降沿触发)
 * @param void
 * @return void
 */
void KEY_Init(void)
{
    // 1. 开启时钟(GPIOB和AFIO)
    RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // 使能GPIOB时钟
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 使能AFIO时钟

    // 2. 配置GPIO工作模式(上拉输入,因为按键另一端接GND)
    GPIOB->CRL &= ~GPIO_CRL_MODE7; // MODE7=00(输入模式)
    GPIOB->CRL |= GPIO_CRL_CNF7_1; // CNF7=10(上拉/下拉输入)
    GPIOB->CRL &= ~GPIO_CRL_CNF7_0;
    GPIOB->ODR |= GPIO_ODR_ODR7; // 上拉(默认高电平)

    // 3. 配置AFIO复用映射(PB7 -> EXTI7)
    AFIO->EXTICR[1] &= ~AFIO_EXTICR2_EXTI7;   // 清除原有映射
    AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI7_PB; // PB7映射到EXTI7

    // 4. 配置EXTI(下降沿触发,允许中断)
    EXTI->FTSR |= EXTI_FTSR_TR7;  // 允许下降沿触发(按键按下)
    EXTI->RTSR &= ~EXTI_RTSR_TR7; // 禁止上升沿触发
    EXTI->IMR |= EXTI_IMR_MR7;    // 允许EXTI7中断

    // 5. 配置NVIC(中断优先级和使能)
    NVIC_SetPriorityGrouping(3);       // 全部使用抢占优先级
    NVIC_SetPriority(EXTI9_5_IRQn, 2); // 设置优先级(值越小优先级越高)
    NVIC_EnableIRQ(EXTI9_5_IRQn);      // 使能EXTI9_5中断
}

/**
 * @brief EXTI9_5中断服务函数(处理PB7中断)
 */
void EXTI9_5_IRQHandler(void)
{
    // 检查是否是PB7触发的中断
    if (EXTI->PR & EXTI_PR_PR7)
    {
        // 清除中断标志位(必须手动清除)
        EXTI->PR |= EXTI_PR_PR7;

        // 软件消抖
        Delay_ms(10);

        // 确认按键按下(PB7接GND,按下时为低电平)
        if (!(GPIOB->IDR & GPIO_IDR_IDR7))
        {
            // 步进电机控制
            // 转动90度
            STEPMOTOR_Run(g_motorDir, 90);
            count++;
            if (count > 4)
            {
                // 切换方向
                g_motorDir = !g_motorDir;
                count = 0;
            }
        }
    }
}

8.4 完整代码获取

STM32F103C8T6 按键控制步进电机


笔者小白,能力有限,以上内容难免存在不足和纰漏,仅供参考,各位阅读时请带着批判性思维学习,遇到问题多查查。同时欢迎各位评论区批评指正。谢谢。

相关推荐
苦逼大学生被编程薄纱2 小时前
C++ 容器学习系列|vector 核心知识全解析,铺垫下一期模拟实现
开发语言·c++·学习
DKPT2 小时前
JVM栈溢出时如何dump栈信息?
java·jvm·笔记·学习·spring
DKPT2 小时前
JVM堆大小如何设置?
java·开发语言·jvm·笔记·学习
小喵要摸鱼2 小时前
【机器学习】监督学习 —— 逻辑回归
学习·机器学习·逻辑回归
hazy1k3 小时前
K230基础-RTC时钟介绍及使用
stm32·单片机·嵌入式硬件·k230
小柯博客3 小时前
从零开始WebRTC(一)
stm32·单片机·嵌入式硬件·青少年编程·嵌入式·webrtc
GilgameshJSS3 小时前
STM32H743-ARM例程11-PWM
c语言·arm开发·stm32·嵌入式硬件·学习
知识分享小能手9 小时前
React学习教程,从入门到精通,React 单元测试:语法知识点及使用方法详解(30)
前端·javascript·vue.js·学习·react.js·单元测试·前端框架
rzjslSe12 小时前
【JavaGuide学习笔记】理解并发(Concurrency)与并行(Parallelism)的区别
java·笔记·学习