STM32之28BYJ-48步进电机驱动
目录
一、引言
二、28BYJ-48步进电机简介
2.1 基本特性
2.2 内部结构
2.3 工作模式
2.4 驱动原理
2.5 性能特点
2.6 驱动方案
2.7 使用注意事项
三、ULN2003驱动板简介
3.1 基本概述
3.2 电路结构
3.3 驱动原理
3.4 接口定义
3.5 使用注意事项
四、硬件准备
五、硬件连接
5.1 接线示意图
5.2 电源注意事项
六、软件设计
6.1 开发环境配置
6.2 关键代码实现
6.2.1 引脚定义与初始化
6.2.2 步进序列定义
6.2.3 定时器配置(TIM4)
6.2.4 运动控制核心逻辑
七、功能实现
7.1 基本运动控制
7.2 速度控制
7.3 加减速控制
八、应用示例
8.1 简单测试程序
8.2 带加减速的位置控制
九、常见问题解决
十、总结
一、引言
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, // A0b1100, // A+B0b0100, // B0b0110, // B+C0b0010, // C0b0011, // C+D0b0001, // D0b1001 // 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, // A0b1100, // AB0b0100, // B0b0110, // BC0b0010, // C0b0011, // CD0b0001, // D0b1001 // 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; // 最大约15RPMif (delay > 10000) delay = 10000; // 最小约1.46RPMstepDelay = 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();// 设置转速为10RPMSetSpeed(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步进电机的完整方案,包括硬件连接、软件实现和运动控制算法。通过合理设置参数,可以实现精确的位置控制和速度调节,满足大多数小型自动化项目的需求。