一、前言
本项目基于STC89C52单片机,通过控制28BYJ-48步进电机实现按角度正反转旋转的功能。28BYJ-48步进电机是一种常用的电机,精准定位和高扭矩输出,适用于许多小型的自动化系统和机械装置。
在这个项目中,使用STC89C52单片机作为控制器,这是一款强大而常用的8位单片机芯片,具有丰富的外设和强大的计算能力。通过编写适当的程序,可以通过单片机的IO口来控制步进电机的运动。
28BYJ-48步进电机是一种低成本、低功耗的步进电机,拥有精确的定位能力和较高的转矩输出。将使用单片机与步进电机之间的接口信号来驱动电机旋转,并通过控制电流脉冲的频率和顺序来控制电机前进或后退以及旋转的角度。
本项目的目标是实现根据用户输入的角度值,控制28BYJ-48步进电机按指定角度进行正反转旋转。通过灵活调整步进电机的控制信号,可以实现不同角度范围内的精确旋转。
在接下来的内容将介绍所需的硬件和软件资源,包括STC89C52单片机的基本特性、28BYJ-48步进电机的工作原理,以及编写控制程序的关键步骤。
二、设计流程
【1】硬件准备:
- 51单片机开发板:选择STC89C52单片机开发板。
- 28BYJ-48步进电机:一个28BYJ-48步进电机+ULN2003驱动板。
- 驱动电路:使用ULN2003芯片来驱动步进电机。
- 连接线和电源:准备连接线和电源供电。
【2】连接电路:
- 将51单片机与驱动电路和步进电机连接起来。
【3】编写程序:
- 使用keil集成开发环境(IDE)编写51单片机的控制程序。
- 初始化引脚和端口设置,配置控制步进电机所需的引脚。
- 编写函数来控制步进电机的正反转旋转。
- 编写函数来控制步进电机按照指定的角度进行旋转。
【4】控制步进电机旋转:
- 在主程序中,调用适当的函数来控制步进电机的旋转。
- 使用按键输入设备来触发步进电机的旋转。
- 控制旋转的角度、速度和方向。
【5】调试和测试:
- 通过编译程序,并将生成的可执行文件下载到51单片机开发板中。
三、代码实现
3.1 电机正反转控制
下面是通过STC89C52单片机控制28BYJ-48步进电机实现正转和反转的实现代码:
#include <reg52.h>
#include <intrins.h>
#define motorPort P1 // 步进电机的控制引脚连接到P1口
#define clockwise 0 // 顺时针方向
#define counterclockwise 1 // 逆时针方向
// 函数声明
void delay(unsigned int time);
void motorRotate(unsigned char direction, unsigned int steps);
void main()
{
while (1)
{
// 正转,执行一定的步数 (这里为512步,可根据需要修改)
motorRotate(clockwise, 512);
delay(1000); // 延时1秒
// 反转,执行一定的步数
motorRotate(counterclockwise, 256);
delay(1000); // 延时1秒
}
}
// 延时函数
void delay(unsigned int time)
{
unsigned int i, j;
for (i = time; i > 0; i--)
{
for (j = 110; j > 0; j--); // 指令周期延时
}
}
// 控制步进电机旋转
void motorRotate(unsigned char direction, unsigned int steps)
{
unsigned int i;
unsigned char motorSequence[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09}; // 步进电机的控制序列
for (i = 0; i < steps; i++)
{
if (direction == clockwise)
{
motorPort = motorSequence[i % 8];
}
else if (direction == counterclockwise)
{
motorPort = motorSequence[7 - (i % 8)];
}
delay(2); // 每步之间的延时,可根据需要调整
}
motorPort = 0x00; // 停止电机
}
代码里使用 STC89C52 单片机的 P1 口连接到28BYJ-48步进电机的控制引脚。在 main
函数中,通过循环实现了正转和反转的功能。motorRotate
函数用于控制步进电机的旋转方向和步数,其中 clockwise
和 counterclockwise
分别代表顺时针和逆时针方向。
3.2 角度旋转
下面代码使用STC89C52单片机控制28BYJ-48步进电机按指定的角度进行正转和反转,封装子函数进行调用。
#include <reg52.h>
// 定义28BYJ-48步进电机的相序
unsigned char stepSequence[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09};
// 定义步进电机当前位置和角度
unsigned char currentPosition = 0;
unsigned int currentAngle = 0;
// 延时函数
void delay(unsigned int time) {
unsigned int i, j;
for (i = 0; i < time; i++) {
for (j = 0; j < 120; j++);
}
}
// 步进电机正转函数
void stepForward(unsigned int angle) {
unsigned int steps = angle / 5; // 每步转动角度为5度
unsigned int i;
for (i = 0; i < steps; i++) {
currentPosition++;
if (currentPosition >= 8) {
currentPosition = 0;
}
P1 = stepSequence[currentPosition];
delay(10); // 控制步进电机转速,可调整延时时间
}
currentAngle += angle;
}
// 步进电机反转函数
void stepBackward(unsigned int angle) {
unsigned int steps = angle / 5; // 每步转动角度为5度
unsigned int i;
for (i = 0; i < steps; i++) {
if (currentPosition == 0) {
currentPosition = 8;
}
currentPosition--;
P1 = stepSequence[currentPosition];
delay(10); // 控制步进电机转速,可调整延时时间
}
currentAngle -= angle;
}
// 主函数
void main() {
while (1) {
// 正转180度
stepForward(180);
delay(1000); // 停顿1秒钟
// 反转90度
stepBackward(90);
delay(1000); // 停顿1秒钟
}
}
代码使用STC89C52单片机的P1口作为输出口,通过控制P1口输出的电平来控制步进电机的旋转。步进电机的相序存储在stepSequence
数组中,每个元素对应一个相位。stepForward
函数用于实现步进电机的正转,stepBackward
函数用于实现步进电机的反转。delay
函数用于控制步进电机的转速,可以根据需要调整延时时间。
在主函数中,演示了步进电机的正转180度和反转90度的操作。
3.3 按键控制电机
有2个按键,接在P2口3上面的,按下是低电平。下面代码加入2个按键,实现了2个按键的功能。
#include <reg52.h>
#define motorPort P1 // 步进电机的控制引脚连接到P1口
#define clockwise 0 // 顺时针方向
#define counterclockwise 1 // 逆时针方向
sbit startBtn = P2^0; // 启动按钮连接到P2.0口
sbit stopBtn = P2^1; // 停止按钮连接到P2.1口
sbit cwBtn = P2^2; // 顺时针按钮连接到P2.2口
sbit ccwBtn = P2^3; // 逆时针按钮连接到P2.3口
unsigned char motorSequence[8] = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09}; // 步进电机的控制序列
bit motorRunning = 0; // 步进电机是否正在运行
unsigned int targetAngle = 0; // 目标转动角度,初始为0
bit clockwiseDirection = 1; // 电机默认启动方向为顺时针
// 函数声明
void delay(unsigned int time);
void motorRotate(unsigned char direction, unsigned int steps);
void main()
{
while (1)
{
if (startBtn == 0) // 如果按下了启动按钮
{
while (startBtn == 0); // 等待按钮释放
if (!motorRunning)
{
motorRunning = 1;
motorRotate(clockwiseDirection, targetAngle); // 启动电机
}
}
if (stopBtn == 0) // 如果按下了停止按钮
{
while (stopBtn == 0); // 等待按钮释放
if (motorRunning)
{
motorRunning = 0;
motorPort = 0x00; // 停止电机
}
}
if (cwBtn == 0) // 如果按下了顺时针按钮
{
while (cwBtn == 0); // 等待按钮释放
clockwiseDirection = 1; // 设置电机启动方向为顺时针
}
if (ccwBtn == 0) // 如果按下了逆时针按钮
{
while (ccwBtn == 0); // 等待按钮释放
clockwiseDirection = 0; // 设置电机启动方向为逆时针
}
}
}
// 延时函数
void delay(unsigned int time)
{
unsigned int i, j;
for (i = time; i > 0; i--)
{
for (j = 110; j > 0; j--); // 指令周期延时
}
}
// 控制步进电机旋转
void motorRotate(unsigned char direction, unsigned int steps)
{
unsigned int i;
for (i = 0; i < steps; i++)
{
if (!motorRunning)
break;
if (direction == clockwise)
{
motorPort = motorSequence[i % 8];
}
else if (direction == counterclockwise)
{
motorPort = motorSequence[7 - (i % 8)];
}
delay(2); // 每步之间的延时,可根据需要调整
}
motorPort = 0x00; // 停止电机
}
在以上代码中,增加了 cwBtn
和 ccwBtn
两个按键引脚,并定义为 P2^2
和 P2^3
。按下顺时针按钮时,将 clockwiseDirection
设置为 1,表示启动方向为顺时针;按下逆时针按钮时,将 clockwiseDirection
设置为 0,表示启动方向为逆时针。