字體:小 中 大 | |
|
|
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_sync=1 與 Busy_flag=1三者的條件成立時,即進入馬達相位數取得,並相對檢測OnOff_flag,Busy_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 x 3= 2.1mS 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過程略有更動內容,就不再更新,以免造成困擾,請見諒。 |
|
( 興趣嗜好|其他 ) |