目录
一、引言
28BYJ-48步进电机因其价格低廉、控制简单等特点,在各类小型自动化项目中广泛应用。本文将详细介绍如何使用STM32F103C8T6单片机通过ULN2003驱动芯片控制这种步进电机,实现正反转、调速和精确位置控制。
二、28BYJ-48步进电机简介
2.1 基本特性
电机类型:
- 永磁式步进电机(Unipolar)
- 内置1:64减速齿轮箱
电气参数:
额定电压:5V DC
相电流:约100-120mA/相
线圈电阻:50Ω/相
驱动方式:单极性驱动(ULN2003驱动板兼容)
机械参数:
步距角:5.625°(原始步距)
减速后步距角:5.625°/64 ≈ 0.0879°
输出轴转速范围:0-15 RPM(建议工作范围)
电机图片:
2.2 内部结构
电磁部分:
4相8极绕组结构
每组线圈中心抽头接正极
齿轮箱结构:
四级行星齿轮减速
总减速比1:64
输出轴扭矩:≥34.3mN·m(5V时)
2.3 工作模式
模式 | 步数/转 | 步距角 | 特点 |
---|---|---|---|
全步(单相) | 64步 | 5.625° | 低分辨率,振动较大 |
全步(双相) | 64步 | 5.625° | 扭矩大,功耗高 |
半步 | 128步 | 2.8125° | 分辨率提高,运行更平稳 |
8步微步 | 512步 | 0.703° | 最高分辨率,需专用驱动 |
2.4 驱动原理
励磁顺序(以全步双相为例):
// 4相8拍驱动序列
const uint8_t seq[8] = {
0b1000, // A
0b1100, // A+B
0b0100, // B
0b0110, // B+C
0b0010, // C
0b0011, // C+D
0b0001, // D
0b1001 // D+A
};
转速计算:
例:每秒683脉冲 → 10 RPM (转每分钟)
2.5 性能特点
优点:
价格低廉
驱动电路简单(ULN2003即可)
低速大扭矩输出
保持转矩大(断电后能保持位置)
局限性:
最高转速较低(通常<15RPM)
齿轮箱存在回程差(约3°)
长时间工作可能发热
2.6 驱动方案
驱动方案对比:
驱动芯片 | 最大电流 | 特点 |
---|---|---|
ULN2003 | 500mA | 经济,适合低速应用 |
DRV8825 | 2.5A | 支持微步,精度高 |
A4988 | 2A | 带过热保护 |
2.7 使用注意事项
电气保护:
反接保护二极管必接
避免长时间堵转(>2秒)
机械安装:
输出轴避免径向受力
齿轮箱需定期润滑(硅脂)
该电机特别适合学生项目和原型开发,其优异的性价比使其成为入门级运动控制的首选。实际使用时建议配合光电编码器实现闭环控制以提升精度。
三、ULN2003驱动板简介
3.1 基本概述
ULN2003驱动板是专为28BYJ-48等小型步进电机设计的低成本驱动模块,核心采用ULN2003达林顿阵列芯片,具有以下特性:
关键参数:
工作电压:5-12V(与电机电压匹配)
单路最大电流:500mA
总功耗:1.5W(需配合散热片)
输入兼容性:3.3V/5V逻辑电平
板载资源:
4路LED指示灯(显示相位状态)
反接保护二极管
电机接口防插反设计
5.08mm间距接线端子
UNL2003驱动板示意图:
ULN2003原理图:
3.2 电路结构
核心芯片:
ULN2003包含7路达林顿管(实际使用4路)。
典型应用电路:
3.3 驱动原理
相位控制真值表:
步序 | IN1 | IN2 | IN3 | IN4 | 励磁相 |
---|---|---|---|---|---|
1 | 1 | 0 | 0 | 0 | A |
2 | 1 | 1 | 0 | 0 | AB |
3 | 0 | 1 | 0 | 0 | B |
... | ... | ... | ... | ... | ... |
电流路径(以A相为例):
5V -> 线圈A -> ULN2003_OUT1 -> 达林顿管 -> GND
3.4 接口定义
引脚标号 | 功能说明 | 连接目标 |
---|---|---|
IN1-IN4 | 相位控制输入 | MCU GPIO |
VCC | 逻辑电源(可选) | MCU 5V |
GND | 公共地 | 电源地 |
A-D | 电机相线输出 | 28BYJ-48对应相线 |
3.5 使用注意事项
电源配置:
当电机电压>5V时,建议:
- 逻辑电源(VCC)接MCU
- 5V电机电源单独供电
保护措施:
电机断电时产生的反电动势可能达30V,必须保留板载续流二极管
长时间工作需监测芯片温度(>70℃应停止使用)
典型问题处理:
电机抖动不转:检查相位顺序是否正确
驱动芯片发烫:
(1)降低PWM频率(建议<2kHz)
(2)增加散热片
四、硬件准备
所需材料:
STM32F103C8T6最小系统板
28BYJ-48步进电机(带ULN2003驱动板)
杜邦线若干
USB转TTL模块(用于程序下载)
电源(5V/2A)
五、硬件连接
5.1 接线示意图
STM32F103C8T6 | ULN2003驱动板 |
PB6 | IN1 |
PB7 | IN2 |
PB8 | IN3 |
PB9 | IN4 |
GND | GND |
5V | VCC |
5.2 电源注意事项
建议为电机驱动单独供电,避免单片机电源受干扰。
六、软件设计
6.1 开发环境配置
安装Keil MDK-ARM
安装STM32标准外设库
配置工程包含必要头文件
6.2 关键代码实现
6.2.1 引脚定义与初始化
// 引脚定义
#define IN1_PIN GPIO_Pin_6
#define IN2_PIN GPIO_Pin_7
#define IN3_PIN GPIO_Pin_8
#define IN4_PIN GPIO_Pin_9
#define MOTOR_PORT GPIOB
// GPIO初始化
void GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(MOTOR_PORT, &GPIO_InitStruct);
}
6.2.2 步进序列定义
// 8步驱动序列(更高精度)
const uint8_t stepSequence[8] = {
0b1000, // A
0b1100, // AB
0b0100, // B
0b0110, // BC
0b0010, // C
0b0011, // CD
0b0001, // D
0b1001 // DA
};
6.2.3 定时器配置(TIM4)
void TIM4_Init(void) {
TIM_TimeBaseInitTypeDef TIM_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// 1MHz计数频率(1μs分辨率)
TIM_InitStruct.TIM_Period = 1000; // 初始ARR值
TIM_InitStruct.TIM_Prescaler = SystemCoreClock/1000000 - 1;
TIM_InitStruct.TIM_ClockDivision = 0;
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_InitStruct);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM4, ENABLE);
}
6.2.4 运动控制核心逻辑
// 全局变量
volatile int32_t stepPosition = 0;
volatile int32_t targetSteps = 0;
volatile uint32_t stepDelay = 2000; // 初始延迟2000μs
volatile int8_t direction = 1;
// 设置电机相位
void SetMotorPhase(uint8_t phase) {
GPIO_WriteBit(MOTOR_PORT, IN1_PIN, (phase & 0x08) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(MOTOR_PORT, IN2_PIN, (phase & 0x04) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(MOTOR_PORT, IN3_PIN, (phase & 0x02) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(MOTOR_PORT, IN4_PIN, (phase & 0x01) ? Bit_SET : Bit_RESET);
}
// 定时器中断服务函数
void TIM4_IRQHandler(void) {
static uint8_t currentPhase = 0;
if (TIM_GetITStatus(TIM4, TIM_IT_Update)) {
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
if ((direction > 0 && stepPosition < targetSteps) ||
(direction < 0 && stepPosition > targetSteps)) {
currentPhase = (currentPhase + direction + 8) % 8;
SetMotorPhase(stepSequence[currentPhase]);
stepPosition += direction;
// 更新定时器
TIM_SetAutoreload(TIM4, stepDelay);
TIM_SetCounter(TIM4, 0);
} else {
SetMotorPhase(0x00); // 停止电机
}
}
}
七、功能实现
7.1 基本运动控制
// 相对移动
void MoveSteps(int32_t steps) {
targetSteps = stepPosition + steps;
direction = (steps > 0) ? 1 : -1;
}
// 绝对移动
void MoveToPosition(int32_t position) {
targetSteps = position;
direction = (position > stepPosition) ? 1 : -1;
}
7.2 速度控制
// 设置转速(RPM)
void SetSpeed(float rpm) {
// RPM转步进延迟(μs)
uint32_t delay = (60 * 1000000) / (4096 * rpm);
// 限制在合理范围
if (delay < 800) delay = 800; // 最大约15RPM
if (delay > 10000) delay = 10000; // 最小约1.46RPM
stepDelay = delay;
}
7.3 加减速控制
// 梯形加减速控制
void UpdateSpeed(void) {
static uint32_t acceleration = 100; // 加速度步/秒²
int32_t remainingSteps = abs(targetSteps - stepPosition);
// 加速阶段(前1/3路程)
if (remainingSteps > (2 * totalSteps / 3)) {
if (stepDelay > minDelay + acceleration) {
stepDelay -= acceleration;
}
}
// 减速阶段(后1/3路程)
else if (remainingSteps < (totalSteps / 3)) {
if (stepDelay < maxDelay - acceleration) {
stepDelay += acceleration;
}
}
}
八、应用示例
8.1 简单测试程序
实现正转一圈然后反转一圈循环。
int main(void) {
SystemInit();
GPIO_Init();
TIM4_Init();
// 设置转速为10RPM
SetSpeed(10.0);
while(1) {
// 正转1圈
MoveSteps(4096);
while(stepPosition < targetSteps);
Delay_ms(1000);
// 反转1圈
MoveSteps(-4096);
while(stepPosition > targetSteps);
Delay_ms(1000);
}
}
8.2 带加减速的位置控制
可设置目标位置以及速度。
void ControlledMove(int32_t target, float speed) {
SetSpeed(speed);
MoveToPosition(target);
while(stepPosition != target) {
UpdateSpeed(); // 实时更新速度
Delay_ms(1);
}
}
九、常见问题解决
电机抖动但不转动:
- 检查电源是否充足(≥5V/1A)
验证步进序列是否正确
确保接线牢固
转速达不到预期:
- 适当减小minDelay
检查ULN2003是否过热
确认电机负载是否过大
位置控制不准确:
- 增加减速阶段时间
考虑使用闭环控制(如加装编码器)
优化建议:
微步驱动:通过PWM实现更精细的256微步控制
闭环控制:增加编码器反馈实现真正的位置闭环
电流控制:动态调整相电流以降低发热
十、总结
本文详细介绍了使用STM32F103C8T6控制28BYJ-48步进电机的完整方案,包括硬件连接、软件实现和运动控制算法。通过合理设置参数,可以实现精确的位置控制和速度调节,满足大多数小型自动化项目的需求。