步进电机源程序
说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。
/*************************************************************************** 程序功能:通过遥控控制步进电机转动的圈数 作 者:Sun 制作日期:2011年7月16日 相关说明:采用uPD6121G芯片发射码格式,用单片机AT89S52实现解码 晶振频率:11.0592MHz,步进电机为28BYJ-48 在数码管上同步显示当前转动的圈数 ***************************************************************************/ #include //51芯片管脚定义头文件 #include //内部包含延时函数 _nop_() #define uchar unsigned char #define uint unsigned int uchar code FFW[8]={0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09}; //正转相序编码 uchar code REV[8]={0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01}; //反转相序编码 uchar code YK_code[]={0xfc, 0xf8, 0xf4, 0xf0, 0xec, 0xe8, 0xe4, 0xe0, 0xdc, 0xd8}; //遥控器解码对应的编码“0-9” uchar code s8[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管显示“0-9” uchar code PM[2]={0xff,0xbf}; //数码管显示正反转 uchar code SW[2]={0xbf,0x7f}; //数码管位显示 sbit IR=P3^2; //定义红外接收器控制端口 sbit BEEP = P3^6; //定义蜂鸣器控制端口 uint LowTime, HighTime; //储存高低电平宽度 uchar a[4]; //储存四位用户码和数据码 uchar key=10; //储存检测到的键值,预先置为无效位 uchar count=1; //数码管显示转动圈数的计数标识位 bit flag=0; //正转反转的标志位 bit wbs=0; //数码管显示位的标识位 /************************************************** 函数功能:实现n毫秒延时 入口参数:n **************************************************/ void delaynms(uint i) { uchar j; while(i--) { for(j=0; j<114; j++) //1ms基准延时程序 { ; } } } /************************************************** 函数功能:蜂鸣器发出响声 **************************************************/ void beep(void) { uchar i; for(i=0; i<80; i++) { BEEP=~BEEP; delaynms(1); //延时 } BEEP=1; //关闭蜂鸣器 } /************************************************** 函数功能:步进电机正转并在数码管上显示出来 **************************************************/ void motor_ffw(void) { uchar i, j; for(j=0; j<8; j++) //内部转轴转一圈 { if(wbs==0) //控制数码管显示 P0=PM[flag]; else P0=s8[count]; P2=SW[wbs]; wbs=~wbs; for(i=0; i<8; i++) //一个周期转四十五度 { P1=FFW[i]; //取数据 delaynms(1); //调整速度 } P2=0xff; } } /************************************************** 函数功能:步进电机反转并在数码管上显示出来 **************************************************/ void motor_rev(void) { uchar i, j; for(j=0; j<8; j++) //内部转轴转一圈 { if(wbs==0) //控制数码管显示 P0=PM[flag]; else P0=s8[count]; P2=SW[wbs]; wbs=~wbs; for(i=0; i<8; i++) //一个周期转四十五度 { P1=REV[i]; //取数据 delaynms(1); //调整速度 } P2=0xff; } } /************************************************** 函数功能:驱动步进电机运行 **************************************************/ void drivemotor(void) { uchar i, j; if(flag==0) { for(i=0; i { for(j=0; j<64; j++) { motor_ffw(); } count++;
//正转标志位成立
//步进电机正转
} }
if(flag==1) { for(i=0; i { for(j=0; j<64; j++) {
//反转标志位成立
motor_rev(); //步进电机反转 } count++; } } wbs=0; count=1; P1=0xf0; }
/************************************************** 函数功能:对四个字节的用户码和数据码进行解码 说明:解码正确返回1,解码错误返回0
**************************************************/
bit Decode(void) { uchar i, j; uchar temp; for(i=0; i<4; i++) 据码 { for(j=0; j<8; j++)
{
temp>>=1; 位,因为是先读出的是地位数据 TH0=0; 清零 TL0=0; 清零 TR0=1; while(IR==0); 低电平计时 TR0=0; LowTime=TH0*256+TL0; TH0=0;
//储存解码出的数据 //连续读取四个用户码和数 //每个码有八位数字 //temp中的数据右移一 //将定时器T0的高八位 //将定时器T0的低八位
//打开定时器T0
//如果是低电平就等待,对 //关闭定时器T0
//计算低电平持续时间 //将定时器T0的高八位
清零 清零 高电平计时
TL0=0;
//将定时器T0的低八位
TR0=1; while(IR==1); //打开定时器T0
//如果是高电平就等待,对
//关闭定时器T0
//计算高电平持续时间
TR0=0; HighTime=TH0*256+TL0; if((LowTime<370)||(LowTime>670))
return 0; 范围,则认为出错,停止解码 if((HighTime>420)&&(HighTime<620)) 秒左右,即计数560/1.085=516次 temp=temp&0x7f; 520+100=620),则该位是0 if((HighTime>1300)&&(HighTime<1800)) 秒左右,即计数1680/1.085=1548次 temp=temp|0x80; //(1550-250=1300,1550+250=1800),则该位是1 }
//如果低电平长度不在合理 //如果高电平时间在560微
//(520-100=420,
//如果高电平时间在1680微
a[i]=temp; //将解码出的字节值储存在a[i] } if(a[2]=~a[3]) //验证键数据码和其反码是否相等,一般情况下不必验证用户码 return 1; //解码正确,返回1 }
/************************************************** 函数功能:检测按下哪个按键
**************************************************/
void check(void) { uchar i; }
for(i=0; i<10; i++) { if(YK_code[i]==a[2]) { key=i; } }
//需要转换十位数据
//将红外接受器的解码转换对应的键值
//将转换结果储存到标识符key
/************************************************** 函数功能:主函数
**************************************************/
void main(void) { EA=1; //开放总中断 EX0=1; //允许外部中断0 ET0=1; //允许定时器T0中断 IT0=1; //定义外中断为下降沿触发 TMOD=0x01; //定义定时器T0为工作方式1 TR0=0; //关闭定时器T0
while(1) //等待遥控发出指令 { ; } }
/*************************************************** 函数功能:红外触发的外中断处理程序
***************************************************/
void int0(void) interrupt 0 {
EX0=0; //关闭外部中断0 TH0=0; //将定时器T0的高八位清零 TL0=0; //将定时器T0的低八位清零 TR0=1; //打开定时器T0 while(IR==0); //如果是低电平就等待,对引导码低电平计时 TR0=0; //关闭定时器T0 LowTime=TH0*256+TL0; //计算低电平持续时间 TH0=0; //将定时器T0的高八位清零 TL0=0; //将定时器T0的低八位清零 TR0=1; //打开定时器T0 while(IR==1); //如果是高电平就等待,对引导码高电平计时 TR0=0; //关闭定时器T0 HighTime=TH0*256+TL0; //计算高电平持续时间 if((LowTime>7800)&&(LowTime<8800)&&(HighTime>3600)&&(HighTime<4700)) 如果是引导码就进行解码,否则放弃 { if(Decode()==1) //执行遥控解码功能 { beep(); //蜂鸣器响一声 提示解码成功
//
}
check(); //检测键值 if(key==0) //检测到零键改变正反转 { flag=~flag; //正反转标志位取反 }
//为无效位时不执行任何指令
else if(key==10) { ; } else { drivemotor(); } } key=10; } EX0=1;
//驱动步进电机转动
//置为无效位
//开放外部中断0
本文来源:https://www.wddqw.com/doc/cbb3af36f9d6195f312b3169a45177232f60e421.html