燕科帆,朱厚耀,林賀邦,李嘉龍
(廣州大學機械與電氣工程學院,廣東廣州 510006)
在整個上位機軟件的開發過程里面,最重要的部分是上位機對于下位機的數據監測,這就要解決二者之間的通信問題,實現穩定的通信才能穩定地進行數據監測和數據交換。傳統的通信方法是采用RS-232C或者RS-485串行方式,但是隨著對于傳輸數據量、設備之間的傳輸距離以及通信的實時性要求越來越高,傳統的串行通信方式慢慢的不能滿足大部分企業的要求[1]。同時,由于國際上現場總線的標準非常多,導致難以實現控制系統集成的統一。所以國際上大部分廠商開始將生產的PLC與以太網技術進行結合,PLC控制器與基于TCP∕IP的以太網結合,可以實現開放、分散的工業控制系統,按照相關的協議就可以進行PLC與計算機的通訊[2]。
AC500系列是ABB公司新一代的模塊式可編程控制器,是一款可升級的,靈活的自動化控制系統。系統的構建采用底板組合模塊的結構。硬件上可選用的模塊有CPU模塊和底板、I∕O模塊和底板、FBP總線適配器和底板以及通訊模塊等,以上的各種模塊均有許多型號,每種型號對應的配置都不一樣,可以根據實際的需求選型。不同的CPU模塊插在CPU底板上,不同的I∕O模塊插在I∕O底板上,直接拼接在CPU底板的右側,通過I∕O總線進行數據交換,其他的模塊也是采用拼接的方法插在底板上,示例如圖1所示。通訊模塊有四種型號,分別是CM572-DP:PROFIBUSDP主站通訊模塊、CM575-DN:DeviceNet主站通訊模塊、CM577-ETH:以太網通訊模塊、CM578-CN:CANopen主站通訊模塊。
以太網通訊模塊支持的協議包括TCP∕IP、UDP∕IP和Modbus TCP。其中本文的通訊采用基于Modbus TCP協議的以太網通訊,AC500的以太網通訊模塊集成了“MOD?BUSon TCP∕IP”協議,所以可以通過Ethernet(以太網)進行MODBUS通訊[3]。

圖1 AC500系列PLC硬件組成
Modbus通信協議是全球最早用于工業現場的總線規約,由Modicon公司在1979年發明。由于免費發布,并且采用主從通信模式(Master∕Slave通信模式),在分散控制方面應用廣泛,從而在全球得到了廣泛的應用。Modbus通信協議具有串口和以太網多種版本,其中比較著名的是Modbus RTU、Modbus ASCII和 Modbus∕TCP 三種。其中Modbus∕TCP協議是通過一種簡單的方式將Modbus幀嵌入到TCP幀中而形成的,由于TCP是基于可靠連接的服務,所以在Modbus TCP協議中沒有CRC校驗碼,從而簡化了協議的內容。
Modbus∕TCP數據幀的組成簡單分成三個部分,分別是報文頭、功能代碼和數據。如圖2所示。

圖2 Modbus∕TCP數據幀
MBAP報文頭分為四個域,一共七個字節。1、2字節是傳輸標志,標志某個Modbus詢問∕應答的傳輸;3、4字節是協議標志,表示協議的種類;5、6字節是長度,表示后續字節的長度計數;7字節是單元標志。
功能代碼共有三種類型,分別是公共功能代碼、用戶自定義功能代碼和保留的功能代碼。本文所用到的為公共功能代碼,分別是十進制的03(讀多個寄存器)和十進制的16(寫多個寄存器)。其余的常見公共功能代碼見表1所示[4]。
MFC(Microsoft Foundation Classes)是微軟基礎類庫,是一個C++的類庫,封裝了大部分windows API函數。它提供了兩個類,這兩個類都封裝了socket,分別是CAsync?Socket和CSocket,CSocket是CAsyncSocket子類,二者的區別在于CAsyncSocket是異步套接字,而CSocket是同步套接字。
使用MFC的socket類可以從這兩個socket類中繼承出自己的socket類,再根據需求增加所繼承的socket類功能。如果需要使用這兩個socket類,一定要從這兩個類中繼承出自己的socket類,通過修改虛函數來實現特定基本功能。有了這兩個類就可以方便的處理同步與異步問題。
本文采用的是CSocket類,需要實現的功能是讀寫數據,因此需要用到的虛函數為OnReceive(),需要對該虛函數進行重載。當有一個socket向CSocket繼承類發送數據的時候,CSocket繼承類的OnReceive()虛函數會被自動執行,因此接收數據可以在OnReceive()虛函數里通過定義的Receive()函數來實現。
Socket通信采用的模式為客戶端和服務器,本文開發的軟件為客戶端,PLC為服務器。通過服務器的IP地址和ModbusTCP固定的502端口,就能進行客戶端和服務器端的連接,連接后就能進行以太網數據通訊。因此按照socket通信流程,利用CSocket類的成員函數實現通信流程中的各個步驟就能進行通訊[5]。Socket通信流程如圖3所示。
當需要進行上位機與PLC以太網通訊時,需要先進行PLC的硬件系統配置。本系統選用的CPU型號為PM583,串口型號為DC532。該CPU自帶以太網通訊口。系統配置的步驟如下。
(1)打開ABB配套的系統組態軟件Control builder Plus,新建AC500工程,按照硬件系統的配置在軟件中對應進行添加,比如串口模塊,通信模塊等等,如圖4所示。

圖3 CSocket實現Modbus∕TCP通訊流程圖

圖4 系統組態樹狀圖
(2)按照步驟(1)中添加的模塊,分別進行參數配置,例如CPU模塊,雙擊CPU模塊進行參數配置,本系統默認參數均能滿足要求。同理對I∕O模塊進行參數配置。
(3)將電腦和PLC通過網線連接,PLC上電,通過圖4中的IP_Settings(IP設置)設置PLC的IP地址。
(4)上位機軟件開發好后,將PC機的IP地址設置成和PLC同一個網段,這樣就完成整個系統的硬件和軟件的配置過程[6]。
本程序采用VS2013IDE編程環境,創建基于對話框的MFC程序。因為需要用到CSocket類,所以必須在導向中勾選Windows套接字選項。在界面輸入服務器地址和端口號就能進行通訊連接。以下是程序的創建步驟和部分代碼。
(1)創建基于對話框的MFC程序,勾選Windows套接字選項。
(2)在對話框中加入所需的各種控件,比如IP地址輸入框等等,并對各個控件添加變量。
(3)創建一個繼承自CSocket類的MFC類,命名My?Socket,用來進行socket通信。對MySocket類的虛函數進行重載,在OnReceive()函數體里面調用Receive()函數,從而起到接收數據的作用。
(4)添加兩個按鈕控件,分別取名為讀取數據和修改數據。二者的作用是對PLC進行數據讀取和修改,將相關的代碼都封裝到這兩個按鈕控件里面。
以下列出部分相關代碼。
void CMysocket::OnReceive(int nErrorCode)∕對 MySock?et類虛函數進行重載
{
if(pClientdlg)
{
pClientdlg->Receive();∕調用主對話框的 Re?ceive方法接收數據
}
CSocket::OnReceive(nErrorCode);
}
以下為通訊連接部分程序代碼:
pMysocket=new CMysocket(this);∕創建套接字對象
if(pMysocket->Create()==FALSE)∕創建套接字
{
deletepMysocket;
pMysocket=NULL;
AfxMessageBox(_T("套接字創建失敗!"));
return;
}
if(pMysocket->Connect(servername,port)==FALSE)∕連接服務器、connect函數成功則返回1,失敗則返回0
{
AfxMessageBox(_T("連接服務器失敗!"));
return;
}
對PLC進行數據讀取需要用到功能碼03,首先需要定義一個數組來存放讀取數據的數據包:
unsigned char Send[12]={0};∕生成 Modbus∕TCP 格式數據包
讀取數據是對PLC的寄存器進行讀取,所以對于寄存器的起始地址和寄存器的數量是需要確定的[7]。下面為整個數組的定義:
Send[0]=m_1;
Send[1]=m_2;∕事務元標識符,高字節在前,低字節在后
Send[2]=m_3;
Send[3]=m_4;∕協議標識符,高字節在前,低字節在后
Send[4]=0x00;
Send[5]=0x06;∕后續字節長度,高字節在前,低字節在后
Send[6]=m_5;∕單元標識符
Send[7]=0x03;∕功能碼,讀多個寄存器
Send[8]=m_register_address_high;∕數據起始地址,高字節在前,低字節在后
Send[9]=m_register_address_low;
Send[10]=m_register_number_high;∕數據長度,高字節在前,低字節在后
Send[11]=m_register_number_low;
int a=pMysocket->Send(Send,12);∕Send 函數返回的是成功發送的字節數
用MySocket類的指針對象調用Send()函數就能數據包發送出去。當包含讀取多個寄存器功能碼的數據包發送給PLC后,PLC會立即返回對應的數據給通訊軟件,這時會觸發OnReceive()函數,從而觸發接受數據函數Re?ceive()。在Receive()函數體里面同樣定義一個數組用來存放PLC反饋回來的數據,部分程序如下所示:
unsigned char Receive[200];∕接收反饋的數據
int receive_data_num = pMysocket->Receive(Receive,200);∕Receive()函數的返回值為所接收到的字節數量。
如圖5所示為讀取數據圖。

圖5 讀取PLC數據
對PLC寫值和讀取PLC數據的內容大致是一樣的,只需要修改功能代碼并且加入需要寫入的值即可。本軟件目前固定一次可以寫三個寄存器。以下所示為對PLC寫值的定義方法。m_value1、m_value2、m_value3為三個需要寫入的值,可以從界面輸入。
Send[13]=m_value1∕256;
Send[14]=m_value1%256;
Send[15]=m_value2∕256;
SendB16]=m_value2%256;
Send[17]=m_value3∕256;
Send[18]=m_value3%256;
如圖6所示為寫數據圖。

圖6 對PLC寫數據
本文介紹了ABBAC500系列PLC的構造組成和通訊方式,并且對ModbusTCP通訊協議進行了總結。通過創建基于對話框的MFC程序,利用封裝的CSocket類,按照sock?et通信的流程創建了以太網通訊的上位機軟件。同時按步驟講述PLC的組態配置過程和程序編寫,從而使讀者對整個流程有基本的掌握。本軟件的框架移植性很高,可以在這個基礎上進行各個方面的擴展,利于PLC的推廣和發展。