步进电机内部实际上产生了一个可以旋转的磁场,当旋转磁场依次切换时,转子就会随之转动相应的角度。当磁场旋转过快或者转子上所带负载的转动惯量太大时,转子无法跟上步伐,就会造成失步。
直奔主题,想要控制步进电机转动,其实就是控制磁场的方向。通过改变磁场的方向来改变施加与转子的力矩。这里以五线四相制步进电机进行说明。原理图如下:
驱动电路:ULN2003达林顿结构芯片,具有很强的驱动能力,现有的驱动板可以用来驱动步进电机,我们只需要选择单片机的四个输出端口用杜邦线分别连接驱动板的IN1、IN2、IN3、IN4,再用外置电源连接驱动板的5-12V+接口,并把电源和单片机的地(GND)与驱动板的(–)共线即可。
三种励磁方式的相续表:
uchar code type_dan[]={0x01,0x02,0x04,0x08};//单相励磁,力矩大
uchar code type_shuang[]={0x09,0x03,0x06,0x0c};//双向励磁
uchar code type_dan_shuang[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//一相励磁和二相励磁交替
实现功能是,利用四个独立按键控制步进电机转动,S1正转,S2反转,S3停转,S4调节速度10级可调,同时利用数码管显示当前速度等级。
源代码:
#include <REGX52.H>
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code type_dan_shuang_1[]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};//正转相序表
uchar code type_dan_shuang_2[]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};//反转相序表
uchar code type1[]={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff };//段选
uchar code type2[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位选
uchar num1,num2,num3,num4,num5,num6,num7,num8;
bit f_2ms;
uchar t_2ms,t_200us;
uchar GN,HN;
uchar speed=4;
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
void Delay(uint num)
{
while(num--);
}
//数码管显示函数
void smg_display(char n1,char n2,char n3,char n4,char n5,char n6,char n7,char n8)
{
char i;
P0=0xff;
P2=(P2&0x1f)|0xc0;
P0=type2[i];
P2=(P2&0x1f);
switch(i)
{
case 0:P2=(P2&0x1f)|0xe0; P0=type1[n1]; P2=(P2&0x1f);break;
case 1:P2=(P2&0x1f)|0xe0; P0=type1[n2]; P2=(P2&0x1f);break;
case 2:P2=(P2&0x1f)|0xe0; P0=type1[n3]; P2=(P2&0x1f);break;
case 3:P2=(P2&0x1f)|0xe0; P0=type1[n4]; P2=(P2&0x1f);break;
case 4:P2=(P2&0x1f)|0xe0; P0=type1[n5]; P2=(P2&0x1f);break;
case 5:P2=(P2&0x1f)|0xe0; P0=type1[n6]; P2=(P2&0x1f);break;
case 6:P2=(P2&0x1f)|0xe0; P0=type1[n7]; P2=(P2&0x1f);break;
case 7:P2=(P2&0x1f)|0xe0; P0=type1[n8]; P2=(P2&0x1f);break;
}
if(++i==1)
i=0;
}
独立按键
uchar key_scan()
{
uchar temp;
temp=(~P3)&0x0f;
if(temp==0) return 0;
Delay10ms();
temp=(~P3)&0x0f;
if(temp==0) return 0;
return temp;
}
void key_change()
{
uchar D;
D=key_scan();
switch(D)
{
case 8:GN=4;break;
case 4:GN=5;break;
case 2:GN=6;break;
case 1:HN=7;break;
case 0:HN=0;break;
}
}
//配置定时器1
void time1_int1()
{
EA=1;
ET1=1;
TR1=1;
TMOD=(TMOD&0x0f)|0x10;
TH1=(65536-200)/256;
TL1=(65536-200)%256;
}
//初始化所有外设
void initial_all()
{
P2=(P2&0x1f)|0xa0;
P0=0x00;
P2=(P2&0x1f);
P2=(P2&0x1f)|0x80;
P0=0xff;
P2=(P2&0x1f);
P2=(P2&0x1f)|0xc0;
P0=0xff;
P2=(P2&0x1f);
P2=(P2&0x1f)|0xe0;
P0=0xff;
P2=(P2&0x1f);
}
void main()
{
char i;
initial_all(); //初始化外设
time1_int1(); //初始化定时器
num1=num2=num3=num4=num5=num6=num7=num8=10;//关闭所有数码管显示
while(1)
{
if(f_2ms==1)
{
f_2ms=0;
key_change();
num1=speed-4;
if(GN==4) //步进电机正传
{
EA=0;
P2=(P2&0x1f)|0xa0; //打开锁存器
P0=(type_dan_shuang_1[i] & 0x0f)|type_dan_shuang_1[i]; //送入旋转相续数
if(++t_200us == speed) //速度调节
{
t_200us=0;
if(++i==8)
i=0;
}
P2=(P2&0x1f); //关闭锁存器
EA=1;
}
if(GN==5) //步进电机反转
{
EA=0;
P2=(P2&0x1f)|0xa0;
P0=(type_dan_shuang_2[i] & 0x0f)|type_dan_shuang_2[i];
if(++t_200us == speed)
{
t_200us=0;
if(++i==8)
i=0;
}
P2=(P2&0x1f);
EA=1;
}
if(GN==6) //步进电机停止
{
EA=0;
P2=(P2&0x1f)|0xa0;
P0=0000;
P2=(P2&0x1f);
EA=1;
}
if(HN==7) //速度调节
{
if(++speed==14)
speed=4;
while(key_scan());
}
}//f_2ms
}
}
void cl_time1_int1() interrupt 3 //定时器中断1处理函数
{
TH1=(65536-200)/256;
TL1=(65536-200)%256;
smg_display(num1,num2,num3,num4,num5,num6,num7,num8);
f_2ms=1;
}
给个小爱心吧,谢谢!