部分内容摘自《51单片机轻松入门---基于STC15W4K系列》
李友全 编著
步进电机的特点
直流电机通电就可以旋转,但旋转位置无法准确控制,在很多对位置有精确要求的控制设备上,往往会使用步进电机。步进电机是一步一步前进的,步进电机可准确的停在我们要求的位置,不存在直流电机断电后的惯性过冲问题。
步进电机特点如下:
①步进电机旋转角度和输入脉冲数成正比,步进电机说明书通常会说明其步进角,也就是一个脉冲所产生的旋转角度)。比如常见的小体积永磁式电机的步进角是7.5°,则送给它48个脉冲使步进电机正好转动一圈。
②步进电机转角误差很小,没有累积误差,因此控制步进电机正反转还是会回到原来位置,不会因为误差累积而使初始位置越来越远。
③具有自保持特性,任何一相线圈加上电源后,电机本身具有自保持力矩,不送脉冲情况下会停止在一定位置,不会改变。
④步进电机空载最高启动频率一般能达到450Hz,使用频率不能超过允许最高频率,否则电机只能振动,无法运转。
⑤常见步进电机供电电压是5V、12V、24V,供电电压允许误差±10%,电机外壳上般都会对供电电压规格作相应标识。
步进电机结构示意图
以常见的28BYJ-48型小功率步进电机为例:
图中所示的步进电机内部有四组线圈,分别为【A相】,【A非相(也称C相)】,【B相】,【B非相(也称D相)】。
电机内部还包括定子和转子,有的电机内部的两条VCC线是连在一起的,所以有的步进电机引出线是5条,有的是6条。
步进电机的3种励磁方式
将电流导入电机的线圈中,称为励磁。
依次改变电流所流过的线圈,就可以让步进电机转动。如果顺序相反的话,电机就会反方向转动。
比如上图所示的电机有A,A/,B,B/共4组线圈,最简单的励磁方式就是依次将电流按A,B,A/,B/的顺序导入4组线圈,不同的导入方式会产生不同的结果。
常用的励磁方式
(1)1相励磁(也称为单4拍)
这种励磁方式是将电流一次只导入一组线圈中,每次可移动一个步进角,这种励磁方式产生的力矩小,噪音振动最大,励磁顺序如表15-1所示,其中H表示励磁,L表示未励磁,图15-2是对应波形图。
(2)2相励磁(也称为双4拍)
这种励磁方式是将电流一次导入两组线圈中,每次可移动一个步进角。由于同时有2个线圈被励磁,因此产生的力矩较大,噪音振动比1相励磁小。
励磁顺序如表15-2所示,图15-3是对应波形图,按照表15-2的方式依1、2、3、4的顺序分别将4组线圈中的2组线圈励磁,步进电机会转动4个步进角,如果反方向励磁(也就是以4、3、2、1的顺序),步进电机就按反方向转动4个步进角。
(3)1-2相励磁(也称为8拍)
这种励磁方式是上述两种励磁方式的综合,将A、B两相采用交互励磁的方式进行。电流第一次导入一组线圈中,在第二次导入两组线圈,每次可移动半个步进角,是噪音振动最小的一种励磁方式。
励磁顺序如表15-3所示,图15-4是对应波形图。
按照表15-3的方式依1、2、3、4、5、6、7、8的顺序分别将4组线圈励磁,步进电机会转动4个步进角(虽然励磁8次,但因每次都只前进半个步进角,所以总共转动4个步进角)。
例如,步进电机的步进角是7.5度,采用这种方式励磁,每次转动半个步进角即3.8度,8拍一共转动4个步进角。
步进电机常用驱动电路:
由于51的端口驱动能力非常有限,这里使用ULN2003作为驱动芯片,51只要使用很小的端口驱动电流,就可以连接ULN2003工作。ULN2003每个管腿单独的输出电流可达500mA,不仅可以用来驱动步进电机,还可以驱动LED,蜂鸣器等。
这里,COM端接电源。如果步进电机使用的是12V电源,则9腿应当接12V,而不是单片机的5V。
步进电机驱动程序
采用1-2相8拍励磁方式,也就是第三种励磁方式。
励磁顺序表:H代表高电平,L代表低电平
管腿 | 顺序 项 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
P3.7 | A | H | H | L | L | L | L | L | H |
P3.6 | B | L | H | H | H | L | L | L | L |
P3.5 | A/(C) | L | L | L | H | H | H | L | L |
P3.4 | B/(D) | L | L | L | L | L | H | H | H |
端口取值 | 0x8X | 0xCX | 0x4X | 0x6X | 0x2X | 0x3X | 0x1X | 0x9X |
#include "STC15W4K.h"
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//根据励磁顺序表编制端口驱动码,使用高四位
uchar code BiaoGe[8]={0x8F,0xCF,0x4F,0x6F,0x2F,0x3F,0x1F,0x9F};
void Delay2ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
void Delay2s() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 85;
j = 12;
k = 155;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void shun200() // 顺转200步
{
uint i;
unsigned char n;
unsigned char P3temp; //用于读取端口值
n=0;
for(i=0;i<200;i++) // 200步,i/2为实际步数
{
P3=0xFF; //向端口写入1,准备读取端口值
P3temp=P3; //读取P3口的值
P3temp=P3temp&0x0F; //高四位清零
P3temp=P3temp|BiaoGe[n]; //高四位赋值,低四位不变
P3=P3temp; //写入端口,不影响P3口低4位
Delay2ms();
n=n+1;
if (n>7)
{
n=0;
}
}
P3&=0x0f; // 保证电机绕组断电,不影响P3口低4位
}
void fan200() // 反转200步
{
unsigned int i;
unsigned char n;
unsigned char P3temp;
n=8;
for(i=0;i<200;i++) // 200步,i/2为实际步数
{
n=n-1;
P3=0xFF; //向端口写入1,准备读取端口值
P3temp=P3; //读取P3口的值
P3temp=P3temp&0x0F; //高四位清零
P3temp=P3temp|BiaoGe[n]; //高四位赋值,低四位不变
P3=P3temp; //写入端口,不影响P3口低4位
Delay2ms();
if (n==0)
{
n=8;
}
}
P3&=0x0f; // 保证电机绕组断电,不影响P3口低4位
}
void port_mode()
{
P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00;
P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
}
void main()
{
port_mode(); //端口初始化
while(1)
{
shun200();
Delay2s();
fan200();
Delay2s();
}
}