1 引言
近年來,隨著大規模集成電路的發展,可編程控制器得到了迅速的發展,并廣泛應用于各種領域中。由于可編程控制器具有自身的通訊端口和通信協議,這就使得工業現場的實時監控和控制成為可能。所以在實際的運用中,常常采用plc作為下位控制機實現整個過程的自動控制。而微機在數據處理及人機界面方面有得天獨厚的優勢,因此采用微機為上位機來進行數據的顯示、控制參數的修改及過程的控制,這樣就不得不解決上位管理機與下位控制機之間的通訊問題。
由于串行通訊具有線路簡單、應用靈活、可靠性高等優點,并且普通微機上均都帶有串口,便于實現,所以微機與plc之間常采用串行異步通訊。vc具有面向對象的設計方法、簡單方便的串行通訊和實用性強等優點,無需借用其他語言就可以開發出優秀的控制系統通訊軟件。本文重點就是介紹在windows98環境下如何利用vc來實現pc機與永宏plc之間的串行通訊。并以實際控制系統“半自動化燈檢機”為例加以說明。
2 控制系統簡介
半自動化燈檢機系統的主要工藝流程:供瓶機供瓶→進瓶輸送帶送瓶→氣缸放瓶→主傳動履帶式置瓶棍移送瓶→進入高速旋轉工位旋瓶→進入低速旋轉工位慢速旋瓶(同時也就進入燈檢工位)→至出瓶輸送帶送瓶→進入剔除工位分瓶(由電磁閥來控制氣缸動作)。下位機主要采用永宏plc完成現場的狀態檢測與控制。上位機則用一般的微機,通過rs-232與plc通信接受現場狀態的顯示并加以控制生產過程。電機的運轉通過plc控制,而電機的升降速則由變頻器調節。因此本系統軟件需要完成的主要任務是:從plc,變頻器循環接受現場的狀態,并根據不同的狀態控制變頻器及電機的運轉。主要的界面有:監控畫面,密碼設置,參數設置和報警畫面等。其中監控畫面設有:操作按鈕,如停止,啟動及產品合格數的實時顯示。畫面中的每一個按鈕或狀態顯示都需要上位機與下位機的通信來完成。
3 永宏plc的通訊格式
整個通訊采用上位機主動發送和接收的方式,plc內部不需要特定的梯形圖編程來做下位機通訊程序。
3.1 通訊格式
計算機與永宏fb系列plc通訊必須遵從fb-plc通訊協議。無論是上位機發出的命令信息格式還是下位機發出的回應信息格式均可分為6個資料位,如圖1所示。

(1) 起始字元(stx):ascii碼的起始字元stx對應的16進制數為02h。無論命令信息還是回應信息,它們的起始字元均為stx,接收方以此來判知傳輸資料的開始。
(2) 從機站號:為兩位16進制數。fb-plc的站號是什么,這個值就是多少。因為fb-plc的站號可以為1-255,所以這個值的范圍為01h-ffh。
(3) 命令號碼:為兩位16進制數。所謂命令號碼是指上位機要求下位機所執行的動作類別,例如要求讀取或寫入單點狀態、寫入或讀取暫存器資料、強制設定、運行、停止等等。在回應信息中,下位機會將從上位機接收到的命令號碼原原本本的隨同其它信息一同發送給上位機。
(4) 本文資料:可為0(無本文資料)-500個ascii字元。在命令信息中,此信息用于指定命令所要運作或存取的對象及要寫入的數值。如果通訊正確,那么在回應信息中此欄為0(30h)和從上位機接收到的本文資料;如果通訊異常,那么為錯誤碼。
(5) 校驗碼(checksum):校驗碼是將1-4各欄的所有ascii字元的16進制數值以“lrc(longitudinal redundancy check)”法計算出1個byte長度(兩個16進制數值00-ffh)的校驗碼。當下位機接收到信息后,用同樣的方法計算出接收信息的校驗碼,如果兩個校驗碼相同,則說明傳送正。
(6) 結束字元(etx):ascii碼的結束字元etx對應的16進制數為03h。無論命令信息還是回應信息,他們的結束字元均為etx,接收方以此來判知此次通訊已結束。
3.2 通訊命令
永宏系列plc有多種命令字,常用的幾種描述如附表所示。例如,上位機要讀取plc內部繼電器m1和m2的狀態,則上位機發送的命令字符串格式為:
起始符(02h)+站號(01)+命令字(44)+個數(02)+起始地址(0001)+校驗碼(3b)+結束符
相應下位機響應的字符串為:
起始符(02h)+站號(01)+命令字(44)+錯誤碼(0)+m0,m1狀態(10)+校驗碼(5c)+結束符若要對字元件進行寫操作,那么命令碼改為47。表明該指令要向plc內部寄存器寫入數據,同時要給出寫入的數據個數、開始寄存器和數據內容。
校驗和在信息幀的尾部,用來判斷傳輸的正確與否。當數據從信息源出發,由于信道總是有一定的噪聲存在,在信號達到信宿之前會與噪聲發生疊加,使接收端收到的二進制數位和發送端實際發送的二進制數位不一致,因而產生差錯。進行差錯檢驗的方法很多,常用的有奇偶校驗碼,水平垂直冗余校驗lrc,目前廣泛使用的是lrc校驗碼,它可以查出99%以上18位或更長的突出錯誤,因而在計算機與plc進行點對點的短程通訊時,采用這種校驗方法出錯的幾率較小。plc接收到計算機發送的命令后,如果沒有錯誤,plc會發出確認碼“0”;若有錯誤,plc會發出錯誤代碼“1”。

4 軟件編程
軟件編程采用微軟的vc++6.0作為開發工具。系統主監控畫面要求不斷掃描下位機的信號的通斷狀態,以及讀取plc的內部存取單元加以顯示。此外手動按鈕可以直接控制,由此主程序結構流程圖如圖2所示。

為了確保通信的成功,在pc機和永宏plc之間開始數據傳送前,常采用握手通訊的方法,即pc機發送特征字符,下位機接收并回送同一特征字符,由pc機進行檢測正確后開始數據傳送,以保證串行通訊數據的可靠。此外在通訊過程中,常因某些原因不能保證每次通訊成功,遇到這種情況,不能簡單地宣布通訊失敗,本程序設置了通訊重復次數計數器,只有在規定次數后握手通訊仍未完成時,才宣布通訊失敗,從而大大提高了通訊的成功率和系統的容錯能力。另外,程序中應用定時器對通訊時間加以限制,以免發生死鎖情況。定時器的打開和關閉由程序進行控制。握手通訊成功后,設置握手連接成功標志位,這樣,pc機和永宏plc之間就可以開始數據傳送。握手通訊程序如下:
void cscommplcdlg::onscommstart()
{ m_mscomm.setcommport(1); file://選擇com1
m_mscomm.setportopen(true); file://打開串口
m_mscomm.setsettings("9600,e,7,1");
file://波特率9600,偶校驗,7個數據位,1個停止位
m_mscomm.setinputmode(1);
file://1:表示以二進制方式檢取數據
m_mscomm.setrthreshold(1); file://參數1表示每 file://當收到一只字符時引發一個接收數據的oncomm事件
m_mscomm.setinputlen(0); file://設置當前接收區 file://數據長度為0
cstring sendstr="";//設置要發送的字符串
sendstr+=0x02;
sendstr+="014eabcdefgb8";
sendstr+=0x03;
m_mscomm.setoutput(colevariant(sendstr));
file://發送數據
char sendcount=0;
while(m_mscomm.getinbuffercount==0)
{ sendcount+=1;
if(sendcount<10)
m_mscomm.setoutput(colevariant(sendstr)); file://再次發送數據
else
afxmessagebox("communication fail!"); return; }
variant data;
char s;
char *recstr=&s;
short l=m_mscomm.getinbuffercount();
if(l>0)
{ data=m_mscomm.getinput();
recstr=(char *)(unsigned char *)data.parray->pvdata;
if(strcmp(sendstr,recstr)==0)
{ linksuccess=1; file://設置連接成功標志
m_timer=settimer(1,1000,null);
file://開啟定時器
}
}
}
4.1 實時數據監控的實現
在本系統的主監控畫面上,如圖3所示。要求實時監控現實合格產品數。在下位機plc程序中,每當合格產品經過特定傳動待時,光電開關便感應信號,plc對此信號計數,存放于一內存單元。上位機就要定時不斷讀取此單元內容顯示。

程序代碼如下:
void cscommplcdlg::ontimer(uint nidevent)
{ cstring sendstr="";//設置要發送的字符串
sendstr+=0x02;
sendstr+="014601r0001273";
sendstr+=0x03;
m_mscomm.setoutput(colevariant(sendstr));//發送數據
sleep(50);
variant data;
char s;
char *recstr=&s;
short recdata=0;
short l=m_mscomm.getinbuffercount();
if(l>0)
{ data=m_mscomm.getinput();
recstr=(char *)(unsigned char *)data.parray->pvdata;
recstr[l]=`