MODBUS是一個工業(yè)上通信常用的通訊協(xié)議,一般在PLC上面用的比較多,主要是定義了一種數(shù)據(jù)傳輸?shù)囊?guī)范,比如數(shù)據(jù)發(fā)給誰,數(shù)據(jù)是干嘛的,數(shù)據(jù)錯沒錯,接收到數(shù)據(jù)的從機告訴我數(shù)據(jù)有沒有接受到等. 傳輸?shù)姆绞降脑挶容^多的是使用RS232c形式的串口傳輸,當(dāng)然485傳輸也可以,比較高端的可以使用網(wǎng)絡(luò)的tcp傳輸,但是是和之前的串口傳輸有區(qū)別的. 在使用232傳輸?shù)臅r候,整個系統(tǒng)中只有一個主機,剩下的全部是設(shè)備,也就是說,只有作為主機的那個角色才能初始化網(wǎng)絡(luò),并且對整個網(wǎng)絡(luò)上的所有從機進行控制,從機和從機之間不允許直接通訊,這就相當(dāng)于一臺PLC對它外接的設(shè)備進行控制了. 在使用TCP傳輸?shù)臅r候就沒有主機從機的概念了,對等技術(shù)通訊,也就是說,所有的節(jié)點的地位是對等的,控制器即可以接受數(shù)據(jù)并作出響應(yīng),也可以主動查詢網(wǎng)絡(luò)上另一個控制器的狀態(tài),當(dāng)然,但是協(xié)議上,依然會有主機從機的數(shù)據(jù)定義 之所以這樣是因為在232的網(wǎng)絡(luò)上沒有沖突檢測,要是兩個主機,那數(shù)據(jù)很容易就混亂了,但是到了tcp時代,底層的數(shù)據(jù)鏈路層已經(jīng)做了沖突檢測的工作,自然就可以同時傳輸不擔(dān)心數(shù)據(jù)撞車了. 到這里我們看看modbus數(shù)據(jù)傳輸?shù)膮f(xié)議模型 開頭是地址幀,在modbus網(wǎng)絡(luò)中,每一個從機都有一個地址,主機在訪問從機的時候依靠這個唯一的地址識別,多個從機接收到主機的數(shù)據(jù)的時候,匹配接收到的數(shù)據(jù)和自身的地址,匹配上的那個從機作出響應(yīng),其他的都忽略. 第二個是功能碼,決定這一幀數(shù)據(jù)主要是干嘛的,輸入數(shù)據(jù),輸出數(shù)據(jù),讀取控制量等 第三是數(shù)據(jù),可以有也可以沒有 第四是差錯校驗,用來對之前發(fā)送的數(shù)據(jù)校驗,防止發(fā)送過程中因為電磁干擾,數(shù)據(jù)出錯.
上面只是簡單地協(xié)議原型,接下來這個協(xié)議原型有兩種實現(xiàn),分別叫做ascii實現(xiàn)和RTU實現(xiàn),我個人比較喜歡稱之為命令行實現(xiàn)和代碼實現(xiàn),為什么這么叫后面你就會知道了.首先我們要知道,modbus是按byte傳輸?shù)?也就是一次傳輸一個字節(jié) RTU模式 在該模式下,傳輸是這樣的 首先,數(shù)據(jù)已幀為單位傳輸,如果一byte數(shù)據(jù)的傳輸時間為T,那么沒兩幀之間的間隔最小應(yīng)該要大于3.5T,否則從機不能分辨這是兩幀,第二,同一幀連續(xù)的兩個數(shù)據(jù)之間的間隔時間不能超過1.5T,否則節(jié)點會認(rèn)為這一幀數(shù)據(jù)不完整,這說明我們在modbus傳輸?shù)臅r候要使能一個定時器的工作. 其次,地址位一個字節(jié) 功能代碼一個字節(jié),數(shù)據(jù)n字節(jié),crc校驗2字節(jié),那么這個n的限制是多少?協(xié)議規(guī)定一幀中數(shù)據(jù)最多是252字節(jié),最少可以是0字節(jié)
Ascii模式 在該模式下,傳輸?shù)膸械臄?shù)據(jù)的每一位只能是ascii碼的0-9 a-f,因為rtu模式下一字節(jié)一個數(shù)據(jù),也就是1字節(jié)0x00-0xff,所以在ascii模式下為了傳送相同的數(shù)據(jù),必須兩個字節(jié)標(biāo)識一個有效數(shù)據(jù),也就是如下 可以看到,找ascii模式下,不是依靠時間間隔判定幀起始了,而是依靠特定字符判斷,結(jié)束也是按照特定字符判斷,起始的判斷是’:’字符,結(jié)束的判斷是windows下的回車換行,數(shù)據(jù)的最大長度被擴容到了2*252,這樣,兩種傳輸模式能傳輸相同的數(shù)據(jù)量,但是ascii傳輸?shù)母? 但是并不是說時間判據(jù)在ascii模式中就沒有用了,還是有用的,字符間的間隔不能大于1s,大于1s認(rèn)為這一幀數(shù)據(jù)丟失.同樣我們可以計算出來ascii幀的最大長度是513字節(jié) 這個時候你能理解為什么這個叫命令行模式了,因為這種模式下發(fā)送的是可視化的字符串,可以人工的輸入,而之前的rtu模式,手工輸入多麻煩啊,一般程序輸入,而且我們可以判定,他以回車換行作為結(jié)尾,應(yīng)該早期主要是在windows上調(diào)試的,因為linux只需要回車就能實現(xiàn)windows的回車換行,在這種模式下可以把指令寫在文本中直接輸入.不過這兩年acsii模式用的少了,因為調(diào)試軟件的出現(xiàn)簡化了手工輸入的步驟. 說到這里,兩種模式之間的不同還有一個校驗方式的不同,RTU使用crc校驗,ASCII使用LRC校驗,首先看看crc 然后是LRC 前面說了,不符合時間規(guī)則的數(shù)據(jù)將會被丟掉,那主機怎么知道被丟掉了呢?而且假如主機向100設(shè)備發(fā)數(shù)據(jù),網(wǎng)絡(luò)里面沒有100怎么辦? 是這樣的,modbus最多能支持255個子設(shè)備的接入,地址從0x01-0xff,而0x00是廣播地址,也就是說,0x00發(fā)送的數(shù)據(jù)所有的設(shè)備都要接收,但是不能響應(yīng),而其他的節(jié)點的設(shè)備在收到數(shù)據(jù)之后,必須在有限的時間里面進行響應(yīng),或者說是應(yīng)答,主機端會有一個超時管理,超過一定時間沒有反應(yīng)就會認(rèn)為數(shù)據(jù)丟失,該時間可以自由設(shè)置,設(shè)計者在設(shè)計的時候應(yīng)當(dāng)保證盡量使得超時時間大于任何一個外設(shè)的響應(yīng)時間. 其實,當(dāng)設(shè)備接收到了數(shù)據(jù)應(yīng)該怎么應(yīng)答,這個時候又分為正確應(yīng)答和錯誤應(yīng)答,正確應(yīng)答很好說,還是這個格式的數(shù)據(jù)幀 地址是從機自己的地址,功能碼和主機發(fā)送來的功能碼保持一致,數(shù)據(jù)看需求(功能碼的需求) 錯誤的請求的回應(yīng),還是在功能碼上下功夫,之前忘了說,功能碼是從0x00-0x7f,也就是最高位都是0,當(dāng)請求出錯的時候,將主機發(fā)送過來的功能碼加上一個0x80,讓最高位為1就OK了,數(shù)據(jù)部分可以定義一個異常碼,比如請求獲取溫度,發(fā)現(xiàn)溫度傳感器離線了,定義一個異常碼0x01,數(shù)據(jù)域放0x01,主機就知道出錯的具體原因是什么了. 到這里基本上寫一部分就說完了,最后附錄上modbus預(yù)定義的功能碼和異常碼,具體可以參考modbus協(xié)議文檔. 功能碼有:
異常碼為 |
|