林 濤 張聲興
摘要:文章介紹了可編程控制器(PCL)與上位機(PC機)實現串行通信功能的硬件組成、通信協議,重點闡明在上位機(PC機)上基于VC++6.0的編程實現細節,并進一步展望PLC對控制系統應用的前景。
關鍵詞:可編程控制器(PCL);VC++
中圖分類號:TP312文獻標識碼:A文章編號:1006-8937(2009)08-0112-02
鑒于目前由可編程控制器(PCL)和PC機所構成的監控系統在工業控制領域得以廣泛的運用,文章將對PCL作下位機,完成現場設備的直接控制、數據收集等工作,PC機作上位機,完成數據的分析存儲、狀態顯示等工作進行技術探討,通過上位機對PLC的讀寫操作,從而完成現場數據的接收、傳達與監控功能。文章以OMRON公司的CJ1G型PLC作下位機,以PC機為上位機,重點研究此分布式控制系統的通訊方式。
1硬件互聯技術細節
1.1PLC與PC的硬件互聯
經過對該品牌PLC的分析,可知PLC本身配有RS-232接口,大大方便了與PC機串口通信的硬件連接,文章直接采用自制電纜將PLC的RS-232口與PC機RS-232口相連,引腳對應關系圖如圖1:
1.2設定PLC通信方式,確定通信協議幀
CJ系列PLC單元支持以下5種串行通信功能:上位機鏈接通信、無協議通信、1:N或1:1鏈接通信、外設總線通信和串行PLC鏈接通信,其中上位機鏈接通信功能適用于上下位機并以會話的方式進行實時數據通信。
一般在控制系統中,采用單臺PLC與PC機通信,上位機擔當命令發起端,通過向PLC發送不同格式的命令幀,完成對PLC寄存器的讀寫操作。因此文章選擇主機-->PLC的主鏈接命令通信方式。

該系統使用RS一232C端口進行通信。RS一232C端口的缺省設定是:上位機鏈接模式、1啟動位、7數據位、偶校驗、2停止位和9 600bps的波特率。用戶可以通過編程工具或者SETUP(237)指令改變RS一232C端口的設定。我們首先用編程工具對PLC進行設置,其中PLC的操作模式設定為監控模式;然后斷開電源,將主機與PLC的CPU單元連接,并將CPU單元DIP的引腳5設定為OFF;最后接通電源,從主機發布主鏈接命令,進行上下位機的通信。
由于整個通信系統采用上位機主動的通信方式。上位機與PLC的通信是通過使用命令幀(command)和響應幀(response)進行數據的發送和接收。幀的發送與接收圖2所示:

命令的格式如圖3所示,命令必須以@開始,機號No為2個十進制數,表示上位機識別所連接PLC的機號。識別碼是2個字符的命令碼,如RR表示讀取CIO區域的內容。正文部分為設定命令的參數,對于不同的命令,正文的內容和長度可能有所不同。FCS是2個字符的幀檢查序列。命令的最后2個字符是終端,表示命令的結束,由“*”和CR碼組成。命令格式圖3所示:
圖3 命令格式

響應的格式與命令的格式相似,只是在識別碼后面多了2個十六進制字符的結束碼,用于返回命令的執行狀態(有無錯誤及錯誤的原因)。一個幀最多由131個ACSⅡ字符組成,如果需要發送的字符超出131個,必須將數據分成若干個幀,第一幀和中間幀的結尾用分界符(CR)代替結束符(*CR)。
VC++6.0軟件實現VC++6.0開發環境為串口通訊已經提供了ActiveX控件,名為MSComm控件。下面闡述對該控件屬性的初始化設置以及相關實現代碼。限于篇幅,此文只將重要的實現代碼羅列如下:
{
My_Comm.SetCommPort(1);//選擇 COM1口
My_Comm.SetSettings( 9600,E,7,1 );//設置通信參數
My_Comm.SetlnputMode(1);//設置二進制輸入模式
My_Comm.SetInBufferSize(1024);//設置輸入緩沖區大小
My_Comm.SetlnputLen(0);//使用Input將使MSComm控件讀取接收緩沖區中的全部內容
My_Comm.SetOutBufferSize(1024);//設置輸出緩沖區大小
My_Comm.SetRThreshold(1);//設置每接收一個字符觸發一次OnComm事件
My_Comm.SetDTREnable(TRUE);//置DTR有效
int timeRes;
if(!My_Comm.GetPortOpen()) //如果沒有開
My_Comm.SetPortOpen(TRUE);//手工打開串口
My_Comm.Getlnput();//清空輸入緩沖區
timeRes=SetTimer(2,500,NULL);//安裝定時器
if(timeRes==0)
{
MessageBox( “設置定時器出錯” );
return ;
}
}
主要實現代碼處于在WM_TIMER消息的處理函數上
void CPLCCommDlg::OnTimer(UINT nlDEvent)
{
int len;
long j;
VARIANT inputdatal:
COleSafeArray inputdata2;
BYTE datatempl,datatemp2;
BYTE commstr[17]={ ‘@ ,0,‘0,R,D,0, 0, 0, 0, 0, 0, 0,2,0x00,0x00,*,0x0d}
//初始化命令參數
My_Comm.SetRTSEnable(TRUE);//設置RTS線有效,請求允許發送數據
verifcation(commstr,17);//對發送的命令進行幀校驗
CByteArray cbaArraylnsA;
cbaArraylnsA.RemoveAll();
for(int nlndex:0;nlndex<17;++nlndex)
{
cbaArraylnsA.Add(commstr[nIndex]);
}
My_Comm.SetOutput(COleVariant(cbaArraylnsA));//發送讀取數據的命令
My_Comm.SetRTSEnable(FALSE);//設置RTS線無效,不允許發送數據
inputdatal= My_Comm.Getlnput();//讀取接收緩沖區的數據
inputdata2=inputdatal;
len=inputdata2.GetOneDimSize();
for(j=0;j { inputdata2.GetElement(&j,inputdata+j); } datatempl=inputdata[15]; datatemp2=inputdata[16]; verfunction(inputdata,19);//計算接收數據的幀校驗碼 if(datatempl! = inputdata [15] || datatemp2 1=inputdata[16]) { MessageBox(”Receive data invalid! );//判斷接收數據是否有效 } else { for(i=0;j<8;j++) { OutputData[j]=inputdata[j+7];//將數據存儲到上位機的數據存儲區中 } } incount=0; CDialog::OnTimer(nlDEvent); } 上述函數所調用的對幀進行校驗的函數verifcation代碼如下: CPLCCommDlg::verfunction(BYTE vdata[],int K) { BYTE sum=0x00,vl=0x0f, v2=0xf0; for(int i=0;i { sum^=vdata[i]; } V1& =sum; V2& =sum; v2> > =4; if(vl>=0&& vl<=9) V1+ =0x30; else V1+ =0x37; if(v2>=0&& v2<=9) V2+ =0x30; else V2+=0x37; vdata[K-3]=vl;//幀貞校驗碼低位字節 vdata[K-4]=v2;//幀校驗碼高位字節 } 2結語 采用這種方法開發出了上位機與PCL的通信系統,實現了上位機和PLC的數據交換功能。文章嘗試為一般化控制系統提供統一通信控制框架,這也是下一步研究方向,希望通過此類努力為硬件通訊提供一個方便調用的軟件接口,從而降低開發難度,提供開發效率。