|
|
抽像一點(diǎn)講,過程控制滲透在生活的各個角落。特別是在數(shù)控行業(yè),尤為明顯。早期在PLC時代,幾乎是一統(tǒng)天下。當(dāng)大小不一的控制卡公司如雨后春筍般成長起來時,控制卡在過程控制逐步體現(xiàn)出強(qiáng)勁優(yōu)勢。 其編程手段往往邦定非常成熟的編程工具,如:CB,VC,Dephi,CB。故其推廣非常迅速. 很快擁有大量客戶群。 但是,作為編程者,碰到同一程序需要控制多個同樣設(shè)備時(動作不一定同步),往往在Window多任務(wù)系統(tǒng)的影響下,很快想到多線程技術(shù),其實多線程編程對系統(tǒng)依賴性較強(qiáng),不同級別的處理,將導(dǎo)致程序的維護(hù)成本增加,并且還需要考慮線程之間的通訊,使編程起來較為麻煩。事實上,依靠過程編程的思想,會使程序獲得更簡單的做法。 純粹從編程角度來看,過程控制編程應(yīng)包含幾個要素,下面以C++偽碼方式來表示一個類,較易說明問題:
/************************** 一個動作封裝類,包含一個 設(shè)備的所有執(zhí)行動作 **************************/ class CAction { public: CAction():m_nWorkStep(-1000){} ~CAction(){} public: enum{ None, Inital, Start, Stop, Pause, Continue };//部分控制標(biāo)記
public: int Control( int nStatus, void *pParam ); //要素2: 一定可以接受外部控制 int Run( void *pParam ); //要素3: 絕對有一個不斷推動的執(zhí)行過程(這是整個過程編程的心臟所在)
public: int m_nWorkStep; //要素1: 必須有一個工作執(zhí)行步 private: void * m_pMemberData; //要素4: 可選,邦定被操作的數(shù)據(jù) // ..其它輔助變量 };
要素5:可選,為了能與外界用戶進(jìn)行溝通,Control函數(shù)與Run函數(shù),須選擇一個參數(shù),滿足用戶的輸入輸出。但由于用戶可選項太多,故古人告訴我們,萬事皆空即是成功,對于C++而言,沒有比void *類型更有前途了(若想體會,需搭配類型轉(zhuǎn)換更有潛力)。早在一年前,本人寫過一個過程控制器編程,并有成功實例,但今次版本,更有精裝之特點(diǎn)。
住下再參見一下Control函數(shù),及Run函數(shù)的一個小樣例,這將是程序員發(fā)揮強(qiáng)勁功能的場地所在。如下:
int CAction::Control( int nStatus, void *pParam ) {//此處的設(shè)計需要一點(diǎn)技巧,當(dāng)然完全取決程序員的經(jīng)驗,和對控制的理解 switch( nStatus ){ case Inital: m_pMemberData = pParam;//初始化邦定的用戶數(shù)據(jù) break; case Start: m_nWorkStep = 0; //一般令第0步作為開始較易理解 break; case Stop: m_nWorkStep = -1000;//停止 break; case …//其它略去 default: break; } return m_nWorkStep;//返回值可自定 }
int CAction::Run( void *pParam ) {//以下為一個動作不斷返回,直至接受到停止指令 switch( m_nWorkStep ){ case 0: if( IsMove() ) break; //正在忙,不執(zhí)行 Move(1600); //正向移動1600單位 m_nWorkStep++; //跳至下一步 break; case 1: if( IsMove() ) break; //正在忙,不執(zhí)行 Move(-1600); //反向移動1600單位 m_nWorkStep=0; //再回至第0步 break; case –1000: break;//停止 default: break;//此句最好有,以便于理解 } return m_nWorkStep; //返回值可自定 } 對于Run函數(shù)須謹(jǐn)記一點(diǎn):不要有長時間的循環(huán)操作,更不要有死循環(huán),否則另外設(shè)備無法正確動作,因為另外的設(shè)備Run函數(shù)無法被激活執(zhí)行,心臟無法跳動,只好等死吧! 當(dāng)然,還須擔(dān)心一點(diǎn):多個設(shè)備同時執(zhí)行時,其實時性會下降一點(diǎn),若沒有特別高的要求,在現(xiàn)今CPU狂奔的時代,以上程序框架足已滿足90%的需求,還是有學(xué)習(xí)和理解的必要吧!
以上的框架出來了,那么如何操作使設(shè)備驅(qū)動起來呢,不管在DOS亦或在Window系統(tǒng)環(huán)境里,以下的思路都一樣,參見偽代碼如下:
const int nSize=10; //定義10臺設(shè)備對象 CAction exeArray[nSize]; BOOL bRunning=FALSE;//控制整個驅(qū)動的標(biāo)志
Void OnRunAction()//啟動函數(shù) { //初始化一下 for( int i(0); i〈nSize; i++) exeArray[i].Control( CAction::Inital, ( void *)userData );//userData由用戶選擇
bRunning = true;//外部控制變量 for( i=0; bRunning; i=(i+1)%nSize)//給予運(yùn)行時間,即是驅(qū)動了 { exeArray[i].Run(( void *)userData); //不斷驅(qū)動Action設(shè)備(即激活心臟) DoEvents();//做其它事情,如系統(tǒng)消息檢測,以防止死機(jī) } }
DoEvents函數(shù)功能的詳解可參見本人的〈〈DMC1000控制卡不能響應(yīng)系統(tǒng)消息〉〉,上面有不同編程工具下的實現(xiàn)源代碼。
void OnControlAction() { for( int i(0); i〈 nSize; i++) exeArray[i].Control( Caction::(/*用戶想要的動作*/), ( void *)userData); }
void OnOver() { bRunning = FALSE;//結(jié)束驅(qū)動 }
注意:有很多程序員在不同編譯器下,需要不同的OnRunAction函數(shù)版本,以上實現(xiàn)最為簡單,但有一些較特殊。比如:在程序啟動時,就驅(qū)動所有設(shè)備,這點(diǎn)本人在VC6.0環(huán)境有過經(jīng)驗,可以分享一下,其它環(huán)境下,還需同胞們一起去努力發(fā)現(xiàn)。
還有一點(diǎn)聲明,多線程技術(shù)也不是一無是處,在花費(fèi)時間較頻繁的通訊編程方面,它的優(yōu)勢,還是有相當(dāng)?shù)恼T惑力。
|
|
狀 態(tài):
離線
公司簡介
產(chǎn)品目錄
|
|
公司名稱:
|
深圳市雷賽智能控制股份有限公司
|
聯(lián) 系 人: |
梁邦敏
|
電 話: |
755-26401178
|
傳 真: |
|
地 址: |
深圳市南山區(qū)登良路天安南油工業(yè)區(qū)2棟3樓 |
郵 編: |
518000 |
主 頁: |
|
|
|
|
|