專注電子技術(shù)學(xué)習(xí)與研究
當前位置:單片機教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

51單片機驅(qū)動步進電機__終極(完整版)

作者:佚名   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2013年11月04日   【字體:

     在這里介紹一下用51單片機驅(qū)動步進電機的方法。  

 
這款步進電機的驅(qū)動電壓12V,步進角為 7.5度 . 一圈 360 度 , 需要 48 個脈沖完成!!!   
   
該步進電機有6根引線,排列次序如下:1:紅色、2:紅色、3:橙色、4:棕色、5:黃色、6:黑色。   
采用51驅(qū)動ULN2003的方法進行驅(qū)動。  
 
ULN2003的驅(qū)動直接用單片機系統(tǒng)的5V電壓,可能力矩不是很大,大家可自行加大驅(qū)動電壓到12V。  
 
;****************************************************************************** 
 
 
 
 
 
 
;************************* 步進電機的驅(qū)動*************************************** ; DESIGN BY BENLADN911      FOSC = 12MHz      2005.05.19  
;---------------------------------------------------------------------------------  
; 步進電機的驅(qū)動信號必須為 脈沖信號!!! 轉(zhuǎn)動的速度和脈沖的頻率成正比!!!  
; 本步進電機步進角為 7.5度 . 一圈 360 度 , 需要 48 個脈沖完成!!!  
;---------------------------------------------------------------------------------  
; A組線圈對應(yīng) P2.4  
; B組線圈對應(yīng) P2.5  
; C組線圈對應(yīng) P2.6  
; D組線圈對應(yīng) P2.7 
 
; 正轉(zhuǎn)次序: AB組--BC組--CD組--DA組 (即一個脈沖,正轉(zhuǎn) 7.5 度)  
;----------------------------------------------------------------------------------  
;----------------------------正轉(zhuǎn)-------------------------- ORG 0000H LJMP MAIN ORG 0100H 
MAIN: 
MOV R3,#144     正轉(zhuǎn) 3 圈共 144 脈沖 START: MOV R0,#00H START1: MOV P2,#00H MOV A,R0 
MOV DPTR,#TABLE MOVC A,@A+DPTR 
JZ START     對 A 的判斷,當 A = 0 時則轉(zhuǎn)到 START MOV P2,A 
LCALL DELAY INC R0 
DJNZ R3,START1 
MOV P2,#00H LCALL DELAY1 
;-----------------------------反轉(zhuǎn)------------------------ 
 
 
 
 
 
 
MOV R3,#144      反轉(zhuǎn)一圈共 144 個脈沖 START2: 
MOV P2,#00H MOV R0,#05 START3: MOV A,R0 
MOV DPTR,#TABLE MOVC A,@A+DPTR JZ START2 MOV P2,A CALL DELAY INC R0 
DJNZ R3,START3 MOV P2,#00H 
LCALL DELAY1 LJMP MAIN 
DELAY: MOV R7,#40 步進電機的轉(zhuǎn)速 M3: MOV R6,#248 DJNZ R6,$ DJNZ R7,M3 
RET 
DELAY1:              MOV     R4,#20      2S 延時子程序 DEL2:                MOV     R3,#200 DEL3:                MOV     R2,#250                      DJNZ    R2,$                      DJNZ    R3,DEL3                      DJNZ    R4,DEL2                      RET TABLE: 
DB 30H,60H,0C0H,90H    正轉(zhuǎn)表 DB 00    正轉(zhuǎn)結(jié)束 
DB 30H,90H,0C0H,60H    反轉(zhuǎn)表 DB 00    反轉(zhuǎn)結(jié)束 END 
        51單片機控制四相步進電機 
  
拿 到步進電機,根據(jù)以前看書對四相步進電機的了解,我對它進行了初步的測試,就是將5伏電源的正端接上最邊上兩根褐色的線,然后用5伏電源的地線分別和另外 四根線(紅、蘭、白、橙)依次接觸,發(fā)現(xiàn)每接觸一下,步進電機便轉(zhuǎn)動一個角度,來回五次,電機剛好轉(zhuǎn)一圈,說明此步進電機的步進角度為 360/(4×5)=18度。地線與四線接觸的順序相反,電機的轉(zhuǎn)向也相反。 
此步進電機,則只需分別依次給四線一定時間的脈沖電流,電機便可連續(xù)轉(zhuǎn)動起來。
通過改變脈沖電流的時間間隔,就可以實現(xiàn)對轉(zhuǎn)速的控制;通過改變給四線脈沖電流的順序,則可實現(xiàn)對轉(zhuǎn)向的控制。所以,設(shè)計了如下電路圖: 
 
 
 
 
 
 
 
C51程序代碼為: 代碼一 
#include <AT89X51.h>  static unsigned int count; static unsigned int endcount; void delay(); void main(void)  { 
  count = 0;   P1_0 = 0;   P1_1 = 0;   P1_2 = 0;   P1_3 = 0; 
  EA = 1;              //允許CPU中斷  
  
TMOD = 0x11;  //設(shè)定時器0和1為16位模式1  
  ET0 = 1;             //定時器0中斷允許    TH0 = 0xFC;  
  TL0 = 0x18;      //設(shè)定時每隔1ms中斷一次     TR0 = 1;           //開始計數(shù) 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(); 
  goto startrun; }  
//定時器0中斷處理   
void timeint(void) interrupt 1  {  
  TH0=0xFC;  
  TL0=0x18; //設(shè)定時每隔1ms中斷一次   count++; } 
void delay() 
 
 
 
 
 
 
  endcount=2;   count=0; 
  do{}while(count<endcount); } 
 
  將上面的程序編譯,用ISP下載線下載至單片機運行,步進電機便轉(zhuǎn)動起來了,初步告捷!  
  不過,上面的程序還只是實現(xiàn)了步進電機的初步控制,速度和方向的控制還不夠靈活,另外,由于沒有利用步進電機內(nèi)線圈之間的“中間狀態(tài)”,步進電機的步進角度為18度。所以,我將程序代碼改進了一下,如下:  
代碼二 
#include <AT89X51.h>  static unsigned int count; 
static int step_index; 
void delay(unsigned int endcount); 
void gorun(bit turn, unsigned int speedlevel); void main(void)  { 
  count = 0; 
  step_index = 0;   P1_0 = 0;   P1_1 = 0;   P1_2 = 0;   P1_3 = 0; 
  EA = 1;             //允許CPU中斷  
  TMOD = 0x11; //設(shè)定時器0和1為16位模式1    
ET0 = 1;            //定時器0中斷允許  
  TH0 = 0xFE;  
  TL0 = 0x0C;  //設(shè)定時每隔0.5ms中斷一次     TR0 = 1;         //開始計數(shù)   do{ 
    gorun(1,60);   }while(1); 
}  
//定時器0中斷處理  
void timeint(void) interrupt 1  {  
  TH0=0xFE;  
  TL0=0x0C; //設(shè)定時每隔0.5ms中斷一次   count++; } 
 
 
 
 
 
 
 
    P1_3 = 1;     break;   case 6: 
    P1_0 = 0;     P1_1 = 0;     P1_2 = 0;     P1_3 = 1;     break;   case 7:     P1_0 = 1;     P1_1 = 0;     P1_2 = 0;     P1_3 = 1;  } 
  delay(speedlevel);   if (turn==0)   { 
    step_index++;     if (step_index>7)       step_index=0;   } 
  else   { 
    step_index--;     if (step_index<0)       step_index=7;   } 
   } 
  改進的代碼能實現(xiàn)速度和方向的控制,而且,通過step_index靜態(tài)全局變量能“記住”步進電機的步進位置,下次調(diào)用 gorun()函數(shù)時則可直接從上次步進位置繼續(xù)轉(zhuǎn)動,從而實現(xiàn)精確步進;另外,由于利用了步進電機內(nèi)線圈之間的“中間狀態(tài)”,步進角度減小了一半,只為 9度,低速運轉(zhuǎn)也相對穩(wěn)定一些了。  
  但是,在代碼二中,步進電機的運轉(zhuǎn)控制是在主函數(shù)中,如果程序還需執(zhí)行其它任務(wù),則有可能使步進電機的運轉(zhuǎn)收到影響,另外還有其它方面的不便,總之不是很完美的控制。所以我又將代碼再次改進:  
代碼三 
#include <AT89X51.h>  
static unsigned int count;  //計數(shù) 
static int step_index;  //步進索引數(shù),值為0-7 static bit turn;  //步進電機轉(zhuǎn)動方向 
static bit stop_flag;  //步進電機停止標志 
 
 
 
 
 
 
static int speedlevel; //步進電機轉(zhuǎn)速參數(shù),數(shù)值越大速度越慢,最小值為1,速度最快 static int spcount;    //步進電機轉(zhuǎn)速參數(shù)計數(shù) 
void delay(unsigned int endcount);  //延時函數(shù),延時為endcount*0.5毫秒 void gorun();          //步進電機控制步進函數(shù) void main(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; //設(shè)定時器0和1為16位模式1  
  ET0 = 1;           //定時器0中斷允許    TH0 = 0xFE; 
  TL0 = 0x0C;   //設(shè)定時每隔0.5ms中斷一次   TR0 = 1;         //開始計數(shù)   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中斷處理   
void timeint(void) interrupt 1  {  
  TH0=0xFE; 
  TL0=0x0C; //設(shè)定時每隔0.5ms中斷一次   count++;   spcount--;   if(spcount<=0) 
 
 
 
 
 
 
  { 
    spcount = speedlevel;     gorun();   } } 
void delay(unsigned int endcount) { 
  count=0; 
  do{}while(count<endcount);  }  
void gorun()  
{  if (stop_flag==1)   { 
    P1_0 = 0;     P1_1 = 0;     P1_2 = 0;     P1_3 = 0;     return; 
  } 
  switch(step_index)   { 
  case 0: //0     P1_0 = 1;     P1_1 = 0;     P1_2 = 0;     P1_3 = 0;     break; 
  case 1: //0、1     P1_0 = 1;     P1_1 = 1;     P1_2 = 0;     P1_3 = 0;     break;   case 2: //1     P1_0 = 0;     P1_1 = 1;     P1_2 = 0;     P1_3 = 0;     break; 
  case 3: //1、2     P1_0 = 0; 
 
 
 
 
 
 
    P1_1 = 1;     P1_2 = 1;     P1_3 = 0;     break;   case 4:  //2     P1_0 = 0;     P1_1 = 0;     P1_2 = 1;     P1_3 = 0;     break; 
  case 5: //2、3     P1_0 = 0;     P1_1 = 0;     P1_2 = 1;     P1_3 = 1;     break;   case 6: //3     P1_0 = 0;     P1_1 = 0;     P1_2 = 0;     P1_3 = 1;     break; 
  case 7: //3、0     P1_0 = 1;     P1_1 = 0;     P1_2 = 0;     P1_3 = 1;   } 
  if (turn==0)   { 
    step_index++;     if (step_index>7)       step_index=0;   }   else   { 
    step_index--;     if (step_index<0)       step_index=7;   } 
   } 
  在代碼三中,我將步進電機的運轉(zhuǎn)控制放在時間中斷函數(shù)之中,這樣主函數(shù)就能很方便的加入其它任務(wù)的執(zhí)行,而對步進電機的運轉(zhuǎn)不產(chǎn)生影響。在此代碼中,不但實現(xiàn)了步進電機的轉(zhuǎn)速和轉(zhuǎn)向的控制,另外還加了一個停止的功能,呵呵,這肯定是需要的。 
 
 
 
 
 
 
 
  步進電機從靜止到高速轉(zhuǎn)動需要一個加速的過程,否則電機很容易被“卡住”,代碼一、二實現(xiàn)加速不是很方便,而在代碼三中,加速則很容易了。在此代碼中,當 轉(zhuǎn)速參數(shù)speedlevel 為2時,可以算出,此時步進電機的轉(zhuǎn)速為1500RPM,而當轉(zhuǎn)速參數(shù)speedlevel 1時,轉(zhuǎn)速為3000RPM。當步進電機停止,如果直接將speedlevel 設(shè)為1,此時步進電機將被“卡住”,而如果先把speedlevel 設(shè)為2,讓電機以1500RPM的轉(zhuǎn)速轉(zhuǎn)起來,幾秒種后,再把speedlevel 設(shè)為1,此時電機就能以3000RPM的轉(zhuǎn)速高速轉(zhuǎn)動,這就是“加速”的效果。 
 
  在此電路中,考慮到電流的緣故,我用的NPN三極管是S8050,它的電流最大可達1500mA,而在實際運轉(zhuǎn)中,我用萬用表測了一下,當轉(zhuǎn)速為 1500RPM時,步進電機的電流只有90mA左右,電機發(fā)熱量較小,當轉(zhuǎn)速為60RPM時,步進電機的電流為200mA左右,電機發(fā)熱量較大,所以 NPN三極管也可以選用9013,對于電機發(fā)熱量大的問題,可加一個10歐到20歐的限流電阻,不過這樣步進電機的功率將會變小。
關(guān)閉窗口

相關(guān)文章