陳家林,賈 濤
(武漢工程大學 電 氣信息學院,湖北 武 漢 4 30000)
Modbus協議是由Modicon公司在1978年發明的,這是一個跨時代的、里程式的網絡協議,正式為工業網絡從此拉開了序幕。Modbus協議是全球第一個真正用于工業現場的總線協議。
本文主要是研究在μC/OS-Ⅱ實時操作系統內核上的Modbus協議主站的具體實現,充分使用μC/OS-Ⅱ上所提供的實時性資源以及通過硬件上單片機和RS485接口實現與串行連接的從站設備進行數據傳輸和交換。然而,目前市面上已經存在的一些主站設備由于功耗、體積和通信實時性等原因限制了發展。特別是實時性要求,如果被測量的對象實時性要求很高,而測量的實時性又無法達到要求,會導致數據的精確度和準確性大打折扣。可見,實時性要求對儀器儀表的測量是非常重要的。為了實現準確檢測這個要求,本文特此提出了一個具有實時性要求的Modbus主站協議系統的設計方案[1-7]。
Modbus標準定義了 OSI模型第7層上的應用層報文傳輸協議,它在連接至不同類型總線或網絡的設備之間提供客戶機/服務器通信。
本文主要描述的是Modbus串行鏈路協議。Modbus串行鏈路協議是一個主/從協議。該協議位于OSI模型的第二層。在物理層,Modbus串行鏈路系統可以使用不同的物理接口(RS485、RS232)。在Modbus串行鏈路上客戶機的功能由主站提供而服務器功能由從站實現。Modbus串行鏈路協議是一個主/從協議。在同一時刻,只有一個主站連接于總線,一個或多個從站(最大編號為247)連接于同一個串行總線。
當電源上電后,主站的初始狀態為空閑狀態。主站只有在空閑狀態下才能發送請求。發送一個請求后,主站離開空閑狀態,而且不能同時發送第二個請求。
當單播請求發送出去后,主站將進入等待應答狀態,同時一個臨界超時定時啟動。這個超時稱為"響應超時"。它避免主站永遠處于等待應答狀態。當收到一個應答時,主站在處理數據之前檢驗應答。在某些情況下,檢驗的結果可能為錯誤。當未收到應答響應超時,也產生一個錯誤。產生錯誤后,主站進入空閑狀態并準備重發。若沒有錯誤產生,則正常處理數據并進入空閑狀態。
當廣播請求發送出時,是沒有從站會發出響應的。這時主站需要進行一個轉換延時以便從站能夠有足夠時間處理這次廣播請求。主站需要等待轉換延時結束后才可進入到空閑狀態。
考慮到Modbus主站與從站不同,其性質是一個主動性的處理過程,而實際應用中主站每一次發送出去的數據幀在請求時間周期、數據幀內容以及處理要求上都不太一致。為了解決這些問題本設計在μC/OS-Ⅱ所提供的系統服務功能下,將主站系統分為3個部分:請求主站服務的用戶任務、主站服務管理任務、串口底層驅動函數。如圖1所示的主站系統邏輯結構。

圖1 主站系統邏輯結構圖Fig.1 Structure diagram of the simple master station system on Modbus protocol
請求主站服務的用戶任務是指的是那些用戶任務中有調用主站服務的需求,這類任務中包括了一個主站服務調用函數,在本系統內可以將它們看作是應用層。主站系統中的主站管理任務是負責專門管理來自各個請求主站服務的任務的具體請求,同樣可以將它們看作是應用層。串口底層的中斷處理實現了具體的數據發送與接收,可以將它們看作是數據鏈路層。這樣設計保證各個請求主站服務的任務按照CPU對任務調度執行的順序依次循環調用主站服務和處理數據幀,都有平等的機會去請求主站服務。同時每個請求任務在發送出請求后可以繼續執行任務代碼而不是處于等待狀態,也保證了系統整體實時性的要求。
1)系統的主要硬件介紹
主站系統基于STM32L152RBT6為控制器的硬件環境而設計。STM32L152RBT6是屬于由ST公司的STM32L152系列微控制器,該系列屬于是超低功耗,高數據安全性,高效能的ARM Cortex-M3微控制器芯片。低功耗運行模式電流為10.4 μA,工作電壓為 1.8~3.6 V。 能夠滿足實際的工業應用中低功耗穩定的需求。
主站系統的通信模塊采用的是SP3072EEN接口芯片。SP3072EEN是由Sipex公司設計生產的RS-485/RS422收發器,其工作電源電壓為 3.3 V,電源電流為 800 μA。SP3072EEN采用半雙工通訊方式,與單片機引腳連接簡單。它完成將TTL電平轉換為RS485電平的功能。

圖2 RS485轉換接口原理圖Fig.2 Principle diagram of RS485 conversion interface
2)μC/OS-Ⅱ環境的移植
μC/OS-Ⅱ移植工作主要是處理與處理器相關的源文件,即 os_cpu_c.c,os_cpu_a.s,os_cpu.h。 其中 os_cpu.h 主要包含編譯器相關的數據類型的定義、堆棧類型的定義以及幾個宏定義和函數說明,為了便于移植,須重新定義數據類型,因為不同的編譯器所提供的同一數據類型的數據長度并不相同。os_cpu_c.c文件中主要實現任務堆棧的初始化函數OSTaskStkInit(),任務創建函數通過調用函數OSTaskStkInit()初始化任務堆棧結構。在os_cpu_a.s文件中需要根據具體的硬件處理器實現幾個匯編函 數 OSstartHighRdy()、OSCtxSw()、OSIntetxsw 以 及臨 界處理函數 OS_CPU_SR_Save,OS_CPU_SR_Restore。尤其需要注意的是,由于STM32是 cortex M3內核,所以 OSCtxSw()、OSIntetxsw函數都是通過PendSV中斷來完成,它實際負責μC/OS-Ⅱ的所有上下文切換。
3)Modbus主站應用層設計

圖3 主站系統軟件結構圖Fig.3 Software structure diagram of master station system
主站應用層設計時使用到μC/OS-Ⅱ所提供的3個系統服務功能:消息郵箱、消息隊列以及內存管理功能。首先通過OSQCreate()、OSMboxCreate()函數進行初始化,分別建立Buffaddress_Queue消息隊列和Rev_Msg郵箱。然后,為了滿足Modbus協議規定的每數據幀大小不超過256字節,使用OSMemCreate()函數建立對應的一個數據幀緩沖區塊,塊內每個緩沖區大小設置為260字節。其中前256字節為實際Modbus緩沖區大小,后4字節用來存放各個請求的處理標志和底層收發信息包括底層接收字節數Rx和發送字節數Tx以及處理標志handle,none預留。緩沖區格式如圖4所示。

圖4 緩沖區格式圖Fig.4 Structure diagram of the buffer
消息隊列Buffaddress_Queue作為連接用戶請求任務和主站調用任務的橋梁,其作用是將用戶申請作為自身任務數據幀的內存塊地址作為消息內容傳遞給主站管理任務。消息郵箱Rev_Msg作為主站管理任務與底層驅動函數之間的同步信號,并啟用超時機制,實現Modbus上響應超時和轉換延時功能。最后,內存管理為各個請求任務分配獨立的數據幀空間,并統一交予主站管理任務處理。
Host_admin_task()主站管理任務的具體執行過程如圖5所示。主站管理任務得優先級比所有請求主站服務任務都要低,以便最后接收到所有的請求并依次處理。調用OSQPend()等待消息隊列Buffaddress_Queue中的具體消息,一旦得到消息內容,就將該內容作為緩沖區首地址,并預先處理該緩沖區的后4字節內容,將handle初始化為0,將Rx和Tx導入底層函數。隨后調用底層函數完成具體發送和接收。然后調用OSMboxPend()等待接收郵箱Rev_Msg,等待時間設置為1s,由于轉換延時時間小于響應超時,這里統一設為一種超時計時方式。最后,如果正常接收Rx個字節,對應修改緩沖區中的handle標志為1(已接收),若出現超時或者發送命令錯誤則統一修改緩沖區中的標志為2(超時)。

圖5 主站管理任務流程圖Fig.5 Flow chart of the host_admin_task()
Service_call()主站服務請求函數的具體執行過程如圖6所示。首先調用OSMemGet()申請一個緩沖區作為任務的數據幀空間。若申請成功則填充數據幀,填充數據幀不要超過256字節大小。最后發送緩沖區地址給消息隊列Buffaddress_Queue。若填充溢出或者發送隊列失敗則需要及時調用OSMemPut()釋放掉申請的緩沖區。

圖6 主站服務請求函數流程圖Fig.6 Flow chart of the service_call()
Host_apply()主站調用函數具體執行過程如圖7所示。主站調用函數是基于state請求狀態的處理。state請求狀態作為任務里的靜態變量,與任務里的每一個請求任都相對應,表示當前請求任務在主站系統中的狀態信息,state有4種狀態:0空閑可用;1已回復;2回復超時;3已請求。主站調用函數根據state狀態完成具體的請求和處理工作。當state為1時,進行數據幀校驗和上層應用處理。當state為2時,進行釋放緩沖區,準備重新請求。當state為0時,請求主站服務Service_call()。當state為3時,讀取緩沖區處理標志handle,檢測是否接收或者超時。

圖7 主站調用函數流程圖Fig.7 Flow chart of the host_apply()
4)Modbus主站底層驅動設計
串口底層驅動是由STM32中的usart外設中斷服務函
數完成。Usart外設的中斷處理服務函數完成對
usart_low_output()底層發送函數和usart_low_input()底層接收
函數的調用。在底層接收函數usart_low_input()中,判斷了是
否正確接收規定的字節數,若接收字節小于或者未接收都認
為超時錯誤。
底層接收函數的部分代碼:
Void usart_low_output(uint8_t*Datas)//參數為將要發送的數據
{
if(TxBytes!=0)
{
USART_SendData(USART,*Datas);//STM32串口驅動發送函數
Datas++;
TxBytes--;//全局變量TxBytes當前主站需發送的字節數
}
else
{
USART_ITConfig(USART,USART_IT_RXNE,ENABLE);//啟動接收中斷
RxBytes=Datas[257];//當前主站需接收的字節數
}
}
底層發送函數的部分代碼:
Void usart_low_input(uint8_t*Buff)//參數為將要接收數據的緩沖區地址
{
if(RxBytes!=0)
{
Buff++;
RxBytes--;
}
else//接收完畢
{
USART_ITConfig(USART,USART_IT_RXNE,DISABLE);//關閉接收中斷
OSMboxPost(Rev_Msg,&RxBytes);
}
}
系統測試通過將單片機通過RS485轉串口與電腦串口連接并使用modbus slave軟件作為通信的從設備。建立了5個從設備連接到主站系統中,從設備ID號為1~5,每個從設備都帶有10個寄存器,測試主站的0x03讀取輸入寄存器功能。同時,在主站系統中建立了5個請求主站任務,每個任務都周期性500 ms調度一次,按照任務自身優先級順序進行主站請求發送,發送命令為03,寄存器個數為10。測試結果表明slave中每個從設備都周期性的獲取到主站服務并成功完成了接收和發送。
簡易式主站系統通過使用μC/OS-Ⅱ實時操作系統內核帶來的一些系統服務功能使得整個主站系統變得穩定和具有實時性。該主站系統能夠完成一些主要的命令單播的發送與接收,并能簡單的處理從設備超時重發和廣播轉換延時等問題,保證了整體系統實時性和穩定性,并能與上位機軟件進行正常通信,達到了主站系統的設計要求,同時簡易式主站系統也提供了移植到其他嵌入式環境的可能。
[1]方羽,梁廣瑞,羅覃東.基于uCOS_Ⅱ的MODBUS協議的實現[J].裝備制造技術,2009(1):83-84.FANG Yu,LIANG Guang-rui,LUO Qin-dong.The Implementation of Modbus Protocol Based on uCOS_II[J].Equipment Manufacturing Technology,2009(1):83-84.
[2]李振東.Modbus協議的工業PLC監控儀表設計[J].單片機與嵌入式系統應用,2012(4):5-8.LI Zhen -dong.Modbus Protocol Monitoring Instrument for Industrial PLC [J].Microcontrollers&Embedded Systems.2012(4):5-8.
[3]余杰,李鐵輝.基于MODBUS協議的串口控件的實現[J].微計算機信息,2008(21):79-81.YU Jie,LI Tie -hui.The Realization of Serial Port ActiveX Control Based on Modbus Protocol[J].Microcomputer Information,2008(21):79-81.
[4]邵貝貝.嵌入式實時操作系統μC/OS-II[M].2版.北京:北京航空航天大學出版社,2003.
[5]任哲.嵌入式實時操作系統μC/OS-II原理及應用[M].北京:北京航空航天大學出版社,2005.
[6]華镕.從Modbus到透明就緒[M].北京:機械工業出版社,2009.
[7]張利平,劉寧,董樹泉.基于Modbus協議CP341與BENTLY3500之間的通訊[J].工業儀表與自動化裝置,2011(2):86-87.ZHANG Li-ping,LIU Ning,DONG Shu-quan.The communication between CP341 and BENTLY3500 based on Modbus protocol [J].Industrial Instrumentation&Automation,2011(2):86-87.