當RS485隔離遇見FreeModbus,你碰到問題了嗎?

當RS485隔離遇見Freemodbus,你碰到問題了嗎?

摘要: 基於RS485物理介面的Modbus匯流排在工業控制中廣泛應用。Freemodbus是一個免費的實用的協議棧,本文用它實現了一個從站。串列埠收發訊號和RS485晶片的收發使能訊號採用光耦進行了隔離,在測試過程發現了偶爾出現TimeOut的問題,經過查詢及分析,發現是光耦訊號延時導致的,給出瞭解決方案,並對問題進行了詳細分析。

關鍵詞:RS485 隔離 Freemodbus 光耦 時序

1.問題來源

工業應用中,在進行RS485電路設計的時候,為了確保電氣安全和抗干擾性,經常會做訊號隔離,光耦隔離是常用的一種形式。Modbus協議是現場匯流排協議中比較常見的一種,其設計和使用簡單,執行可靠,在可程式設計控制器、儀器儀表、感測器中使用廣泛,其中,基於RS485物理介面的Modbus匯流排使用最多。Modbus是主從式的通訊結構,一個系統中僅有一個主站,其他為從站。Freemodbus是一個免費的協議棧,僅支援從站。Freemodbus有專門的機構在維護,比較成熟,相對於自己編寫的協議程式碼,執行更穩定,是開發者在研發時的常用選項。

近來,在設計一個基於Modbus-RTU介面的訊號採集站,作為從站,把採集到的訊號傳輸給PLC等主站裝置。微控制器採用STM32F103C8T6,RS485晶片:SP485EEN,接收和傳送的隔離採用光耦PC410,485收發使能訊號的隔離採用光耦EL357NB。RS485部分的原理圖如圖1所示。

當RS485隔離遇見FreeModbus,你碰到問題了嗎?

圖1

程式設計中,採用Freemodbus協議棧實現Modbus-RTU協議,串列埠速率為115200bps,資料位8位,停止位1位,無校驗。

在使用Modbus主站軟體(Modbus Poll)進行除錯的過程中,發現通訊過程中會出現TimeOut的錯誤,有以下幾個特點:

a)並不是每一幀都會出錯,但會不定時地出現;

b)主站詢從站的頻率越高,出錯的機率越低,主站每30ms詢一幀資料的時候基本不出錯,但每500ms或1000ms詢一次的時候,就會比較明顯地出錯。

2.查詢過程

由於硬體電路是之前使用過的,剛開始並沒有考慮是電路的問題。首先是從軟體開始查詢的。由於能夠正常地回覆資料,只是偶爾出錯,因此軟體的整體流程應該是通的,只是某個程式碼的細節有問題,把程式碼整個重新捋了一遍,也沒有發現明顯的問題。

後來,開始逐步排查,先把RS485部分的電路短接掉,用USB-TTL轉換器直接連線微控制器的串列埠收發管腳,進行收發資料的測試,結果一切都正常,無論主站的詢問資料週期是多少,都不會出錯。於是開始懷疑跟485相關的程式碼。

搞過485電路的朋友都知道,485電路僅僅是實現一個電平轉換,另外由於485是半雙工,需要外加一個收發使能控制,485晶片 實現TTL電平與差分電平的轉換。涉及到程式碼,就是多一個管腳,用來控制收發使能。雖然這一步沒有測試出問題,但在反覆試的過程中,倒是有一點意外收穫,分享一下。使能485晶片的傳送語句,必須在使能串列埠傳送中斷(傳送為空中斷)之前,否則通訊是無法成功的。原因分析:傳送為空中斷在使能後,是立即進入中斷的,使能485傳送的程式碼無法執行,傳送沒有使能,但已開始傳送資料,這種情況下,傳送是肯定不會成功的。這個點給我了啟發,是不是傳送的時序有問題,導致傳送失敗呢?

於是開始分析485的收發電路,由於訊號是隔離的,最有可能出現問題的地方是光耦,就從光耦開始查起。開始查閱PC410和EL357NB的資料手冊,開始是擔心光耦前後的限流電阻跟光耦的電流傳輸比是不是不匹配,導致光耦導通不充分,後經分析電路引數沒有問題。然後開始分析光耦的時序,經過光耦隔離的訊號肯定會延時,延時的不同步會不會導致問題呢?果然,PC410和EL357NB的傳輸延時還是有差別的,PC410的傳輸延時在幾十ns,而EL357NB的傳輸延時在1us左右,程式程式碼做了如下修改:在使能485傳送管腳後,延時一段時間後(1us左右,無需太精確),再使能串列埠的傳送中斷,經測試,TimeOut的錯誤了。

3.結論及分析

(1)問題就出在光耦的訊號傳輸延時上,在485電路的設計之初,微控制器的串列埠收發腳採用高速光耦進行隔離,收發使能腳由於不需要頻繁切換,採用一般光耦即可。正是由於這個設計,在使能485收發和使能傳送中斷同時執行的時候,在微控制器的串列埠傳送部分(從傳送快取區到硬體管腳,微控制器內部完成,無需使用者程式碼干預)處理比較快的時候,就會導致485還沒有使能傳送狀態,微控制器已開始向485晶片傳送資料,就會導致傳送出錯,Modbus主站軟體(Modbus Poll)收到的是不完整的錯誤的幀,就是看到的TimeOut錯誤。但在微控制器的串列埠傳送部分處理得不那麼快的時候,就不會出現這個錯誤,這是錯誤不定時出現的原因。

(2)使能485傳送管腳後的延時,不能採用HAL_Delay()函式,Freemodbus協議棧的收發使能在vMBPortSerialEnable(),由於在調此函式之前已經禁掉了中斷,而HAL_Delay()函式是基於系統時鐘中斷定時的,因此不能使用。由於此處不需要精確地定時,只要能滿足兩種光耦延時的時間差即可,可以使用空語句進行定時,大體算一下時間即可。我的程式碼如圖2所示。

當RS485隔離遇見FreeModbus,你碰到問題了嗎?

圖2

(3)在最初的問題中,為什麼主站詢的快的時候錯誤少,反而詢得慢的時候錯誤多?這個問題沒有完全思考清楚,但有一些心得。元器件都會有一些寄生電容,在電平轉換的時候,可以認為電容要先進行充電或放電,因此會有一個斜坡,在主站詢的快的時候,電平轉換快,在電平改變的時候,電容在上一次的過程中還沒有完全放電或充電完畢,這個時候進行反方向的改變需要的時候就會短,可以對沖兩種光耦時間差的影響。不知道我這種說法大家是否可以理解,更深層次或者更確切的原因,也歡迎高手指點,或者大家行進討論。