您好,欢迎访问三七文档
当前位置:首页 > 机械/制造/汽车 > 综合/其它 > 51单片机驱动步进电机的方法(详解)
51单片机驱动步进电机的方法2019.02这款步进电机的驱动电压12V,步进角为7.5度.一圈360度,需要48个脉冲完成!!!该步进电机有6根引线,排列次序如下:1:红色、2:红色、3:橙色、4:棕色、5:黄色、6:黑色。采用51驱动ULN2003的方法进行驱动。ULN2003的驱动直接用单片机系统的5V电压,可能力矩不是很大,大家可自行加大驱动电压到12V。;******************************************************************************;*************************步进电机的驱动***************************************;DESIGNBYBENLADN911FOSC=12MHz2005.05.19;---------------------------------------------------------------------------------;步进电机的驱动信号必须为脉冲信号!!!转动的速度和脉冲的频率成正比!!!;本步进电机步进角为7.5度.一圈360度,需要48个脉冲完成!!!;---------------------------------------------------------------------------------;A组线圈对应P2.4;B组线圈对应P2.5;C组线圈对应P2.6;D组线圈对应P2.7;正转次序:AB组--BC组--CD组--DA组(即一个脉冲,正转7.5度);----------------------------------------------------------------------------------;----------------------------正转--------------------------ORG0000HLJMPMAINORG0100HMAIN:MOVR3,#144正转3圈共144脉冲START:MOVR0,#00HSTART1:MOVP2,#00HMOVA,R0MOVDPTR,#TABLEMOVCA,@A+DPTRJZSTART对A的判断,当A=0时则转到STARTMOVP2,ALCALLDELAYINCR0DJNZR3,START1MOVP2,#00HLCALLDELAY1;-----------------------------反转------------------------MOVR3,#144反转一圈共144个脉冲START2:MOVP2,#00HMOVR0,#05START3:MOVA,R0MOVDPTR,#TABLEMOVCA,@A+DPTRJZSTART2MOVP2,ACALLDELAYINCR0DJNZR3,START3MOVP2,#00HLCALLDELAY1LJMPMAINDELAY:MOVR7,#40步进电机的转速M3:MOVR6,#248DJNZR6,$DJNZR7,M3RETDELAY1:MOVR4,#202S延时子程序DEL2:MOVR3,#200DEL3:MOVR2,#250DJNZR2,$DJNZR3,DEL3DJNZR4,DEL2RETTABLE:DB30H,60H,0C0H,90H正转表DB00正转结束DB30H,90H,0C0H,60H反转表DB00反转结束END51单片机控制四相步进电机拿到步进电机,根据以前看书对四相步进电机的了解,我对它进行了初步的测试,就是将5伏电源的正端接上最边上两根褐色的线,然后用5伏电源的地线分别和另外四根线(红、兰、白、橙)依次接触,发现每接触一下,步进电机便转动一个角度,来回五次,电机刚好转一圈,说明此步进电机的步进角度为360/(4×5)=18度。地线与四线接触的顺序相反,电机的转向也相反。此步进电机,则只需分别依次给四线一定时间的脉冲电流,电机便可连续转动起来。通过改变脉冲电流的时间间隔,就可以实现对转速的控制;通过改变给四线脉冲电流的顺序,则可实现对转向的控制。所以,设计了如下电路图:C51程序代码为:代码一#includeAT89X51.hstaticunsignedintcount;staticunsignedintendcount;voiddelay();voidmain(void){count=0;P1_0=0;P1_1=0;P1_2=0;P1_3=0;EA=1;//允许CPU中断TMOD=0x11;//设定时器0和1为16位模式1ET0=1;//定时器0中断允许TH0=0xFC;TL0=0x18;//设定时每隔1ms中断一次TR0=1;//开始计数startrun:P1_3=0;P1_0=1;delay();P1_0=0;P1_1=1;delay();P1_1=0;P1_2=1;delay();P1_2=0;P1_3=1;delay();gotostartrun;}//定时器0中断处理voidtimeint(void)interrupt1{TH0=0xFC;TL0=0x18;//设定时每隔1ms中断一次count++;}voiddelay(){endcount=2;count=0;do{}while(countendcount);}将上面的程序编译,用ISP下载线下载至单片机运行,步进电机便转动起来了,初步告捷!不过,上面的程序还只是实现了步进电机的初步控制,速度和方向的控制还不够灵活,另外,由于没有利用步进电机内线圈之间的“中间状态”,步进电机的步进角度为18度。所以,我将程序代码改进了一下,如下:代码二#includeAT89X51.hstaticunsignedintcount;staticintstep_index;voiddelay(unsignedintendcount);voidgorun(bitturn,unsignedintspeedlevel);voidmain(void){count=0;step_index=0;P1_0=0;P1_1=0;P1_2=0;P1_3=0;EA=1;//允许CPU中断TMOD=0x11;//设定时器0和1为16位模式1ET0=1;//定时器0中断允许TH0=0xFE;TL0=0x0C;//设定时每隔0.5ms中断一次TR0=1;//开始计数do{gorun(1,60);}while(1);}//定时器0中断处理voidtimeint(void)interrupt1{TH0=0xFE;TL0=0x0C;//设定时每隔0.5ms中断一次count++;}voiddelay(unsignedintendcount){count=0;do{}while(countendcount);}voidgorun(bitturn,unsignedintspeedlevel){switch(step_index){case0:P1_0=1;P1_1=0;P1_2=0;P1_3=0;break;case1:P1_0=1;P1_1=1;P1_2=0;P1_3=0;break;case2:P1_0=0;P1_1=1;P1_2=0;P1_3=0;break;case3:P1_0=0;P1_1=1;P1_2=1;P1_3=0;break;case4:P1_0=0;P1_1=0;P1_2=1;P1_3=0;break;case5:P1_0=0;P1_1=0;P1_2=1;P1_3=1;break;case6:P1_0=0;P1_1=0;P1_2=0;P1_3=1;break;case7:P1_0=1;P1_1=0;P1_2=0;P1_3=1;}delay(speedlevel);if(turn==0){step_index++;if(step_index7)step_index=0;}else{step_index--;if(step_index0)step_index=7;}}改进的代码能实现速度和方向的控制,而且,通过step_index静态全局变量能“记住”步进电机的步进位置,下次调用gorun()函数时则可直接从上次步进位置继续转动,从而实现精确步进;另外,由于利用了步进电机内线圈之间的“中间状态”,步进角度减小了一半,只为9度,低速运转也相对稳定一些了。但是,在代码二中,步进电机的运转控制是在主函数中,如果程序还需执行其它任务,则有可能使步进电机的运转收到影响,另外还有其它方面的不便,总之不是很完美的控制。所以我又将代码再次改进:代码三#includeAT89X51.hstaticunsignedintcount;//计数staticintstep_index;//步进索引数,值为0-7staticbitturn;//步进电机转动方向staticbitstop_flag;//步进电机停止标志staticintspeedlevel;//步进电机转速参数,数值越大速度越慢,最小值为1,速度最快staticintspcount;//步进电机转速参数计数voiddelay(unsignedintendcount);//延时函数,延时为endcount*0.5毫秒voidgorun();//步进电机控制步进函数voidmain(void){count=0;step_index=0;spcount=0;stop_flag=0;P1_0=0;P1_1=0;P1_2=0;P1_3=0;EA=1;//允许CPU中断TMOD=0x11;//设定时器0和1为16位模式1ET0=1;//定时器0中断允许TH0=0xFE;TL0=0x0C;//设定时每隔0.5ms中断一次TR0=1;//开始计数turn=0;speedlevel=2;delay(10000);speedlevel=1;do{speedlevel=2;delay(10000);speedlevel=1;delay(10000);stop_flag=1;delay(10000);stop_flag=0;}while(1);}//定时器0中断处理voidtimeint(void)interrupt1{TH0=0xFE;TL0=0x0C;//设定时每隔0.5ms中断一次count++;spcount--;if(spcount=0){spcount=speedlevel;gorun();}}voiddelay(unsignedintendcount){count=0;do{}while(countendcount);}voidgorun(){if(stop_flag==1){P1_0=0;P1_1=0;P1_2=0;P1_3=0;return;}switch(step_index){case0://0P1_0=1;P1_1=0;P1_2=0;P1_3=0;break;case1://0、1P1_0=1;P1_1=1;P1_2=0;P1_3=0;break;case2://1P1_0=0;P1_1=1;P1_2=0;P1_3=0;break;case3://1、2P1_0=0;P1_1=1;P1_2=1;P1_3=0;break;case4://2P1_0=0;P1_1=0;P1_2=1;P1_3=0;break;case5://2、3P1_0=0;P1_1=0;P1_2=1;P1_3=1;break;case6://3P1_0=0;P1_1=0;P1_2=0;P1_3=1;break;case7://3、0P1_0=1;P1_1=0;P1_2=0;P1_3=1;}if(turn==0){step_index++;if(step_index7)step_index=0;}else{step_index--;if(step_index0)step_index=7;}}在代码三中,我将步进电机的运转控制放在时间中断函数之中,这样主函数就能很方便的加入其它任务的执行,而对步进电机的运转不产生影响
本文标题:51单片机驱动步进电机的方法(详解)
链接地址:https://www.777doc.com/doc-1491072 .html