袁福營(yíng),史智興(等)
摘要:將Modbus協(xié)議應(yīng)用到農(nóng)業(yè)信息化領(lǐng)域,設(shè)計(jì)了一種基于Modbus協(xié)議的嵌入式農(nóng)田信息采集服務(wù)器。分析了Modbus協(xié)議,設(shè)計(jì)了系統(tǒng)各模塊之間的數(shù)據(jù)通信接口,ARM服務(wù)器與應(yīng)用層采用Modbus/TCP通信完成用戶的查詢,ARM服務(wù)器與數(shù)據(jù)采集層采用Modbus串口通信進(jìn)行數(shù)據(jù)的存儲(chǔ),提出了Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換方法,實(shí)現(xiàn)了應(yīng)用層與數(shù)據(jù)采集層的實(shí)時(shí)通信,提高了系統(tǒng)的有效性和可靠性。
關(guān)鍵詞:現(xiàn)代農(nóng)業(yè);嵌入式服務(wù)器;農(nóng)田信息采集;Modbus
中圖分類(lèi)號(hào):TP274 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):0439-8114(2014)07-1667-04
Modbus Protocol Based Designs of ARM Farmland Server
YUAN Fu-ying,SHI Zhi-xing,JING Li-wei,ZHANG Yi-jun
(College of Information Science and Technology, Agricultural University of Hebei, Baoding 071000, Hebei, China)
Abstract: Modbus protocol was applied in the farmland information collection system and a preliminary design of an embedded farmland information collection server based on Modbus protocol was presented. ARM server using Modbus/TCP to communicate with the application layer for completing the users query, and ARM server using seriallink to communicate with data acquisition layer for data storage were analyzed. The conversion of Modbus/TCP frame with serial link RTU frame was proposed to realize the communication for the application layer and the data acquisition layer. The design improved the effectiveness and reliability of the system.
Key words: modern agriculture; embedded server; farmland information acquisition; Modbus
隨著現(xiàn)代農(nóng)業(yè)的推動(dòng),信息技術(shù)正在迅速滲透到農(nóng)業(yè)的各個(gè)領(lǐng)域。采用農(nóng)業(yè)信息化技術(shù),對(duì)大田種植、設(shè)施園藝和水產(chǎn)養(yǎng)殖等農(nóng)業(yè)生產(chǎn)的各種要素進(jìn)行信息采集,進(jìn)一步實(shí)行數(shù)字化設(shè)計(jì)、智能化控制、科學(xué)化管理,大大提高了農(nóng)業(yè)生產(chǎn)的標(biāo)準(zhǔn)化、自動(dòng)化、產(chǎn)業(yè)化,促進(jìn)了農(nóng)業(yè)生產(chǎn)的高產(chǎn)、高效、生態(tài)和安全。信息采集技術(shù)成為了實(shí)現(xiàn)農(nóng)業(yè)信息化的必不可少的前提。
在工業(yè)自動(dòng)化領(lǐng)域中,控制系統(tǒng)普遍采用Modbus通訊協(xié)議[1]。陸晶[2]設(shè)計(jì)了一種基于Modbus協(xié)議的電廠數(shù)據(jù)采集系統(tǒng),提高了數(shù)據(jù)采集的精確性和穩(wěn)定性。任清娟[3]針對(duì)煉鐵廠的高爐渣粒化工廠,采用Modbus通訊協(xié)議達(dá)到了對(duì)現(xiàn)場(chǎng)設(shè)備遠(yuǎn)程實(shí)時(shí)監(jiān)控的目的。林勇堅(jiān)[4]將Modbus現(xiàn)場(chǎng)總線應(yīng)用到水處理流程控制工程項(xiàng)目中,解決了傳統(tǒng)現(xiàn)場(chǎng)總線布線量大、傳輸精度低、信號(hào)易受干擾等問(wèn)題。但是Modbus協(xié)議在農(nóng)業(yè)信息化領(lǐng)域的應(yīng)用尚且不足,為此,將Modbus協(xié)議應(yīng)用到農(nóng)業(yè)信息化領(lǐng)域,設(shè)計(jì)一種基礎(chǔ)Modbus協(xié)議的嵌入式農(nóng)田信息采集服務(wù)器。
1 基于Modbus協(xié)議ARM農(nóng)田服務(wù)器的整體設(shè)計(jì)
農(nóng)田信息采集系統(tǒng)主要包括數(shù)據(jù)采集層、數(shù)據(jù)處理控制層、應(yīng)用層。系統(tǒng)的體系結(jié)構(gòu)如圖1所示。在數(shù)據(jù)采集層,數(shù)據(jù)傳感器采集田間CO2濃度、空氣濕度、光照度等田間參數(shù),經(jīng)過(guò)一系列數(shù)據(jù)處理之后將采集的數(shù)據(jù)信息匯總通過(guò)串口RS485上傳至數(shù)據(jù)處理控制層。服務(wù)器接收到田間信息數(shù)據(jù),進(jìn)行存儲(chǔ)。客戶端可通過(guò)瀏覽器訪問(wèn)服務(wù)器瀏覽田間信息,也可采用C/S的Windows客戶端訪問(wèn)服務(wù)器讀取田間信息。
2 服務(wù)器到應(yīng)用層的通信
設(shè)計(jì)的ARM服務(wù)器使用Linux系統(tǒng)采用Modbus協(xié)議,服務(wù)器與客戶端通信采用Modbus/TCP,服務(wù)器與數(shù)據(jù)采集層通信采用Modbus串口。Modbus/TCP是可靠連接,保證了客戶端與服務(wù)器的有效實(shí)時(shí)通信。服務(wù)器與數(shù)據(jù)采集層通過(guò)串口通信,故可將ARM服務(wù)器放置于田間,解決了傳統(tǒng)服務(wù)器必須放置于室內(nèi)的問(wèn)題。
Modbus屬于應(yīng)用層報(bào)文傳輸協(xié)議,用于不同類(lèi)型的總線或網(wǎng)絡(luò)連接的設(shè)備之間的客戶端/服務(wù)器通信[5]。數(shù)據(jù)通訊采用一對(duì)多的主從查詢模式。主站可以單獨(dú)與從機(jī)通信,也可以廣播方式和所有從站通信。主站以廣播方式查詢,則從站不做出回應(yīng)[6]。Modbus/TCP采用以太網(wǎng)技術(shù)(IEEE802.3)以一種簡(jiǎn)單的方式將Modbus幀嵌入到TCP/IP協(xié)議幀中,在物理層傳輸[7]。Modbus/TCP在TCP/IP上使用專用MBAP報(bào)文頭,MBAP報(bào)文頭包括傳輸標(biāo)志(Transaction Identifier)、協(xié)議標(biāo)志(Protocol Identifier)、長(zhǎng)度域(Length)、單元標(biāo)志(Unit Identifier)。Protocol Identifier為0時(shí),表明是Modbus協(xié)議。Unit Identifier用來(lái)定義從站的設(shè)備地址。Modbus/TCP是可靠連接,因此在Modbus/TCP中不存在校驗(yàn)碼。Modbus/TCP數(shù)據(jù)幀格式如圖2所示。
Modbus有ASCII和RTU兩種串行傳輸方式。ASCII模式通過(guò)冒號(hào)、回車(chē)字符判定數(shù)據(jù)幀的起始和結(jié)束,采用LRC 數(shù)據(jù)檢驗(yàn)。消息中的每一個(gè)8位字節(jié)作為2個(gè)ASCII字符傳輸。ASCII幀字符之間的最大間隔為1 s,超過(guò)1 s則默認(rèn)發(fā)送錯(cuò)誤。RTU模式消息中的每一個(gè)8位字節(jié)含有兩個(gè)4位的16進(jìn)制的字符傳輸,因此在相同的波特率下其具有更高的數(shù)據(jù)量[8]。RTU 模式中數(shù)據(jù)以非壓縮 BCD 碼表示,通過(guò)時(shí)間標(biāo)記實(shí)現(xiàn)數(shù)據(jù)幀起始判定,采用CRC數(shù)據(jù)校驗(yàn),具有數(shù)據(jù)吞吐量高、傳輸穩(wěn)定、通信效率高的優(yōu)點(diǎn)[9]。此次設(shè)計(jì)采用了RTU傳輸方式,RTU報(bào)文格式如表1所示。
2.1 服務(wù)器到應(yīng)用層的通信實(shí)現(xiàn)
Modbus客戶端根據(jù)用戶應(yīng)用向Modbus客戶機(jī)接口發(fā)送的要求中所包含的參數(shù)來(lái)建立一個(gè)Modbus/TCP請(qǐng)求。Modbus服務(wù)器一直處于監(jiān)聽(tīng)TCP502端口的狀態(tài),當(dāng)檢測(cè)到有Modbus請(qǐng)求的時(shí)候,經(jīng)過(guò)TCP 3次握手連接成功。服務(wù)器接收到Modbus請(qǐng)求幀之后,首先進(jìn)行幀解析,完成事務(wù)處理,然后向用戶發(fā)送返回幀。Modbus服務(wù)器處理的事件主要有:等待Modbus/TCP連接、接收請(qǐng)求幀、處理應(yīng)答、處理差錯(cuò)等。Modbus服務(wù)器與客戶端通信流程如圖3所示。
作為通信服務(wù)器端,首先初始化并建立通信socket,bind()本地IP和端口與socket相連,并使用listen方法將其設(shè)置為偵聽(tīng)模式。當(dāng)Modbus客戶機(jī)需要對(duì)服務(wù)器進(jìn)行查詢時(shí),首先會(huì)向Modbus服務(wù)器網(wǎng)關(guān)的502端口發(fā)起連接請(qǐng)求,服務(wù)器監(jiān)聽(tīng)到請(qǐng)求與之建立TCP連接后,客戶機(jī)發(fā)送Modbus/TCP請(qǐng)求幀并等待響應(yīng)。服務(wù)器收到Modbus客戶機(jī)的請(qǐng)求幀,首先進(jìn)行Modbus PDU處理,依次分析處理消息幀結(jié)構(gòu),根據(jù)功能碼進(jìn)行事務(wù)處理,并將事物處理結(jié)果封裝成Modbus/TCP應(yīng)答幀,返回至Modbus客戶機(jī),然后斷開(kāi)連接等待下一次的連接請(qǐng)求。
程序中最核心的Modbus類(lèi)的主要方法的聲明如下:
class CModBus
{
public:
void Connect(const char*ip,ushort port);
void ReadHoldingRegistersFun(ushort strAddress,ushortnumInputs);
void WriteMultipleRegistersFun(ushort straddress,int*ptrValue,int nLen);
void WriteSingleRegistersFun(ushort address,ushort Data);
private:
void CreateReadHeader(ushort startReadAddress,ushort lenght,unsigned char function);
void CreateWriteHeader(ushort starAddaress,ushort len,unsigned char function);
void CRCChick(unsigned char*messageDate,int nLen);
void WriteAsyncDate(unsigned char*pWriteDate,int nDataLen);
void TransformParamDateFun(int len,unsigned char*Data);
void TransformControlDateFun(int len,unsigned char*Data);
void RecvReadData();
……}
Modbus類(lèi)中Connect()實(shí)現(xiàn)服務(wù)器與客戶端socket的連接,ReadHoldingRegistersFun()用來(lái)發(fā)送客戶端讀取數(shù)據(jù)的結(jié)果,WriteSingleRegistersFun()、WriteMultipleRegistersFun()分別實(shí)現(xiàn)寫(xiě)單個(gè)寄存器和寫(xiě)多個(gè)寄存器。CreateReadHeader()、CreateWriteHeader()分別創(chuàng)建Modbus讀寫(xiě)寄存器幀的頭部數(shù)據(jù),WriteAsyncDate()將數(shù)據(jù)寫(xiě)入到socket。TransformControlDateFun()、TransformParamDateFun()轉(zhuǎn)換讀取控制、參數(shù)數(shù)據(jù)。RecvReadData()從連接套接字中讀取信息。
服務(wù)器向客戶端發(fā)送回應(yīng)結(jié)果,首先調(diào)用ReadHoldingRegistersFun(),通過(guò)執(zhí)行CreateReadWriteHeader()填寫(xiě)RTU數(shù)據(jù)幀信息,然后WriteAsyncDate()向緩沖區(qū)用SendData發(fā)送數(shù)據(jù)。具體實(shí)現(xiàn)程序如下:
void CModBus::ReadHoldingRegistersFun(usho
rt strAddress,ushort numInputs){
CreateReadWriteHeader(strAddress,numInputs,ReadHoldingRegisters);
WriteAsyncDate(SendDate,READ_REGISTERS_HEA
DER_LEN);
}
void CModBus::WriteAsyncDate(unsigned char *pWriteDate,int nDataLen)
{
if(nSocket>0&&nConnect>=0)
{
FD_SET(nSocket,&set);
neSlect=select(nSocket+1,NULL,&set,NULL,&tv);if(neSlect>0)
{
nSend=send(nSocket,(char*)pWriteDate,nDataLen,0);
}
if(nDataLen==READ_REGISTERS_HEAD
ER_LEN)
{
RecvReadData();
}
else
{
RecvWriteReturn();
}
}
FD_ZERO(&set);
}
若客戶端要讀取06號(hào)設(shè)備起始地址為4的連續(xù)2個(gè)寄存器,讀取保持寄存器的功能碼function為3。服務(wù)器通信結(jié)果見(jiàn)圖4。
2.2 Modbus/TCP幀與RTU幀轉(zhuǎn)換設(shè)計(jì)
當(dāng)客戶端需要查詢當(dāng)前的實(shí)時(shí)數(shù)據(jù),而服務(wù)器還未進(jìn)行存儲(chǔ),客戶端向服務(wù)器發(fā)送Modbus/TCP請(qǐng)求幀并等待服務(wù)器應(yīng)答,服務(wù)器接收Modbus/TCP請(qǐng)求幀對(duì)其進(jìn)行分析處理,轉(zhuǎn)化成Modus RTU串行鏈路響應(yīng)幀并發(fā)送到與數(shù)據(jù)采集層相連的串行鏈路中去,監(jiān)聽(tīng)等待數(shù)據(jù)采集層的應(yīng)答。若服務(wù)器收到串行鏈路上的RTU應(yīng)答幀,則將該應(yīng)答幀重新封裝成Modbus/TCP應(yīng)答幀,發(fā)送給客戶端。因此,在服務(wù)器端需要進(jìn)行Modbus/TCP與串行鏈路RTU的轉(zhuǎn)換。
ModToRtu()函數(shù)實(shí)現(xiàn)Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換功能,轉(zhuǎn)換過(guò)程見(jiàn)圖5。
Modbus/TCP幀與串行鏈路RTU幀相比,增加了MBAP報(bào)文,減少了CRC校驗(yàn)碼。Modbus/TCP轉(zhuǎn)串行鏈路RTU過(guò)程:首先從MBAP報(bào)文頭中解析出地址段,并將MBAP的各字段保存。然后從Modbus/TCP幀中分別解析出功能碼和數(shù)據(jù)段,并計(jì)算CRC校驗(yàn)碼,最后封裝成串行鏈路RTU幀。
串行鏈路RTU幀轉(zhuǎn)換成Modbus/TCP幀:首先利用已保存MBAP字段重新封裝成MBAP,然后從RTU幀中讀取數(shù)據(jù)段和功能碼,分別填充到Modbus/TCP幀的數(shù)據(jù)段和功能碼,封裝成Modbus/TCP幀。
2.3 線程池
在服務(wù)器整個(gè)工作過(guò)程中,系統(tǒng)通過(guò)線程與客戶端和與數(shù)據(jù)采集層進(jìn)行通信。傳統(tǒng)多線程方案的服務(wù)器,多個(gè)線程在同一時(shí)間內(nèi)并發(fā)運(yùn)行執(zhí)行相應(yīng)的任務(wù)[10],采用“及時(shí)創(chuàng)建,及時(shí)銷(xiāo)毀”的策略。當(dāng)服務(wù)器接收到請(qǐng)求之后創(chuàng)建一個(gè)線程,由該線程執(zhí)行具體任務(wù),任務(wù)結(jié)束之后線程退出。若大量用戶同時(shí)訪問(wèn)服務(wù)器,在短時(shí)間內(nèi),服務(wù)器將處于不停地創(chuàng)建線程、銷(xiāo)毀線程的狀態(tài),容易導(dǎo)致消耗系統(tǒng)內(nèi)存。因此,系統(tǒng)增加了線程池,大大減少了線程的開(kāi)銷(xiāo)。
線程池采用預(yù)創(chuàng)建技術(shù)。程序啟動(dòng)之后,首先創(chuàng)建一定數(shù)量(NUM個(gè))的線程,這些線程處于阻塞狀態(tài),并不消耗CPU。當(dāng)系統(tǒng)有任務(wù)需要執(zhí)行時(shí),程序喚醒一個(gè)空閑線程執(zhí)行任務(wù)。任務(wù)完成之后,該線程再次回到阻塞狀態(tài),等待下次任務(wù)的到來(lái)。在線程池的數(shù)量設(shè)計(jì)上,程序所創(chuàng)建的線程總數(shù)不能高于THREAD_MAXNUM,當(dāng)系統(tǒng)中的空閑線程數(shù)量低于THREAD_Max時(shí),程序?qū)?chuàng)建一些線程,使得空閑線程維持在THREAD_AvailLow之上。當(dāng)系統(tǒng)中的空閑線程數(shù)量高于THREAD_AvailHigh時(shí),線程池會(huì)自動(dòng)銷(xiāo)毀一些線程,保持空閑線程的數(shù)量在一個(gè)合理的范圍內(nèi)。
3 服務(wù)器到數(shù)據(jù)采集層的通信
服務(wù)器通過(guò)串口定期向數(shù)據(jù)采集層發(fā)送RTU請(qǐng)求幀,并等待接收數(shù)據(jù)采集層的RTU返回幀,將收到的農(nóng)田信息存儲(chǔ)在數(shù)據(jù)庫(kù)中。
服務(wù)器端首先打開(kāi)串口,調(diào)用CreatData()準(zhǔn)備要發(fā)送的請(qǐng)求數(shù)據(jù),執(zhí)行CreatCRC()生成函數(shù)獲取CRC校驗(yàn)碼,通過(guò)CreatRtu()封裝程序組織生成RTU報(bào)文,發(fā)送RTU信息幀,檢測(cè)串口等待返回幀。若等待超過(guò)Modbus協(xié)議規(guī)定的4個(gè)字符延時(shí)等待時(shí)間,則進(jìn)行超時(shí)處理。否則,接收數(shù)據(jù)采集層的返回幀之后,返回到數(shù)據(jù)準(zhǔn)備階段,繼續(xù)檢測(cè)串口。服務(wù)器端界面采用qt設(shè)計(jì),如圖6所示。
4 小結(jié)
分析了Modbus協(xié)議,將應(yīng)用在工業(yè)控制中的Modbus協(xié)議引入到農(nóng)田信息采集系統(tǒng),Modbus幀格式簡(jiǎn)單、緊湊、高效,同時(shí)Modbus/TCP具有實(shí)時(shí)通信的特點(diǎn),更適合嵌入式設(shè)備,實(shí)現(xiàn)遠(yuǎn)程數(shù)據(jù)的交互,從而達(dá)到遠(yuǎn)程監(jiān)測(cè)的目的。設(shè)計(jì)了基于Modbus協(xié)議的ARM農(nóng)田信息采集服務(wù)器,實(shí)現(xiàn)了服務(wù)器與應(yīng)用層、服務(wù)器與數(shù)據(jù)采集層的通信接口,提出了Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換方法,增加了線程池完成每一次的通信任務(wù)。服務(wù)器可訪問(wèn)數(shù)據(jù)采集端進(jìn)行田間信息存儲(chǔ),客戶端可隨時(shí)訪問(wèn)服務(wù)器瀏覽田間信息。但是服務(wù)器還存在不足,如何健全服務(wù)器功能,發(fā)揮Modbus嵌入式服務(wù)器的綜合優(yōu)勢(shì),仍需進(jìn)一步的研究。
參考文獻(xiàn):
[1] 劉西廣.用于西門(mén)子Insight軟件的Modbus協(xié)議通用網(wǎng)關(guān)設(shè)計(jì)[D].成都:電子科技大學(xué),2011.
[2] 陸 晶.基于Modbus的數(shù)據(jù)采集系統(tǒng)[D].江蘇無(wú)錫:江南大學(xué),2011.
[3] 任清娟.基于Modbus和GPRS的高爐渣?;潆姳O(jiān)控系統(tǒng)的設(shè)計(jì)[D].內(nèi)蒙古包頭:內(nèi)蒙古科技大學(xué),2012.
[4] 林勇堅(jiān).基于Modbus現(xiàn)場(chǎng)總線的水處理流程控制的工程設(shè)計(jì)[J].廣西民族大學(xué)學(xué)報(bào)(自然科學(xué)版),2013,19(1):79-81.
[5] 陳 輝.基于Modbus協(xié)議灌區(qū)遠(yuǎn)程智能測(cè)控系統(tǒng)研究[D].蘭州:蘭州理工大學(xué),2012.
[6] 王 諦.基于Modbus協(xié)議的PC機(jī)與dsPIC6014處理器的通信[D].呼和浩特:內(nèi)蒙古大學(xué),2012.
[7] 景柏豪,沈孟良,唐曄鈞.CAN-Modbus/TCP協(xié)議轉(zhuǎn)換的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程與設(shè)計(jì),2013,34(5):1552-1556.
[8] 李振江.Linux系統(tǒng)下Modbus主協(xié)議棧設(shè)計(jì)與實(shí)現(xiàn)[D].合肥:安徽大學(xué),2012.
[9] 吳寅華,趙 敏.基于ARM Cortex-M3的Modbus協(xié)議實(shí)現(xiàn)及其應(yīng)用[J].電子科技,2011,24(6):19-21.
[10] 楊開(kāi)杰,劉秋菊,徐汀榮.線程池的多線程并發(fā)控制技術(shù)研究[J].計(jì)算機(jī)應(yīng)用與軟件,2010,27(1):168-169.
{
FD_SET(nSocket,&set);
neSlect=select(nSocket+1,NULL,&set,NULL,&tv);if(neSlect>0)
{
nSend=send(nSocket,(char*)pWriteDate,nDataLen,0);
}
if(nDataLen==READ_REGISTERS_HEAD
ER_LEN)
{
RecvReadData();
}
else
{
RecvWriteReturn();
}
}
FD_ZERO(&set);
}
若客戶端要讀取06號(hào)設(shè)備起始地址為4的連續(xù)2個(gè)寄存器,讀取保持寄存器的功能碼function為3。服務(wù)器通信結(jié)果見(jiàn)圖4。
2.2 Modbus/TCP幀與RTU幀轉(zhuǎn)換設(shè)計(jì)
當(dāng)客戶端需要查詢當(dāng)前的實(shí)時(shí)數(shù)據(jù),而服務(wù)器還未進(jìn)行存儲(chǔ),客戶端向服務(wù)器發(fā)送Modbus/TCP請(qǐng)求幀并等待服務(wù)器應(yīng)答,服務(wù)器接收Modbus/TCP請(qǐng)求幀對(duì)其進(jìn)行分析處理,轉(zhuǎn)化成Modus RTU串行鏈路響應(yīng)幀并發(fā)送到與數(shù)據(jù)采集層相連的串行鏈路中去,監(jiān)聽(tīng)等待數(shù)據(jù)采集層的應(yīng)答。若服務(wù)器收到串行鏈路上的RTU應(yīng)答幀,則將該應(yīng)答幀重新封裝成Modbus/TCP應(yīng)答幀,發(fā)送給客戶端。因此,在服務(wù)器端需要進(jìn)行Modbus/TCP與串行鏈路RTU的轉(zhuǎn)換。
ModToRtu()函數(shù)實(shí)現(xiàn)Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換功能,轉(zhuǎn)換過(guò)程見(jiàn)圖5。
Modbus/TCP幀與串行鏈路RTU幀相比,增加了MBAP報(bào)文,減少了CRC校驗(yàn)碼。Modbus/TCP轉(zhuǎn)串行鏈路RTU過(guò)程:首先從MBAP報(bào)文頭中解析出地址段,并將MBAP的各字段保存。然后從Modbus/TCP幀中分別解析出功能碼和數(shù)據(jù)段,并計(jì)算CRC校驗(yàn)碼,最后封裝成串行鏈路RTU幀。
串行鏈路RTU幀轉(zhuǎn)換成Modbus/TCP幀:首先利用已保存MBAP字段重新封裝成MBAP,然后從RTU幀中讀取數(shù)據(jù)段和功能碼,分別填充到Modbus/TCP幀的數(shù)據(jù)段和功能碼,封裝成Modbus/TCP幀。
2.3 線程池
在服務(wù)器整個(gè)工作過(guò)程中,系統(tǒng)通過(guò)線程與客戶端和與數(shù)據(jù)采集層進(jìn)行通信。傳統(tǒng)多線程方案的服務(wù)器,多個(gè)線程在同一時(shí)間內(nèi)并發(fā)運(yùn)行執(zhí)行相應(yīng)的任務(wù)[10],采用“及時(shí)創(chuàng)建,及時(shí)銷(xiāo)毀”的策略。當(dāng)服務(wù)器接收到請(qǐng)求之后創(chuàng)建一個(gè)線程,由該線程執(zhí)行具體任務(wù),任務(wù)結(jié)束之后線程退出。若大量用戶同時(shí)訪問(wèn)服務(wù)器,在短時(shí)間內(nèi),服務(wù)器將處于不停地創(chuàng)建線程、銷(xiāo)毀線程的狀態(tài),容易導(dǎo)致消耗系統(tǒng)內(nèi)存。因此,系統(tǒng)增加了線程池,大大減少了線程的開(kāi)銷(xiāo)。
線程池采用預(yù)創(chuàng)建技術(shù)。程序啟動(dòng)之后,首先創(chuàng)建一定數(shù)量(NUM個(gè))的線程,這些線程處于阻塞狀態(tài),并不消耗CPU。當(dāng)系統(tǒng)有任務(wù)需要執(zhí)行時(shí),程序喚醒一個(gè)空閑線程執(zhí)行任務(wù)。任務(wù)完成之后,該線程再次回到阻塞狀態(tài),等待下次任務(wù)的到來(lái)。在線程池的數(shù)量設(shè)計(jì)上,程序所創(chuàng)建的線程總數(shù)不能高于THREAD_MAXNUM,當(dāng)系統(tǒng)中的空閑線程數(shù)量低于THREAD_Max時(shí),程序?qū)?chuàng)建一些線程,使得空閑線程維持在THREAD_AvailLow之上。當(dāng)系統(tǒng)中的空閑線程數(shù)量高于THREAD_AvailHigh時(shí),線程池會(huì)自動(dòng)銷(xiāo)毀一些線程,保持空閑線程的數(shù)量在一個(gè)合理的范圍內(nèi)。
3 服務(wù)器到數(shù)據(jù)采集層的通信
服務(wù)器通過(guò)串口定期向數(shù)據(jù)采集層發(fā)送RTU請(qǐng)求幀,并等待接收數(shù)據(jù)采集層的RTU返回幀,將收到的農(nóng)田信息存儲(chǔ)在數(shù)據(jù)庫(kù)中。
服務(wù)器端首先打開(kāi)串口,調(diào)用CreatData()準(zhǔn)備要發(fā)送的請(qǐng)求數(shù)據(jù),執(zhí)行CreatCRC()生成函數(shù)獲取CRC校驗(yàn)碼,通過(guò)CreatRtu()封裝程序組織生成RTU報(bào)文,發(fā)送RTU信息幀,檢測(cè)串口等待返回幀。若等待超過(guò)Modbus協(xié)議規(guī)定的4個(gè)字符延時(shí)等待時(shí)間,則進(jìn)行超時(shí)處理。否則,接收數(shù)據(jù)采集層的返回幀之后,返回到數(shù)據(jù)準(zhǔn)備階段,繼續(xù)檢測(cè)串口。服務(wù)器端界面采用qt設(shè)計(jì),如圖6所示。
4 小結(jié)
分析了Modbus協(xié)議,將應(yīng)用在工業(yè)控制中的Modbus協(xié)議引入到農(nóng)田信息采集系統(tǒng),Modbus幀格式簡(jiǎn)單、緊湊、高效,同時(shí)Modbus/TCP具有實(shí)時(shí)通信的特點(diǎn),更適合嵌入式設(shè)備,實(shí)現(xiàn)遠(yuǎn)程數(shù)據(jù)的交互,從而達(dá)到遠(yuǎn)程監(jiān)測(cè)的目的。設(shè)計(jì)了基于Modbus協(xié)議的ARM農(nóng)田信息采集服務(wù)器,實(shí)現(xiàn)了服務(wù)器與應(yīng)用層、服務(wù)器與數(shù)據(jù)采集層的通信接口,提出了Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換方法,增加了線程池完成每一次的通信任務(wù)。服務(wù)器可訪問(wèn)數(shù)據(jù)采集端進(jìn)行田間信息存儲(chǔ),客戶端可隨時(shí)訪問(wèn)服務(wù)器瀏覽田間信息。但是服務(wù)器還存在不足,如何健全服務(wù)器功能,發(fā)揮Modbus嵌入式服務(wù)器的綜合優(yōu)勢(shì),仍需進(jìn)一步的研究。
參考文獻(xiàn):
[1] 劉西廣.用于西門(mén)子Insight軟件的Modbus協(xié)議通用網(wǎng)關(guān)設(shè)計(jì)[D].成都:電子科技大學(xué),2011.
[2] 陸 晶.基于Modbus的數(shù)據(jù)采集系統(tǒng)[D].江蘇無(wú)錫:江南大學(xué),2011.
[3] 任清娟.基于Modbus和GPRS的高爐渣?;潆姳O(jiān)控系統(tǒng)的設(shè)計(jì)[D].內(nèi)蒙古包頭:內(nèi)蒙古科技大學(xué),2012.
[4] 林勇堅(jiān).基于Modbus現(xiàn)場(chǎng)總線的水處理流程控制的工程設(shè)計(jì)[J].廣西民族大學(xué)學(xué)報(bào)(自然科學(xué)版),2013,19(1):79-81.
[5] 陳 輝.基于Modbus協(xié)議灌區(qū)遠(yuǎn)程智能測(cè)控系統(tǒng)研究[D].蘭州:蘭州理工大學(xué),2012.
[6] 王 諦.基于Modbus協(xié)議的PC機(jī)與dsPIC6014處理器的通信[D].呼和浩特:內(nèi)蒙古大學(xué),2012.
[7] 景柏豪,沈孟良,唐曄鈞.CAN-Modbus/TCP協(xié)議轉(zhuǎn)換的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程與設(shè)計(jì),2013,34(5):1552-1556.
[8] 李振江.Linux系統(tǒng)下Modbus主協(xié)議棧設(shè)計(jì)與實(shí)現(xiàn)[D].合肥:安徽大學(xué),2012.
[9] 吳寅華,趙 敏.基于ARM Cortex-M3的Modbus協(xié)議實(shí)現(xiàn)及其應(yīng)用[J].電子科技,2011,24(6):19-21.
[10] 楊開(kāi)杰,劉秋菊,徐汀榮.線程池的多線程并發(fā)控制技術(shù)研究[J].計(jì)算機(jī)應(yīng)用與軟件,2010,27(1):168-169.
{
FD_SET(nSocket,&set);
neSlect=select(nSocket+1,NULL,&set,NULL,&tv);if(neSlect>0)
{
nSend=send(nSocket,(char*)pWriteDate,nDataLen,0);
}
if(nDataLen==READ_REGISTERS_HEAD
ER_LEN)
{
RecvReadData();
}
else
{
RecvWriteReturn();
}
}
FD_ZERO(&set);
}
若客戶端要讀取06號(hào)設(shè)備起始地址為4的連續(xù)2個(gè)寄存器,讀取保持寄存器的功能碼function為3。服務(wù)器通信結(jié)果見(jiàn)圖4。
2.2 Modbus/TCP幀與RTU幀轉(zhuǎn)換設(shè)計(jì)
當(dāng)客戶端需要查詢當(dāng)前的實(shí)時(shí)數(shù)據(jù),而服務(wù)器還未進(jìn)行存儲(chǔ),客戶端向服務(wù)器發(fā)送Modbus/TCP請(qǐng)求幀并等待服務(wù)器應(yīng)答,服務(wù)器接收Modbus/TCP請(qǐng)求幀對(duì)其進(jìn)行分析處理,轉(zhuǎn)化成Modus RTU串行鏈路響應(yīng)幀并發(fā)送到與數(shù)據(jù)采集層相連的串行鏈路中去,監(jiān)聽(tīng)等待數(shù)據(jù)采集層的應(yīng)答。若服務(wù)器收到串行鏈路上的RTU應(yīng)答幀,則將該應(yīng)答幀重新封裝成Modbus/TCP應(yīng)答幀,發(fā)送給客戶端。因此,在服務(wù)器端需要進(jìn)行Modbus/TCP與串行鏈路RTU的轉(zhuǎn)換。
ModToRtu()函數(shù)實(shí)現(xiàn)Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換功能,轉(zhuǎn)換過(guò)程見(jiàn)圖5。
Modbus/TCP幀與串行鏈路RTU幀相比,增加了MBAP報(bào)文,減少了CRC校驗(yàn)碼。Modbus/TCP轉(zhuǎn)串行鏈路RTU過(guò)程:首先從MBAP報(bào)文頭中解析出地址段,并將MBAP的各字段保存。然后從Modbus/TCP幀中分別解析出功能碼和數(shù)據(jù)段,并計(jì)算CRC校驗(yàn)碼,最后封裝成串行鏈路RTU幀。
串行鏈路RTU幀轉(zhuǎn)換成Modbus/TCP幀:首先利用已保存MBAP字段重新封裝成MBAP,然后從RTU幀中讀取數(shù)據(jù)段和功能碼,分別填充到Modbus/TCP幀的數(shù)據(jù)段和功能碼,封裝成Modbus/TCP幀。
2.3 線程池
在服務(wù)器整個(gè)工作過(guò)程中,系統(tǒng)通過(guò)線程與客戶端和與數(shù)據(jù)采集層進(jìn)行通信。傳統(tǒng)多線程方案的服務(wù)器,多個(gè)線程在同一時(shí)間內(nèi)并發(fā)運(yùn)行執(zhí)行相應(yīng)的任務(wù)[10],采用“及時(shí)創(chuàng)建,及時(shí)銷(xiāo)毀”的策略。當(dāng)服務(wù)器接收到請(qǐng)求之后創(chuàng)建一個(gè)線程,由該線程執(zhí)行具體任務(wù),任務(wù)結(jié)束之后線程退出。若大量用戶同時(shí)訪問(wèn)服務(wù)器,在短時(shí)間內(nèi),服務(wù)器將處于不停地創(chuàng)建線程、銷(xiāo)毀線程的狀態(tài),容易導(dǎo)致消耗系統(tǒng)內(nèi)存。因此,系統(tǒng)增加了線程池,大大減少了線程的開(kāi)銷(xiāo)。
線程池采用預(yù)創(chuàng)建技術(shù)。程序啟動(dòng)之后,首先創(chuàng)建一定數(shù)量(NUM個(gè))的線程,這些線程處于阻塞狀態(tài),并不消耗CPU。當(dāng)系統(tǒng)有任務(wù)需要執(zhí)行時(shí),程序喚醒一個(gè)空閑線程執(zhí)行任務(wù)。任務(wù)完成之后,該線程再次回到阻塞狀態(tài),等待下次任務(wù)的到來(lái)。在線程池的數(shù)量設(shè)計(jì)上,程序所創(chuàng)建的線程總數(shù)不能高于THREAD_MAXNUM,當(dāng)系統(tǒng)中的空閑線程數(shù)量低于THREAD_Max時(shí),程序?qū)?chuàng)建一些線程,使得空閑線程維持在THREAD_AvailLow之上。當(dāng)系統(tǒng)中的空閑線程數(shù)量高于THREAD_AvailHigh時(shí),線程池會(huì)自動(dòng)銷(xiāo)毀一些線程,保持空閑線程的數(shù)量在一個(gè)合理的范圍內(nèi)。
3 服務(wù)器到數(shù)據(jù)采集層的通信
服務(wù)器通過(guò)串口定期向數(shù)據(jù)采集層發(fā)送RTU請(qǐng)求幀,并等待接收數(shù)據(jù)采集層的RTU返回幀,將收到的農(nóng)田信息存儲(chǔ)在數(shù)據(jù)庫(kù)中。
服務(wù)器端首先打開(kāi)串口,調(diào)用CreatData()準(zhǔn)備要發(fā)送的請(qǐng)求數(shù)據(jù),執(zhí)行CreatCRC()生成函數(shù)獲取CRC校驗(yàn)碼,通過(guò)CreatRtu()封裝程序組織生成RTU報(bào)文,發(fā)送RTU信息幀,檢測(cè)串口等待返回幀。若等待超過(guò)Modbus協(xié)議規(guī)定的4個(gè)字符延時(shí)等待時(shí)間,則進(jìn)行超時(shí)處理。否則,接收數(shù)據(jù)采集層的返回幀之后,返回到數(shù)據(jù)準(zhǔn)備階段,繼續(xù)檢測(cè)串口。服務(wù)器端界面采用qt設(shè)計(jì),如圖6所示。
4 小結(jié)
分析了Modbus協(xié)議,將應(yīng)用在工業(yè)控制中的Modbus協(xié)議引入到農(nóng)田信息采集系統(tǒng),Modbus幀格式簡(jiǎn)單、緊湊、高效,同時(shí)Modbus/TCP具有實(shí)時(shí)通信的特點(diǎn),更適合嵌入式設(shè)備,實(shí)現(xiàn)遠(yuǎn)程數(shù)據(jù)的交互,從而達(dá)到遠(yuǎn)程監(jiān)測(cè)的目的。設(shè)計(jì)了基于Modbus協(xié)議的ARM農(nóng)田信息采集服務(wù)器,實(shí)現(xiàn)了服務(wù)器與應(yīng)用層、服務(wù)器與數(shù)據(jù)采集層的通信接口,提出了Modbus/TCP幀與串行鏈路RTU幀的轉(zhuǎn)換方法,增加了線程池完成每一次的通信任務(wù)。服務(wù)器可訪問(wèn)數(shù)據(jù)采集端進(jìn)行田間信息存儲(chǔ),客戶端可隨時(shí)訪問(wèn)服務(wù)器瀏覽田間信息。但是服務(wù)器還存在不足,如何健全服務(wù)器功能,發(fā)揮Modbus嵌入式服務(wù)器的綜合優(yōu)勢(shì),仍需進(jìn)一步的研究。
參考文獻(xiàn):
[1] 劉西廣.用于西門(mén)子Insight軟件的Modbus協(xié)議通用網(wǎng)關(guān)設(shè)計(jì)[D].成都:電子科技大學(xué),2011.
[2] 陸 晶.基于Modbus的數(shù)據(jù)采集系統(tǒng)[D].江蘇無(wú)錫:江南大學(xué),2011.
[3] 任清娟.基于Modbus和GPRS的高爐渣粒化配電監(jiān)控系統(tǒng)的設(shè)計(jì)[D].內(nèi)蒙古包頭:內(nèi)蒙古科技大學(xué),2012.
[4] 林勇堅(jiān).基于Modbus現(xiàn)場(chǎng)總線的水處理流程控制的工程設(shè)計(jì)[J].廣西民族大學(xué)學(xué)報(bào)(自然科學(xué)版),2013,19(1):79-81.
[5] 陳 輝.基于Modbus協(xié)議灌區(qū)遠(yuǎn)程智能測(cè)控系統(tǒng)研究[D].蘭州:蘭州理工大學(xué),2012.
[6] 王 諦.基于Modbus協(xié)議的PC機(jī)與dsPIC6014處理器的通信[D].呼和浩特:內(nèi)蒙古大學(xué),2012.
[7] 景柏豪,沈孟良,唐曄鈞.CAN-Modbus/TCP協(xié)議轉(zhuǎn)換的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)工程與設(shè)計(jì),2013,34(5):1552-1556.
[8] 李振江.Linux系統(tǒng)下Modbus主協(xié)議棧設(shè)計(jì)與實(shí)現(xiàn)[D].合肥:安徽大學(xué),2012.
[9] 吳寅華,趙 敏.基于ARM Cortex-M3的Modbus協(xié)議實(shí)現(xiàn)及其應(yīng)用[J].電子科技,2011,24(6):19-21.
[10] 楊開(kāi)杰,劉秋菊,徐汀榮.線程池的多線程并發(fā)控制技術(shù)研究[J].計(jì)算機(jī)應(yīng)用與軟件,2010,27(1):168-169.