标题:
单片机控制三相步进电极(C 语言程序)
[打印本页]
作者:
huxiao
时间:
2015-1-24 16:07
标题:
单片机控制三相步进电极(C 语言程序)
因为这是第一次接触步进电机以及电机驱动器,所以编了个简单的程序,其实是改过来的,有兴趣的朋友可以参考一下,喜欢交流的朋友也可以回帖.
这是l连接好的图片:
我用p1口的0、1、2、3分别接驱动器的+、PU、+、DR接线端,其中PU的脉冲提供了转速的变化,DR电平的改变决定了旋转方向下面给出程序,大家有什么不懂的到群里讨论。
#include <reg51.h> //51芯片管脚定义头文件
#include <intrins.h> //内部包含延时函数 _nop_() ;
#define uchar unsigned char
#define uint unsigned int
#define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;
uchar code FFW[4]={0xf5,0xf7,0xf5,0xf7} ;
uchar code REV[4]={0xfd,0xff,0xfd,0xff} ;
sbit K1 = P3^3 ; //运行与停止
sbit K2 = P3^2 ; //设定圈数
sbit K3 = P3^5 ; //方向转换
sbit K4 = P3^4 ; //速率调整
sbit BEEP = P2^4 ; //蜂鸣器
sbit LCD_RS = P2^6 ;
sbit LCD_RW = P3^6 ;
sbit LCD_EN = P2^7 ;
bit on_off=0 ; //运行与停止标志
bit direction=1 ; //方向标志
bit rate_dr=1 ; //速率标志
bit snum_dr=1 ; //圈数标志
uchar code cdis1[ ] = {" STEPPING MOTOR "} ;
uchar code cdis2[ ] = {"CONTROL PROCESS"} ;
uchar code cdis3[ ] = {" STOP "} ;
uchar code cdis4[ ] = {"NUM: RATE: "} ;
uchar code cdis5[ ] = {" RUNNING "} ;
uchar m,v=0,q=0 ;
int number=0,number1=0;
char snum=1,snum1=1 ; //预设定圈数
char rate=1 ; //预设定速率
char data_temp,data_temp1,data_temp2 ;
/********************************************************/
/*
/* 延时t毫秒
/* 11.0592MHz时钟,延时约1ms
/*
/********************************************************/
void delay(uint t)
{
uchar k ;
while(t--)
{
for(k=0 ; k<125 ; k++)
{ }
}
}
/********************************************************/
void delayB(uchar x) //x*0.14MS
{
uchar i ;
while(x--)
{
for (i=0 ; i<13 ; i++)
{ }
}
}
/********************************************************/
void beep()
{
uchar j ;
for (j=0 ;j<100 ;j++)
{
delayB(4) ;
BEEP=!BEEP ; //BEEP取反
}
BEEP=1 ; //关闭蜂鸣器
delay(170) ;
}
/********************************************************/
/*
/*检查LCD忙状态
/*lcd_busy为1时,忙,等待。为0时,闲,可写指令与数据。
/*
/********************************************************/
bit lcd_busy()
{
bit result ;
LCD_RS = 0 ;
LCD_RW = 1 ;
LCD_EN = 1 ;
delayNOP() ;
result = (bit)(P0&0x80) ;
LCD_EN = 0 ;
return(result) ;
}
/********************************************************/
/*
/*写指令数据到LCD
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
/*
/********************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy()) ;
LCD_RS = 0 ;
LCD_RW = 0 ;
LCD_EN = 0 ;
_nop_() ;
_nop_() ;
P0 = cmd ;
delayNOP() ;
LCD_EN = 1 ;
delayNOP() ;
LCD_EN = 0 ;
}
/********************************************************/
/*
/*写显示数据到LCD
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。
/*
/********************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy()) ;
LCD_RS = 1 ;
LCD_RW = 0 ;
LCD_EN = 0 ;
P0 = dat ;
delayNOP() ;
LCD_EN = 1 ;
delayNOP() ;
LCD_EN = 0 ;
}
/********************************************************/
/*
/* LCD初始化设定
/*
/********************************************************/
void lcd_init()
{
delay(30) ;
lcd_wcmd(0x38) ; //16*2显示,5*7点阵,8位数据
delay(5) ;
lcd_wcmd(0x38) ;
delay(5) ;
lcd_wcmd(0x38) ;
delay(5) ;
lcd_wcmd(0x0c) ; //显示开,关光标
delay(5) ;
lcd_wcmd(0x06) ; //移动光标
delay(5) ;
lcd_wcmd(0x01) ; //清除LCD的显示内容
delay(5) ;
}
/********************************************************/
/*
/* 设定显示位置
/*
/********************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80) ; //数据指针=80+地址变量
}
/********************************************************/
/*
/* LCD1602初始显示子程序
/*
/********************************************************/
void LCD_init_DIS()
{
delay(10) ; //延时
lcd_init() ; //初始化LCD
lcd_pos(0) ; //设置显示位置为第一行的第1个字符
m = 0 ;
while(cdis1[m] != '\0')
{ //显示字符
lcd_wdat(cdis1[m]) ;
m++ ;
}
lcd_pos(0x40) ; //设置显示位置为第二行第1个字符
m = 0 ;
while(cdis2[m] != '\0')
{
lcd_wdat(cdis2[m]) ; //显示字符
m++ ;
}
delay(1000) ; //延时
lcd_pos(0) ; //设置显示位置为第一行的第1个字符
m = 0 ;
while(cdis3[m] != '\0')
{ //显示字符
lcd_wdat(cdis3[m]) ;
m++ ;
}
lcd_pos(0x40) ; //设置显示位置为第二行第1个字符
m = 0 ;
while(cdis4[m] != '\0')
{
lcd_wdat(cdis4[m]) ; //显示字符
m++ ;
}
for(m=0 ;m<2 ;m++)
{
lcd_pos(0x0c+m) ; //显示方向符号
lcd_wdat(0x3e) ;
}
}
/********************************************************/
/*
/*数据转换子程序
/*
/********************************************************/
void data_conv()
{
data_temp1=data_temp/10 ; //高位
if(data_temp1==0)
{data_temp1=0x20 ;} //高位为0不显示
else
{data_temp1=data_temp1+0x30 ;}
data_temp2=data_temp%10 ; //低位
data_temp2=data_temp2+0x30 ;
}
/********************************************************/
/*
/*数据显示子程序
/*
/********************************************************/
void data_dis()
{
data_temp = snum ; //显示圈数
data_conv() ;
lcd_pos(0x44) ;
lcd_wdat(data_temp1) ;
lcd_pos(0x45) ;
lcd_wdat(data_temp2) ;
data_temp = rate ; //显示速率
data_conv() ;
lcd_pos(0x4d) ;
lcd_wdat(data_temp1) ;
lcd_pos(0x4e) ;
lcd_wdat(data_temp2) ;
}
/********************************************************
/*
/* 显示运行方向符号
/*
/********************************************************/
void motor_DR()
{
if(direction==1) //正转方向标志
{ for(m=0 ;m<2 ;m++)
{
lcd_pos(0x0c+m) ; //显示方向符号
lcd_wdat(0x3e) ;
}
}
else
{ for(m=0 ;m<2 ;m++) //反转方向标志
{
lcd_pos(0x0c+m) ; //显示方向符号
lcd_wdat(0x3c) ;
}
}
}
/********************************************************
/*
/* 显示运行状态
/*
/********************************************************/
void motor_RUN()
{
if(on_off==1)
{ TR0=1 ;
lcd_pos(0) ; //设置显示位置为第一行的第1个字符
m = 0 ;
while(cdis5[m] != '\0')
{ lcd_wdat(cdis5[m]) ; //RUNNING
m++ ; }
motor_DR() ; //
}
else
{ TR0=0 ; P1 =0xf0 ;
lcd_pos(0) ; //设置显示位置为第一行的第1个字符
m = 0 ;
while(cdis3[m] != '\0')
{ lcd_wdat(cdis3[m]) ; //STOP
m++ ; }
motor_DR() ; //
snum=snum1 ; //
number1=0 ; //清圈数计数器
}
}
/********************************************************
*
* 主程序
*
*********************************************************/
main()
{
LCD_init_DIS() ;
TMOD = 0x01 ; //T0定时方式1
TL0 = 0xee ;
TH0 = 0xff ;
EA = 1 ;
ET0 = 1 ;
P1 = 0xf0 ;
while(1)
{
if(K1==0)
{
beep() ;
while(K1==0) ; //等待键释放
on_off=~on_off ;
motor_RUN() ;
} //K1 end
/********************************************************/
if(K2==0)
{
beep() ;
if(snum_dr==1)
{ snum++ ;
snum1=snum ;
if(snum==10)
{ snum_dr=~snum_dr ;}
}
else
{snum-- ;
snum1=snum ;
if(snum==1)
{ snum_dr=~snum_dr ; }
}
} //K2 end
/********************************************************/
if(K3==0)
{
beep() ;
direction=~direction ;
motor_DR() ;
}//K3 end
/********************************************************/
if(K4==0)
{
beep() ;
if(rate_dr==1)
{ rate++ ;
if(rate==10)
{ rate_dr=~rate_dr ;}
}
else
{
rate-- ;
if(rate==1)
{ rate_dr=~rate_dr ; }
}
} //K4 end
/********************************************************/
if(number1==snum1) //与设定圈数是否相等
{ number1=0 ;
on_off=0 ;
TR0=0 ;
snum=snum1 ;
P1 =0xf0 ;
motor_RUN() ;
}
data_dis() ;
} // while(1) end
} //main end
/********************************************************/
/*
/* 定时器 0 中断
/*
/********************************************************/
void motor_onoff() interrupt 1
{
TL0 = 0xff ;
TH0 = 0xff ;
q++ ;
if(q < rate)
{ return ; }
else
{ q=0 ;
number++ ; //脉冲计数
if(number==800) //2*400个脉冲电机转一圈
{ snum-- ;
number=0 ;
number1++ ;
} //电机转动圈数
if(direction==1) //方向标志
{ if(v<4)
{P1 = FFW[v] ;v++ ;} //取数据,正转
if(v==4)
{ v=0 ; }
}
else
{ if(v<4)
{P1 = REV[v] ;v++ ;} //取数据,反转
if(v==4)
{ v=0 ; }
}
}
}
复制代码
以上程序本人运行正常。
作者:
xyz1015231411
时间:
2015-1-28 12:15
不错,值得学习
作者:
6ningning
时间:
2015-4-12 15:07
这个不错。
作者:
小坤--
时间:
2015-4-14 14:28
感谢分享
作者:
xuanyuanleiyun
时间:
2015-4-14 18:37
很有用处的帖子,先收藏了
作者:
lyrichard021
时间:
2015-6-15 12:25
驱动器是什么型号的
作者:
liu2916
时间:
2015-6-18 15:14
我也准备做个反馈程序用到步进电机,到时候向你请教。
作者:
君君爱你
时间:
2016-4-18 14:49
好难啊
作者:
Richardyg
时间:
2016-8-23 09:48
怎么1602液晶不显示转速和方向?????????????????????
作者:
e介草民
时间:
2017-9-27 11:02
赞一个,感谢分享
作者:
GUOXUAN
时间:
2017-11-24 16:57
三相步进电机我买错了2个,没找到驱动就一直放,现在变废铁啦
作者:
zxdpj
时间:
2018-1-29 14:52
非常好,谢谢分享!
作者:
vbnm
时间:
2019-3-17 21:26
楼主 你好单片机接到什么电器来控制电机的可以讲解下下吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1