外设模块学习(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 V2SWDIO, SWCLK, GND, 3.3V严格对应引脚连接,为单片机提供调试和烧录接口

⚠️ 特别注意:

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

8.3 核心代码

8.3.1 步进电机控制部分
#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 按键控制部分
// 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 按键控制步进电机


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

posted @ 2025-10-22 21:21  yjbjingcha  阅读(6)  评论(0)    收藏  举报