網路城邦
上一篇 回創作列表 下一篇  字體:
8051單軸馬達微控器 — 開發程式說明一
2015/03/04 07:00:09瀏覽1182|回應0|推薦0

單軸馬達微控器 — 開發程式說明一

 

壹,前言

經過數日努力,總算將"單軸馬達微控器"的程式初步完成第一階段的撰寫,此階段主要在撰寫微控器的主副程式,然而因為程式共達405條,因此將分為數個篇幅來解說,首先解說的部份有程式的變數宣告與最重要的TIMER0中斷副程式(即馬達運轉副程式),在此先行說明,為了開發時方便檢視程式運作的種種訊息,此階段的程式中包含了LCM顯示器的連接,而後將來如果商品化時,可再將LCM顯示器移除,如此可以一方面可以降低微控器的成本,同時亦可減少微控器的程式碼,來適合小包裝89C2051 SOP—20PIN的場合,所以宣告中的P0與P2的定義都是將來可移除的項目,而在初步此階段的開發中,仍使用89C52包裝進行之。

 

    以下是變數宣告的程式碼:

/*-----------------------------------------------

  名稱:單軸步進式馬達

  編寫:PETER YANG

  日期:2015.03.02

  內容:使用89C52設計一個獨立單軸步進馬達控制器,

        外部只需傳送一組數據,就可驅動步進馬達進行動作,

包括正反轉,速度快慢,與驅動馬達步進數同時輸出正反轉,快慢,忙祿與啟動的狀態

               

P0^0~P0^7   => J3                      LCM DATAPORT

P1^4~P0^7   => J42                     步進馬達四向輸出信號

P1^0        =>     ON/OFF FLAG         步進馬達ON/OFF旗號

P1^1        =>     BUZY FLAG           步進馬達BUZY旗號

P1^2        =>     FAST/SLOW FLAG      步進馬達FLAS/SLOW旗號

P1^3        =>     FOR/REV FLAG        步進馬達FORWARD/REVWARD旗號

P2^0        => NC                  

P2^1        => NC

P2^2        => NC          

P2^3        => NC

P2^4        =>     LCM RS              LCM RS控制信號

P2^5        =>     LCM RW              LCM RW控制信號

P2^6        =>     LCM EN              LCM EN控制信號

P2^7        => NC    

P3^0        =>     RXD                 USB RXD

P3^1        =>     TXD                 USB TXD

P3^2        =>     INTR0               緊急停止按鈕鍵

P3^3        =>     INTR1               HOME位置信號

P3^4        =>     T0                  SYNC信號

P3^5        =>     T1                  SENSOR INPUT

P3^7        =>     LIMIT               LIMIT信號

 

INTERRUPT#      FUNCTION

    0           緊急按鈕鍵中斷

    1           TIMER_0中斷

    2           HOME SENSOR中斷

    3           TIMER_1中斷,SENSOR COUNT

    4           UART中斷

    5           TIMER_2

------------------------------------------------*/

#include

#include

#include

#include <1602.c>

#include "1602.h"

 

#define DataPort P0     //定義資料埠

 

sbit A1 =          P1^4;     //步進馬達A相位

sbit B1 =          P1^5;    //步進馬達B相位

sbit C1 =          P1^6;    //步進馬達C相位

sbit D1 =          P1^7;    //步進馬達D相位

sbit OnOff_Flag =  P1^0;    //步進馬達ON/OFF旗號

sbit Busy_Flag =   P1^1;    //步進馬達BUZY旗號系統忙碌旗號   

sbit FstSlw_Flag = P1^2;    //步進馬達FAST/SLOW旗號

sbit FR_Flag =     P1^3;    //步進馬達正反轉旗號

//sbit triger=     P2^0;    //(預留做為DEBUG用)

sbit USB_rxd =     P3^0;    //USB RXD

sbit USB_txd =     P3^1;    //USB TXD

sbit M_stop =      P3^2;    //外部緊急鈕停機信號

sbit M_home =      P3^3;    //外部強制馬達至原點信號

sbit M_sync =      P3^4;    //外部馬達同步信號

sbit M_sensor =    P3^5;    //外部步進SENSOR信號

sbit M_limit =     P3^7;    //外部馬達限制位置信號

 

 

#define Coil_0 {A1=0;B1=0;C1=0;D1=0;}//全部斷電

#define MSB_reload_value 0x255 /* TIMER2 msb reload value exemple */

#define LSB_reload_value 0x255 /* TIMER2 lsb reload value exemple */

 

unsigned char Coil_tab[4] = {0x11,0x22,0x44,0x88};    //步進馬達相位

unsigned char Speed=4;        //設定轉速為4

unsigned short timesx,SensorCnt;

unsigned short timesy,timesz;

unsigned char temp[20];

 

bit OnOff_flag;         //ON_OFF旗號

bit Busy_flag;          //BUSY旗號

bit FR_flag;            //正反轉旗號

bit Home_flag;          //HOME旗號

bit Sensor_flag;        //SENSOR旗號

bit Msg_flag;            //訊息旗號

int Err_flag;            //ERR旗號

 

void Init_Timer0(void);              //TIMER0 起啟副程式

void UART_Init(void);                //UART 起啟副程式

void SendByte(unsigned char dat);   //發送一個BYTE至UART

void SendStr(unsigned char *s);        //發送一個字串至UART

void ISR_INT0(void);             //外部中斷 – 緊急停機按鍵

void Timer2_isr(void);               //內部TIMER2 – 定時檢知外部SENSOR狀態

void DispScreen(void);               //LCM顯示副程式

void Disp_Sensor(void);              //顯示SENSOR狀態副程式

void FunChar(void);                  //指令服務副程式

 

#define Rcv_Buf_Size 9               // Receive Buffer Size. (0 – 8)

#define row2 20                      //定義位數20

bit Rcv_Get = 0;                  //UART接收旗號

 

 

unsigned char xdata Rcv_Buf_Index = 0;              //UART接收指標

unsigned char xdata Rcv_Buf[Rcv_Buf_Size] = {0};    // Receive_Buffer.

 

unsigned char *Err_Table0,*Err_Table1,*Err_Table2,*Err_Table3,*Err_Table4,*Err_Table5,*Err_Table6,*Err_Table7,*Err_Table8,*Err_Table9;    //訊息字幕

unsigned char *Clearn;                           

unsigned char code numtab[10] = {'0','1','2','3','4','5','6','7','8','9'};

 

貳,TIMER0中斷副程式(即馬達運轉副程式)

此副程式是此微控器的核心程式,主要負責當微控器接收到主機傳送的各項指令後,當TIMER0中斷發生時,而OnOff_flag=1,M_sync1 Busy_flag=1三者的條件成立時,即進入馬達相位數取得,並相對檢測OnOff_flagBusy_flag FstSlw_Flag FR_flag等四個旗號,整合後送至P1,在程式設計上,為了顧及馬達初步啟動時,馬達力矩需有比較大的力量,在步進數小於64以內時,會用減速方式來運轉,而當步進數大於64時,就會全部由主機傳送指令中的SPEED值來運轉,而當馬達運轉之最後階段時,為了減少馬達在全速運轉下,所產生的慣性,形成馬達要停止時,而產生有慣性力衝出而造成MISS—STEP現象,程式中亦設計了減速的動作,就是當timesx的數值小於128~64之間時,馬達速度會用30值來動作,再當timesx的數值又低於64時,會再減速至40值,讓馬達的速度減慢,同樣的因為馬達每一減速的步進脈沖時序較長,也會讓馬達的力矩增加,而達到剎車之作用,雖然讓馬達在減速時,會犧牲了一點時間,但是卻可以增加馬達運作的穩定性,目前程式中設定的步進脈沖時序寬度如下

        TIMER0中斷參數是0.7mS

        SPEED之最小設定是3

        所以0.7mS 3= 2.1mS
        SPEED
之最大設定是19

0.7mS x 19 = 13.3 mS

另外是當整個步進數完成運作後,會將Rcv_Buf[0]的指令碼改為"Z"字,而且將目前微控器已完成的timesy步進數轉換成字串,並放置於Rcv_Buf[1]~ Rcv_Buf[5]中,而SPEED也亦同轉換為字串置於Rcv_Buf[6]~ Rcv_Buf[7],如此一個八位元字串,而後可以由UART回送至主機報告微控器目前之狀態,再者是如果在馬達運作期間,如果主機送來M_sync是處於LOW狀態,則表示主機要求各微控器"同步"運轉的信號,所以在副程式中最後會判斷M_sync的信號,因此當M_sync處於LOW時,馬達會"暫時"停止計轉,而當M_sync處於HIGH時,馬達會持續未完成的工作,而當馬達處於SYNC狀態時,也會將Rcv_Buf[0]=0x59為"Y"字元,Err_flag=8訊息會同時顯示等待同步信號的字幕,這就是TIMER0中斷副程式碼的幾個工作重點。

以下是TIMER0中斷副程式碼

/*------------------------------------------------

        TIMER 0 INTERRUPT 1

------------------------------------------------*/

void Timer0_isr(void) interrupt 1

{

    static unsigned char times,k,x;

    TH0=(65536-700)/256;            //重新賦值 0.7ms

    TL0=(65536-700)%256;

    if(timesz<=64) fstslw_flag="1;<span" style="mso-tab-count: 1;" data-mce-style="mso-tab-count: 1;">  //馬達剛啟動進行減速,以增加馬達力矩

    if(OnOff_flag==1 && M_sync==1 && Busy_flag==1)    //條件

    {    Err_flag=10;                //設定顯示訊息為忙碌中

        if(times==(Speed+(((int)FstSlw_Flag)*10)))    //速度基數=3~19

        {  

            times=0;                //重置速度設定率數

            if(FR_flag==0)          //偵測正反轉旗號,FrFlag=0時為正轉

            {   timesy++;    }      //正轉時,現行步數加一

            else

            {   timesy--;    }      //反轉時,現行步數減一

            k=timesy%4;             //將現行步數除4,以取得馬達對應相數

            x=(Coil_tab[k] & 0xf0);  //

            if (OnOff_flag!=0) x=x & 0xfe;   //檢知OnOff_flag旗號

            else x=x | 0x01;

            if (Busy_flag!=0) x=x & 0xfb;    //檢知Busy_flag旗號

            else x=x | 0x02;

            if (FstSlw_Flag==0) x=x & 0xfd;   //檢知FstSlw_Flag旗號

            else x=x | 0x04;

            if (FR_flag==0) x=x & 0xf7;     //檢知FR_flag旗號

            else x=x | 0x08;                        

            P1=x;                   //送出馬達相數與旗號

            timesx--;timesz++;              //步進數減一次

        }

        if (timesx>=128) {FstSlw_Flag=0;}    //如果大於128步進數時,使用指定速度

        else    {    FstSlw_Flag=1;  }       //否則進行減速

        if (timesx<128) speed="30;<span" style="mso-tab-count: 1;" data-mce-style="mso-tab-count: 1;">           //步進小於128個時,設定速度為30

            else {     if(timesx<64) speed="40;<span" style="mso-tab-count: 1;" data-mce-style="mso-tab-count: 1;">  }    //步進再小於64個時,設定速度為40     

        times++;

        if(timesx<=0) span="" style="mso-tab-count: 2;" data-mce-style="mso-tab-count: 2;">                       //如步進數為0時,

        {    Rcv_Buf[0]=0x5a;                //”Z”字元

            Rcv_Buf[1]=numtab[timesy/10000];        //進行將TIMESY轉換為字串

            Rcv_Buf[2]=numtab[((timesy-(timesy/10000)*10000))/1000];

            Rcv_Buf[3]=numtab[((timesy-(timesy/1000)*1000))/100];

            Rcv_Buf[4]=numtab[((timesy-(timesy/100)*100))/10];

            Rcv_Buf[5]=numtab[((timesy-(timesy/10)*10))%10];

            Rcv_Buf[6]=numtab[Speed/10];            //進行將SPEED轉換為字串

            Rcv_Buf[7]=numtab[Speed%10];

            OnOff_flag=0;   }               //停止步進馬達

    }

    if(M_sync==0) {    Rcv_Buf[0]=0x59;Err_flag=8; }    //如外部同步信號為LOW時

}                                                                                                       //設定訊息為等待SYNC信號

/*------------------------------------------------

        TIMER-0  INIT (提供給步進馬達)

------------------------------------------------*/

void Init_Timer0(void)

{

    TMOD |= 0x01;   //使用模式1,16位元計時器,使用"|"符號可以在使用多個計時器時不受影響          

// TH0=0x00;        //給定初值

//    TL0=0x00;

//  EA=1;           //總中斷打開

    ET0=1;          //計時器中斷打開

 

    TR0=1;          //計時器開關打開

    PT0=1;          //優先順序打開

}

 

參,結論

上面只是將程式變數宣告與TIMER0中斷副程式的程式碼進行解說,因為篇幅大小的限制,先行就此部份公開分享,而後會再就其他主程式與各副程式再撰文說明,請各位同好能予體諒未一次全數公開,之前已有分享之文章,因為在整個開發與DEBUG過程略有更動內容,就不再更新,以免造成困擾,請見諒。

( 興趣嗜好其他 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=PYANG&aid=21261115