RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

安卓與串口通信入門之modbus(上)

jf_78858299 ? 來源:Android技術之家 ? 作者:Android技術之家 ? 2023-04-23 17:40 ? 次閱讀

前言

在之前的兩篇文章中,我們講解了串口的基礎知識和在安卓中使用串口通信的方法,如果還沒看過之前文章的同學們,建議先看一遍,不然可能會不理解這篇文章講的某些內容。

事實上,在實際應用中,我們很少會直接使用串口通信,一般都會使用到 Modbus。

因為正如我上篇文章所說,如果直接使用串口通信的話,需要我們自定義數(shù)據(jù)層協(xié)議,或者干脆就直接發(fā)送一個 byte 的數(shù)字進行通信,這顯然是不方便的,也不安全的。

例如我上篇提到過的一個問題,我所使用的驅動版廠商定義的協(xié)議中沒有定義數(shù)據(jù)長度(或者在數(shù)據(jù)中附上數(shù)據(jù)長度),也沒有定義停止符號,這會導致出現(xiàn)“沾包”或“分包”情況時不好區(qū)分數(shù)據(jù)。

并且自定義協(xié)議還需要自己去解析并處理數(shù)據(jù),使用起來不是那么方便。

所以,我司在嘗試過直接使用串口通信后,最終還是決定放棄直接使用串口通信,而是改用 Modbus 通信。

本篇文章屬于系列文章的擴展篇,我們將講解 Modbus 的基礎知識以及如何在安卓中使用 Modbus。

本文中部分圖表來自文末標注的參考資料

Modbs 基礎

簡介

Modbus 是一種應用層報文傳輸協(xié)議,由 Modicon 公司在 1979 年發(fā)布,是為了解決 PLC 通信而研發(fā)的協(xié)議。

因為 Modbus 是開源的且無著作權要求、易于部署維護、可靠性強的特性,所以 Modbus 已經成為工業(yè)領域通信協(xié)議事實上的業(yè)界標準,并且現(xiàn)在是工業(yè)電子設備之間常用的連接方式。

由于 Modbus 定義的只是應用層的報文協(xié)議,所以它可以使用串口(RS232、RS485)、以太網作為物理層接口。

Modbus 分為三種傳輸模式:RTU、ASII、TCP。

在使用 Modbus 時,所有設備的傳輸模式必須相同。

RTU 使用二進制數(shù)據(jù)傳輸、ASCII 使用 ASCII 字符傳輸。

使用串口連接時支持 RTU 和 ASCII 模式。

使用以太網連接時支持 TCP 模式。

因為本系列文章的重點在于講解串口通信,所以我們不過多講解 TCP 模式,同時,由于 ASCII 模式在目前實際應用中比較少,我們一般都是使用的 RTU 模式。故,我們會重點講解 Modbus RTU。如果對其他傳輸模式感興趣的可以閱讀參考資料 4 的文檔。

額外說明一下,Modbus 和 RS232、RS485 的區(qū)別。

RS232、RS485定義的是物理層標準,即接線方式,電平高低,數(shù)據(jù)傳輸方式等。

而 Modbus 是應用層協(xié)議,即定義了上述物理層傳輸過來的數(shù)據(jù)應該以什么樣的格式去解析。

Modbus RTU

使用串口作為物理層協(xié)議時,通常采用的是 RS485 。

而我們在第一篇文章就說過,RS485 支持一主多從多個設備同時連接,所以使用 RS485 的 Modbus 同樣支持多個設備連接。在標準負載情況下,支持一個主機連接最多32個從機。并且在連接設備時,只能使用菊花鏈連接,不能使用星型網絡

圖片

另外,Modbus 是一種請求/應答協(xié)議,即只能通過主站(主機)發(fā)送請求給從站后,從站響應數(shù)據(jù)給主站,而不能從站直接主動發(fā)送數(shù)據(jù)給主站。

儲存區(qū)數(shù)據(jù)模型

在 Modbus 中定義了4種不同的數(shù)據(jù)模型,具體如下:

名稱 數(shù)據(jù)類型 訪問類型 說明
離散量輸入 單個比特(bit) 只讀 I/O系統(tǒng)提供
線圈 單個比特(bit) 讀寫 可通過應用程序改寫
輸入寄存器 字(word,16bit) 只讀 I/O系統(tǒng)提供
保持寄存器 字(word,16bit) 讀寫 可通過應用程序改寫

其中 線圈 和 離散量輸入 又可以稱為 輸出線圈 和 輸入線圈。

它們的數(shù)據(jù)長度都是一個 bit,即只能表示 1 或 0,表現(xiàn)在程序中就是一個 Boolean 類型的數(shù)據(jù)。對于安卓程序員來說,可能會疑惑啥是線圈,其實這兩個模型之所以叫做線圈是因為 Modbus 是為了 PLC 通信而編寫的協(xié)議,而在 PLC 中一些物理設備(例如繼電器)只有兩種狀態(tài):斷開與接通(即 0 或 1 ,或者 Boolean 的 false 與 true ),這些物理設備的狀態(tài)切換一般都是依賴于線圈的通/斷電來實現(xiàn),所以在 Modbus 中就將這種類型的數(shù)據(jù)稱為 線圈。

而 輸入寄存器 和 保持寄存器 又可以稱為 輸入寄存器 和 輸出寄存器。

它們的數(shù)據(jù)長度是一個 word,即 16 bit,2 byte,表現(xiàn)在程序中可以看成一個 Int 類型。

顯然,在同一個設備中不同的數(shù)據(jù)模型肯定不止一個可用的數(shù)據(jù)區(qū)塊,理論上來說,每種數(shù)據(jù)模型最大可以定義 65536 個數(shù)據(jù)區(qū)塊。

因此,每種數(shù)據(jù)模型的地址定義為如下:

數(shù)據(jù)模型 地址范圍
線圈 00001-09999
離散輸入 10001-19999
輸入寄存器 30001-39999
保持寄存器 40001-49999

可以看到,雖然我們上面說每種模型理論上支持 65536 個數(shù)據(jù)區(qū)塊,但是實際使用中每種數(shù)據(jù)模型一般都只會定義最大 10000 個數(shù)據(jù)區(qū)塊。

Modbus 允許將四種不同的數(shù)據(jù)模型存放在不同的數(shù)據(jù)區(qū)塊,這樣使用不同的功能碼(下面會說什么是功能碼)讀到的是不同的數(shù)據(jù):

圖片

同時,Modbus 也可以將不同的數(shù)據(jù)模型映射到同一個數(shù)據(jù)區(qū)塊中,這樣一來,不同的功能碼讀取到的可能是相同的數(shù)據(jù):

圖片

功能碼

在上一節(jié)我們介紹了儲存區(qū)數(shù)據(jù)模型,那么我們要如何去讀取不同的數(shù)據(jù)模型數(shù)據(jù)呢?或者說,在 Modbus 中是怎么區(qū)分不同的數(shù)據(jù)模型?

此時,就要用到 功能碼。

在 Modbus 中定義了三種類型的功能碼:

  • 公共功能碼 :Modbus 組織定義的標準的公開的通用的功能碼,包括已定義的和保留的功能碼
  • 用戶自定義功能碼 :用戶可以自定義自己需要的功能碼,范圍在 65-72 和 100-110(都是十進制)之間。
  • 保留功能碼 :一些公司的傳統(tǒng)設備中使用的功能碼,對公共功能碼無效。

圖片

公共功能碼定義了如下幾種:

圖片

而我們一般會使用到的有以下幾種:

圖片

可以看到,我們常用的有 8 個功能碼,其實仔細一看就能看出不過是讀所有數(shù)據(jù)模型;以及可寫數(shù)據(jù)模型和寫單個/寫多個的排列組合。

讀取數(shù)據(jù)時所有數(shù)據(jù)模型均支持只讀取單個和同時讀取多個數(shù)據(jù),并且使用的都是同一個功能碼。

寫入數(shù)據(jù)同樣支持只寫入單個數(shù)據(jù)和同時寫入多個數(shù)據(jù),但是寫入單個和寫入多個的功能碼是分開的。

可能有細心的讀者發(fā)現(xiàn)了,為什么表中的所有 寄存器地址 都是一樣的啊,這是因為上表中的 PLC 地址使用的是絕對地址,一般用于文檔中或程序中。

而實際設備的寄存器地址則使用的是相對地址。由于我們已經通過功能碼區(qū)分開了不同的數(shù)據(jù)區(qū)塊,所以為了節(jié)約傳輸時的字節(jié)占用,直接使用相對地址即可(如果使用絕對地址,那么現(xiàn)在的字節(jié)數(shù)不夠表示所有地址)。

主/從站

上文中提到過,使用串口的 Modbus 是主-從協(xié)議。即,在同一時刻,只有一個主節(jié)點和一個或多個子節(jié)點連接在同一個串行總線上。

Modbus 的通信總是由主節(jié)點發(fā)起,子節(jié)點響應。并且子節(jié)點之間不會相互通信。

在 Modbus 中,主節(jié)點沒有地址,每個子節(jié)點都有自己唯一的地址(1-247),通常稱為從站地址。

主節(jié)點有兩種方式發(fā)出請求:單播模式與廣播模式。

圖片

在單播模式中,主站(主節(jié)點)發(fā)送一個帶有從站(子節(jié)點)地址的請求給當前連接的所有設備,但是只有從站地址符合的從站會響應該請求,并返回數(shù)據(jù)。其他設備不會響應也不會執(zhí)行任何操作(讀取到地址不符合后直接拋棄這個請求報文)。在這個模式中會產生兩個報文:主站的請求報文和從站的響應報文。

在廣播模式中所有從站都不會發(fā)送響應報文給主站,但是會執(zhí)行請求的操作,并且主站的請求會發(fā)送給所有從站。廣播模式一般用于寫數(shù)據(jù)。此時主站發(fā)送的請求報文中的從站地址為 0 ,表示廣播。

數(shù)據(jù)幀

一個 Modbus RTU 的報文幀由 4 個部分組成:

8位從站地址+8位功能碼+最大252*8位數(shù)據(jù)+16位差錯校驗

圖片

在 RTU 中通常使用的錯誤校驗方式是 CRC 校驗(眼熟嗎?CRC 又出現(xiàn)了)

不知道你們有沒有發(fā)現(xiàn),這里的功能碼使用了 2 byte ,但是上面介紹功能碼時明明最大才到 127 ,那么剩下的一半去哪兒呢?

在 Modbus 定義中,從機如果能夠正確處理主機的請求,則返回報文中的功能碼將和主機請求的功能碼一樣,如果出現(xiàn)錯誤,無法正確的處理請求,則從機返回報文的功能碼將是最高位為 1 的功能碼,即 128-255 。

數(shù)據(jù)位在不同的功能碼以及主機請求還有從機響應都有不同的數(shù)據(jù)內容和長度,例如請求讀取線圈則數(shù)據(jù)位的內容為:2字節(jié)數(shù)據(jù)表示讀取線圈起始地址+2字節(jié)數(shù)據(jù)表示要讀取的線圈數(shù)量。

此時從機將會按照請求讀取的線圈數(shù)量返回數(shù)據(jù),數(shù)據(jù)格式為:1字節(jié)表示數(shù)據(jù)的字節(jié)數(shù)+N字節(jié)表示讀取到線圈狀態(tài)數(shù)據(jù)。如果讀取到的線圈狀態(tài)數(shù)據(jù)不是 8 位的整數(shù),則會在后面填充 0 使其滿足 8 位的倍數(shù)。

圖片

數(shù)據(jù)位在某些情況下,可以為空。

下面舉一個數(shù)據(jù)幀的完整例子(例子來自參考資料 1)。

我們有一個從站是溫濕度傳感器,從站地址為 1,它會將采集到的濕度寫入保持寄存器的 40001 區(qū)塊中;溫度寫入保持寄存器的 40002 區(qū)塊中。此時我們發(fā)送讀取保持寄存器請求去獲取它的溫濕度信息。

則,主機的請求報文為:

0103040146013B5A59

分別拆解這個數(shù)據(jù)幀為:

01 :從站地址

03 :功能碼,讀保持寄存器

00 00 :讀取的起始寄存器地址(對應 40001 的相對地址)

00 02 :讀取的寄存器長度(這里表示連續(xù)讀取兩個寄存器)

C4 0B :CRC校驗碼

從機在接收到請求后,響應報文為:

0103040146013B5A59

拆解數(shù)據(jù):

01:從站地址

03: 功能碼,讀保持寄存器

04 :讀取到的數(shù)據(jù)的字節(jié)長度(這里表示4字節(jié))

01 46 01 3B :讀取到的數(shù)據(jù),前兩個字節(jié)為濕度(換算成十進制為 326 ,即 32.6% ),后兩個字節(jié)為溫度(十進制為 315,即 31.5 攝氏度)

5A 59 :CRC校驗碼

這里提一句,別糾結為啥讀取到的溫濕度的值要除以 10 才是實際值,因為這是溫濕度傳感器廠家定義的。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • MODBUS
    +關注

    關注

    28

    文章

    1799

    瀏覽量

    76949
  • 串口通信
    +關注

    關注

    34

    文章

    1624

    瀏覽量

    55507
  • 安卓
    +關注

    關注

    5

    文章

    2126

    瀏覽量

    57145
收藏 人收藏

    評論

    相關推薦

    入門

    入門必備?。。。。。。。。。。。。?!
    發(fā)表于 03-11 10:53

    為何選擇智炫胎壓監(jiān)測?

    本帖最后由 recheid 于 2016-9-24 14:39 編輯 一、目前市場接大屏導航的胎壓監(jiān)測分為兩種第一種:串口通信胎壓監(jiān)測。
    發(fā)表于 09-24 10:21

    串口MODBUS教程1_入門教程

    串口MODBUS教程1_入門教程
    發(fā)表于 08-05 16:29

    板子下用什么樣的藍牙串口通信程序遙控

    問問各位的板子下用什么樣的藍牙串口通信程序遙控?
    發(fā)表于 07-17 06:58

    為何要將CH340的ATD+Eclipse工程移植到AndroidStudio

    CH340與Android串口通信為何要將CH340的ATD+Eclipse工程移植到AndroidStudio移植的具體步驟CH3
    發(fā)表于 08-09 06:42

    與ESP8266串口WIFI模塊的通信實現(xiàn)相關資料推薦

    Button分別對應相應的功能鍵。通信實現(xiàn)原理使用基于tcp協(xié)議的socket通信。串口WiFi模塊配置成tcp Service模式,然后
    發(fā)表于 01-18 08:34

    HAL庫入門串口通信學習經驗分享

    HAL庫入門串口通信學習經驗分享
    發(fā)表于 02-15 06:56

    設備如何通過USB與多串設備通信?

    本Demo僅適用于支持USB Host功能的設備與單個CH9342/CH9344多串設備通信。 點擊Scan按鈕,掃描并顯示多串設備,如下圖所示 點擊打開相應的設備,將自動獲取串口
    發(fā)表于 07-11 07:47

    單片機串口通信485modbus

    單片機串口通信485modbus.doc單片機串口通信485modbus.doc
    發(fā)表于 07-12 10:42 ?131次下載

    【HAL庫】串口通信

    HAL庫入門串口通信學習經驗分享
    發(fā)表于 12-16 16:58 ?5次下載
    【HAL庫】<b class='flag-5'>串口</b><b class='flag-5'>通信</b>

    用單片機串口modbus poll 進行通信

    由于程序中我的stm32單片機都是做的從機來和主機進行通信的,都是modbus協(xié)議通過串口來實現(xiàn)通信的。之前為了調通串口,所以用的是單片機的
    發(fā)表于 12-28 20:04 ?23次下載
    用單片機<b class='flag-5'>串口</b>和<b class='flag-5'>modbus</b> poll 進行<b class='flag-5'>通信</b>

    串口通信入門modbus(下)

    在之前的兩篇文章中,我們講解了串口的基礎知識和在中使用串口通信的方法,如果還沒看過之前文章的同學們,建議先看一遍,不然可能會不理解這篇文
    的頭像 發(fā)表于 04-23 17:40 ?4961次閱讀
    <b class='flag-5'>安</b><b class='flag-5'>卓</b>與<b class='flag-5'>串口</b><b class='flag-5'>通信</b><b class='flag-5'>入門</b><b class='flag-5'>之</b><b class='flag-5'>modbus</b>(下)

    端的串口通信實踐講解2

    這篇文章我們將講解端的串口通信實踐,即如何使用串口通信實現(xiàn)
    的頭像 發(fā)表于 04-23 17:59 ?1686次閱讀
    <b class='flag-5'>安</b><b class='flag-5'>卓</b>端的<b class='flag-5'>串口</b><b class='flag-5'>通信</b>實踐講解2

    端的串口通信實踐講解1

    這篇文章我們將講解端的串口通信實踐,即如何使用串口通信實現(xiàn)
    的頭像 發(fā)表于 04-23 17:59 ?2959次閱讀
    <b class='flag-5'>安</b><b class='flag-5'>卓</b>端的<b class='flag-5'>串口</b><b class='flag-5'>通信</b>實踐講解1

    串口Modbus教程1_入門教程V1.0

    串口Modbus教程1_入門教程V1.0
    發(fā)表于 04-29 13:29 ?21次下載
    RM新时代网站-首页