51单片机控制步进电机程序。在线等高分,请会写的高手大侠写出来。

51单片机控制步进电机程序。在线等高分,请会写的高手大侠写出来。,第1张

我上周刚做的这个实验 成功拉,给你参考一下吧 这可是我当时辛辛苦苦编出来的啊,不过我用的是L298驱动的 和ULN2003一样,你把它换成2003就行拉

#include <AT89X51H>

unsigned char code table[]=;

unsigned char temp,temp_old;

unsigned char key;

unsigned char i,j,k,m,s;

void delay(int i)

{

for(m=i;m>0;m--)

for(j=250;j>0;j--)

for(k=10;k>0;k--);

}

void saomiao()

{

P3=0xff;

P3_4=0;

temp=P3;

temp=temp&0x0f;

if(temp!=0x0f)

{

for(i=50;i>0;i--)

for(j=200;j>0;j--);

temp=P3;

temp=temp&0x0f;

if(temp!=0x0f)

{

temp=P3;

temp=temp&0x0f;

switch(temp)

{

case 0x0e:

key=1;

break;

case 0x0d:

key=2;

break;

case 0x0b:

key=3;

break;

case 0x07:

key=4;

break;

}

temp=P3;

temp=temp&0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp&0x0f;

}

}

}

P3=0xff;

P3_5=0;

temp=P3;

temp=temp&0x0f;

if(temp!=0x0f)

{

for(i=50;i>0;i--)

for(j=200;j>0;j--);

temp=P3;

temp=temp&0x0f;

if(temp!=0x0f)

{

temp=P3;

temp=temp&0x0f;

switch(temp)

{

case 0x0d:

key=5;

break;

case 0x0b:

key=6;

break;

case 0x07:

key=7;

break;

}

temp=P3;

temp=temp&0x0f;

while(temp!=0x0f)

{

temp=P3;

temp=temp&0x0f;

}

}

}

}

void main(void)

{

while(1)

{

saomiao();

if(key==1)

{ P1=0;

P2=0;

saomiao();

}

if(key==2)

{

temp_old=key;

for(s=0;s<8;s++)

{ P2=table[s];

P1_4=0;

delay(13);

saomiao();

if(key!=temp_old)

{

P1_4=1;

break;

}

}

}

if(key==3)

{

temp_old=key;

for(s=0;s<8;s++)

{ P2=table[s];

P1_5=0;

delay(5);

saomiao();

if(key!=temp_old)

{

P1_5=1;

break;

}

}

}

if(key==4)

{

temp_old=key;

for(s=0;s<8;s++)

{ P2=table[s];

P1_6=0;

delay(20);

saomiao();

if(key!=temp_old)

{

P1_6=1;

break;

}

}

}

if(key==5)

{

temp_old=key;

for(s=9;s<17;s++)

{ P2=table[s];

P1_7=0;

delay(13);

saomiao();

if(key!=temp_old)

{

P1_7=1;

break;

}

}

}

if(key==6)

{

temp_old=key;

for(s=9;s<17;s++)

{ P2=table[s];

P1_5=0;

delay(5);

saomiao();

if(key!=temp_old)

{

P1_5=1;

break;

}

}

}

if(key==7)

{

temp_old=key;

for(s=9;s<17;s++)

{ P2=table[s];

P1_6=0;

delay(20);

saomiao();

if(key!=temp_old)

{

P1_6=1;

break;

}

}

}

}

}

#include<reg52h>

#include<intrinsh>

#define mode 0x81 // 方式0,A口、B口输出,C口高4位输出,低4位输入

# include "stdioh"

# include "stringh"

# include "mathh"

xdata unsigned char PA _at_ 0x7f00;

xdata unsigned char PB _at_ 0x7f01;

xdata unsigned char PC _at_ 0x7f02;

xdata unsigned char caas _at_ 0x7f03; //控制字

sbit P32=P3^2;

sbit P33=P3^3;

sbit P35=P3^5;

#define uchar unsigned char

#define uint unsigned int

unsigned char h,Pos ;

unsigned int R,NX,NY;

unsigned char key;

code unsigned char KeyTable[] = { // 键码定义

0x0f, 0x0b, 0x07, 0x03,

0x0e, 0, 0x06, 0x02,

0x0d, 0x09, 0x05, 0x01,

0x0c, 0x08, 0x04, 0x00

};

code unsigned char LEDMAP[] = { // 八段管显示码

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,

0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71

};

unsigned char Code_ ; // 字符代码寄存器

#define PD1 61 // 122/2 分成左右两半屏(122x32)

unsigned char Column;

unsigned char Page_ ; // 页地址寄存器 D1,DO:页地址

unsigned char Code_ ; // 字符代码寄存器

unsigned char Command; // 指令寄存器

unsigned char LCDData; // 数据寄存器

xdata unsigned char CWADD1 _at_ 0x1cff; // 写指令代码地址(E1)

xdata unsigned char DWADD1 _at_ 0x1eff; // 写显示数据地址(E1)

xdata unsigned char CRADD1 _at_ 0x1dff; // 读状态字地址(E1)

xdata unsigned char DRADD1 _at_ 0x1fff; // 读显示数据地址(E1)

xdata unsigned char CWADD2 _at_ 0x3cff; // 写指令代码地址(E2)

xdata unsigned char DWADD2 _at_ 0x3eff; // 写显示数进地址(E2)

xdata unsigned char CRADD2 _at_ 0x3dff; // 读状态字地址(E2)

xdata unsigned char DRADD2 _at_ 0x3fff; // 读显示数据地址(E2)

//----------------------液晶-----------------

// 清屏

// 中文显示程序 /

/直线 插 补8/

void delay(uint z)

{

uint x,y;

for(x=z;x>0;x--)

for(y=50;y>0;y--);

}

void zhengx()

{

PA=0x00;

delay(10);

PA=0x01;

delay(10);

}

void fux()

{

PA=0x02;

delay(10);

PA=0x03;

delay(10);

}

void zhengy()

{

PB=0x00;

delay(10);

PB=0x10;

delay(10);

}

void fuy()

{

PB=0x20;

delay(10);

PB=0x30;

delay(10);

}

void zhixian(int NX,int NY)

{int FM, NXY, XOY,ZF,z;

FM=0;

{if(NX>0)

if(NY>0)

XOY=1;

else

XOY=4;

else

if(NY>0)

XOY=2;

else

XOY=3;}

for(NXY= fabs(NX) + fabs(NY)-1;NXY>=0&&P32!=0&&P33!=0;NXY--)

{ {if(NX>0)

if(NY>0)

XOY=1;

else

XOY=4;

else

if(NY>0)

XOY=2;

else

XOY=3;}

for(NXY= fabs(NX) + fabs(NY)-1;NXY>=0;NXY--)

{ if(FM>=0)

{if(XOY==1||XOY==4)

{ZF=1;

zhengx();

}

else

{ZF=2;

fux();

}

FM=FM-fabs(NY);

}

else

{if(XOY==1||XOY==2)

{

ZF=3;

zhengy();

}

else

{ZF=4;

fuy();

}

FM=FM+fabs(NX);

}

}

for(z=0;z<200;z++)

{P35 = 0;

delay(10);

P35 = 1;

delay(10);

}

}

}

/圆 弧 插 补8/

void yuanhu1( int X0,int Y0, int NX, int NY ,int RNS )

{

int NXY,BS,ZF,XM,YM,z;

int FM=0;

BS=fabs(NX-X0) + fabs(NY-Y0);

XM=fabs(X0);

YM=fabs(Y0);

for(NXY= fabs(NX-X0) + fabs(NY-Y0)-1;NXY>=0&&P32!=0&&P33!=0;NXY--)

{

if(RNS==1||RNS==3||RNS==6||RNS==8)

{

if(FM<0)

{

if(RNS==1||RNS==8)

{ZF=1;

zhengx();

}

else

{ZF=2;

fux();}

FM=FM+2fabs(XM)+1;

XM=XM+1;

}

else

{

if(RNS==1||RNS==6)

{

ZF=3;

fuy();

}

else

{ZF=4;

zhengy();

}

FM=FM-2fabs(YM)+1;

YM=YM-1;

}

}

else

if(FM>=0)

{

if(RNS==2||RNS==7)

{ZF=1;

zhengx();

}

else

{ZF=2;

fux();

}

FM=FM-2fabs(XM)+1;

XM=XM-1;

}

else

{

if(RNS==2||RNS==5)

{ZF=3;

zhengy();}

else

{ZF=4;

fuy();}

FM=FM+2fabs(YM)+1;

YM=YM+1;

}

}

if(P32==0||P33==0)

{

for(z=0;z<200;z++)

{P35 = 0;

delay(10);

P35 = 1;

delay(10);

}

}

}

int shuzhi1 ()

{

int i=0,j=0,k=3;

while (1)

{

if(testkey())

{ delay(300);

delay1();

if(testkey())

{ j=getkey();

if(j!=14)

{i=i10 + j;

k--;}

}}

if(k==0)

break;

}

return i;

}

int shuzhi2 ()

{

int i=0,j=0,k=3;

while (1)

{

if(testkey())

{ delay(300);

delay1();

if(testkey())

{ j=getkey();

if(j!=14)

{i=i10 + j;

k--;}

}}

if(k==0)

break;

}

return i;

}

void yuanhuchabu1()

{ int q=0;

delay(300);

R=shuzhi1();

yj1();

q=R/100;

Page_ = 0x00;

Column = 0x35;

Code_ = q;

WriteCHN8x16();

q=R%100;

q=q/10;

Page_ = 0x00;

Column = 0x40;

Code_ = q;

WriteCHN8x16();

q=R%10;

Page_ = 0x00;

Column = 0x48;

Code_ = q;

WriteCHN8x16();

yuanhu1(R,0,0,R,5);

yuanhu1(0,R,-R,0,6);

yuanhu1(-R,0,0,-R,7);

yuanhu1(0,-R,R,0,8);

}

void yuanhuchabu2()

{ int q=0;

delay(300);

R=shuzhi1();

yj1();

q=R/100;

Page_ = 0x00;

Column = 0x35;

Code_ = q;

WriteCHN8x16();

q=R%100;

q=q/10;

Page_ = 0x00;

Column = 0x40;

Code_ = q;

WriteCHN8x16();

q=R%10;

Page_ = 0x00;

Column = 0x48;

Code_ = q;

WriteCHN8x16();

yuanhu1(0,R,R,0,1);

yuanhu1(R,0,0,-R,4);

yuanhu1(0,-R,-R,0,3);

yuanhu1(-R,0,0,R,2);

}

void zhixianchabu()

{ int q1=0,q2=0;

delay(300);

NX=shuzhi1();

delay(300);

NY=shuzhi2();

yj2();

Page_ = 0x00;

Column = 0x25;

Code_ = 0x10;

WriteCHN8x16();

q1=NX/100;

Page_ = 0x00;

Column = 0x30;

Code_ = q1;

WriteCHN8x16();

q1=NX%100;

q1=q1/10;

Page_ = 0x00;

Column = 0x37;

Code_ = q1;

WriteCHN8x16();

q1=NX%10;

Page_ = 0x00;

Column = 0x40;

Code_ = q1;

WriteCHN8x16();

q2=NY/100;

Page_ = 0x00;

Column = 0x50;

Code_ =q1;

WriteCHN8x16();

q2=NY%100;

q2=q2/10;

Page_ = 0x00;

Column = 0x58;

Code_ = q2;

WriteCHN8x16();

q2=NY%10;

Page_ = 0x00;

Column = 0x60;

Code_ = q2;

WriteCHN8x16();

Page_ = 0x00;

Column = 0x72;

Code_ = 0x11;

WriteCHN8x16();

zhixian(NX,NY );

}

void main()

{ int q=0,q1=0,q2=0;

caas=mode;

PA=0X00;

PB=0X00;

PC=0x00;

R=0X00;

while(1)

{

if(testkey())

{

delay1();

if(testKey())

{ delay1();

if(getkey()==15)

{

delay(300);

yuanhuchabu1();

}

else if(getkey()==10)

{ delay(300);

yuanhuchabu2();

}

else if(getkey()==13)

{

zhixianchabu();

}

else if(getkey()==1)

{

zhengx();

}

else if(getkey()==2)

{

fux();

}

else if(getkey()==3)

{

zhengy();

} else if(getkey()==4)

{

fuy();

}

}

}

if(GetKey()==12)

{ break;}

}

}

先看步进电机控制电机转动原理,把时序搞清楚,单片机控制驱动按照时序置管脚就OK

1、本程序用于测试4相步进电机常规驱动

2、需要用跳帽或者杜邦线把信号输出端和对应的步进电机信号输入端连接起来

3、速度不可以调节的过快,不然就没有力矩转动了

4、按s4(设置成独立按键模式)可以控制正反转

------------------------------------------------/

#include <reg52h>

bit Flag;//定义正反转标志位

unsigned char code F_Rotation[4]={0xf1,0xf2,0xf4,0xf8}; //正转表格

unsigned char code B_Rotation[4]={0xf8,0xf4,0xf2,0xf1}; //反转表格

//

/ 延时函数 /

//

void Delay(unsigned int i)//延时

{

while(--i);

}

//

/ 主函数 /

//

main()

{

unsigned char i;

EX1=1; //外部中断0开

IT1=1; //边沿触发

EA=1; //全局中断开

while(!Flag)

{

P0=0x71;//显示 F 标示正转

for(i=0;i<4;i++) //4相

{

P1=F_Rotation[i]; //输出对应的相 可以自行换成反转表格

Delay(500); //改变这个参数可以调整电机转速 ,数字越小,转速越大

}

}

while(Flag)

{

P0=0x7C;//显示 b 标示反转

for(i=0;i<4;i++) //4相

{

P1=B_Rotation[i]; //输出对应的相

Delay(500); //改变这个参数可以调整电机转速 ,数字越小,转速越大

}

}

}

//

/ 中断入口函数 /

//

void ISR_Key(void) interrupt 2 using 1

{

Delay(300);

Flag=!Flag; //s3按下触发一次,标志位取反

}

用单片机同时是不可能的,当然,时间间隔小到可以接受,跑几个任务,那也可以视为同时。要实现真正意义上的同时,用FPGA/CPLD是可以完成的。 话说回来,也许你的同时并不是说一定严格地同时工作,只是说一个单片机去控制四个步进电机,那就好办多了。 一个步进电机,比如四相5线那种,四个IO口可控制一个,四个步进电机就要一陆个,驱动芯片用ULN二00三即可。 当然,如果你的IO口不允许使用这么多,那也可以通过串转并的方法,扩展IO口,比如用漆四HC595,三根IO口控制它,它可以级联,三根线可以控制很多片。一片为吧位,两片就为一陆位,三片为二四位 …… 只要加些三极管驱动那三根控制线,三个IO口可控制一串级联的漆四HC595,得到的扩展IO口,那是相当多的。我用三个IO口控制过5片漆四HC595,三个IO口一下子就扩展成了四0个IO口!!

这是我自己做过的。源码都给你了

#include<reg52h>

#include<intrinsh>

#include<absacch>

#include<stringh>

#define uchar unsigned char

#define uint unsigned int

uint count; //当前计数值

uint distance;

bit intt=1;

unsigned char cont=0;

unsigned char co=0;

uchar buf;

//uchar m,lm,cm;

/针脚定义/

sbit rect_wave=P2^0; //晶振控制信号

sbit RS=P1^0;

sbit RW=P1^1;

sbit EN=P1^2;

sbit CLR=P1^3;

sbit DATA=P1^4;

sbit CLK=P1^5;

sbit d=P2^1;

sbit cp=P2^2;

sbit dir=P2^3;

//

/函数声明/

void time0over(void); //定时器计时程序

void clrlcd(void); //clr LCD

void c_send(unsigned char y); //发命令

void reset(void); // reset LCD

void d_send(unsigned char x); //发数据

void pos(unsigned char pos); //设定显示位置

void l_delay(unsigned int t); //长延时

void trans(j);

void ret(void); //初始化系统

void retcont(void); //定时器复位

void math(void); //计算测量距离

//

void init(void)

{ TH1=0xf3;

TL1=0xf3;

PCON=0x80;

TR1=1;

SCON=0x50; /串口初始化设置,波特率4800BPS/

}

////

void send(uchar dat) /发送子程序/

{ //uchar i;

/发送一个数据/

SBUF=dat;

while(TI==0);

TI=0;

}

//

void turn (void) //电机转动控制

{

unsigned char x;

cont++;

cp=~cp;

l_delay(50);

cp=~cp;

co++;

if(co == 3)

{d=~d;

}

if(co == 4)

{d=~d;

co=0;

}

if (cont == 200) //判断是否进行反转复位

{dir=~dir;

cont=0;

for(x=0;x < 200;x++)

{cp=~cp;

l_delay(5);

cp=~cp;

co++;

if(co == 3)

{d=~d;

}

if(co == 4)

{d=~d;

co=0;

}

}

dir=~dir;

cont=0;

}

}

/子程序/

void int0 () interrupt 0 //中断0服务程序

{

EX0=0; //关闭中断

TR0=0; //关闭定时器

TF0=0; //标志位清零

rect_wave=0; //停止发送超声波

intt=0;

}

void work(void)

{

if(!intt)

{

intt=1;

if (distance < 400)

{

buf=distance;

send(buf);

turn();

math();} //计算所测得的距离

l_delay(5); //延时

retcont(); //定时器复位

rect_wave=1;

count=0;

}

}

void math(void) //计算所测得的距离

{ uchar m,lm,cm;

cm=distance%10; //取距离的最低位

distance=distance/10; //取距离的次高位

lm=distance%10;

distance=distance/10; //取距离的最高位

m=distance%10;

clrlcd(); //输出计算结果

pos(0);

d_send('d');

d_send('i');

d_send('s');

d_send('=');

//pos(4);

d_send(m+0x30);

d_send(lm+0x30);

d_send(cm+0x30);

d_send('c');

d_send('m');

l_delay(500);

}

void time0over(void) //定时器计时程序

{ TF0=0;

count++;

distance=count;

}

/

void trans(j)

{

switch(j)

{

case 0: d_send('0');break;

case 1: d_send('1');break;

case 2: d_send('2');break;

case 3: d_send('3');break;

case 4: d_send('4');break;

case 5: d_send('5');break;

case 6: d_send('6');break;

case 7: d_send('7');break;

case 8: d_send('8');break;

case 9: d_send('9');break;

}

}

/

delay() //延时

{

int i;

for(i=0;i<1000;i++);

}

void l_delay(unsigned int t) //延时

{

unsigned int p;

unsigned int j;

for(j=0;j<t;j++)

{

for(p=0;p<1000;p++);

}

}

void reset(void) // reset LCD

{

delay();

c_send(0x38);

c_send(0x01);

c_send(0x06);

c_send(0x0c);

c_send(0x80);

}

void clrlcd(void) // clr LCD

{

delay();

c_send(0x01);

}

void pos(unsigned char pos) //设定显示位置

{

c_send(pos | 0x80);

}

void c_send(unsigned char y) //发命令

{

unsigned char i;

EN=1;

RS=0;

RW=0;

for(i=0;i<8;i++)

{

if(_crol_(y,i)&0x80)

DATA=1;

else

DATA=0;

CLK=0;

CLK=1;

}

EN=0;

delay();

}

void d_send(unsigned char x) //发数据

{

unsigned char i;

EN=1;

RS=1;

RW=0;

for(i=0;i<8;i++)

{

if(_crol_(x,i)&0x80)

DATA=1;

else

DATA=0;

CLK=0;

CLK=1;

}

EN=0;

delay();

}

void ret(void) //初始化计数器

{ TMOD=0x22; //设置定时器计数器1为工作方式2

TH0=0xc6; //设置计数初值高字节

TL0=0xc6; //设置计数初值低字节

count=0;

IE=0x00; //禁止中断

TF0=0; //溢出标志位清零

TR0=1; //打开定时器1

rect_wave=1;

EA=1; //打开中断

IP=0x01; //外部中断0为高中断优先级

IT0=0; //外部中断低电平触发シ

EX0=1;

}

void retcont(void)

{ TF0=0; //溢出标志位清零

TR0=1; //打开定时器1

EA=1; //打开中断

IP=0x01; //外部中断0为高中断优先级

IT0=0; //外部中断下降沿触发

EX0=1;

rect_wave=1;

}

/主程序/

void main(void)

{ rect_wave=0;

reset();

l_delay(10);

ret();

init();

math();

for(;;)

{

if(TF0)

{

time0over();

}

work();

}

}

以上就是关于51单片机控制步进电机程序。在线等高分,请会写的高手大侠写出来。全部的内容,包括:51单片机控制步进电机程序。在线等高分,请会写的高手大侠写出来。、一个51单片机同时控制2个步进电机的C语言程序、如何使用单片机控制步进电机等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9307876.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存