banner
yono

yono

哈喽~欢迎光临
follow
github

modbus プロトコルの紹介

参考資料#

各ブログサイトは欠落や誤りがあり、レイアウトが乱れているため、参考にしないことをお勧めします。

ここに modbus 中国語サイトの資料があります

MODBUS プロトコル中国語版 / 英語版プレビューとダウンロード | Modbus IoT クラウドプラットフォーム

より権威のあるのは公式文書です

MODBUS アプリケーションプロトコル 1 1 b

および公式の他の文書は、ここで探すことができます

Modbus 仕様と実施ガイド

もちろん、公式文書にもあまり満足していません。彼らの古代の設計構造を維持するために、各フレームセグメントの紹介が直感的ではなく、少数の誤字もあります。

image

以下は自分が書き直した有効な情報です。

また、私自身が実装したライブラリがあります

stbanana/modbusX: modbus プロトコルサポート (github.com)

プロトコルの特徴#

全体フレーム構造#

メッセージヘッダーアドレスフィールド機能コードデータフィールドチェックフィールド
RTU1 バイト (スレーブ ID)1 バイトn バイト不定2 バイト (他のすべての内容の CRC-MB16)
TCP6 バイト
(2 バイトトランザクション番号 +
2 バイトプロトコル識別子 - 全て 0+
2 バイト後続バイトの総長 - スレーブ ID を含む)
1 バイト (スレーブ ID)1 バイトn バイト不定

メッセージヘッダーについては、公式文書の全体モデルではアドレスフィールドに分類されていますが、実際のバイトの総長にはスレーブ ID も含まれています。おそらく、初期のシリアルプロトコルのみの時に全体モデルが決まったため、新たに追加された modbusTCP は互換性のために無理をしているのでしょう。

私はここで直接再分類しましたが、標準ではありませんが、私はそれを好みます。

レジスタ属性#

RW 属性ビット数
コイル (0x01)読み書き可能1 ビット
離散入力レジスタ (0x02)読み取り専用1 ビット
ホールドレジスタ (0x03)読み書き可能16 ビット
入力レジスタ (0x04)読み取り専用16 ビット

全体モデル#

ソフトウェアを使用してメモリ構造を抽象化し、各アドレスに異なる意味のデータを格納します。FPGA が SRAM をシミュレートするのと同じ原理です。ただし、各レジスタアドレスは必ずしも 16 ビットではなく、1 ビットであることもあります。属性は RO\RW です。

RTU シリーズ#

(0x01) コイルの読み取り#

ホスト要求#

アドレスフィールド機能コード開始アドレスコイル数チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コードバイト数コイル状態チェックフィールド
1 バイト1 バイト1 バイト (計算コイル状態部分のバイト数)n バイト2 バイト (CRC-MB16)

#

20〜38 アドレスのコイルデータを読み取る要求をし、返信アドレスは低位から高位に、最終バイトが不足している場合は高位に 0 を埋めます。

[!NOTE]

最終的な出力状態 38-36 の返信バイトは、5 つの残りのビットをゼロで埋めます(高位端まで)。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x01機能コード0x01
開始アドレス高 8 ビット0x00バイト数0x03
開始アドレス低 8 ビット0x13出力状態 27-200xCD
出力数量高 8 ビット0x00出力状態 35-280x6B
出力数量低 8 ビット0x13出力状態 38-360x05
チェック CRC 低 8 ビット0xA9チェック CRC 低 8 ビット0x42
チェック CRC 高 8 ビット0xC8チェック CRC 高 8 ビット0x82

(0x02) 離散入力レジスタの読み取り#

ホスト要求#

アドレスフィールド機能コード開始アドレス離散入力数チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コードバイト数離散入力状態チェックフィールド
1 バイト1 バイト1 バイト (計算離散入力状態部分のバイト数)n バイト2 バイト (CRC-MB16)

#

197〜218 アドレスの離散入力レジスタデータを読み取る要求をし、返信アドレスは低位から高位に、最終バイトが不足している場合は高位に 0 を埋めます。

[!NOTE]

最終的な入力状態 218-213 の返信バイトは、2 つの残りのビットをゼロで埋めます(高位端まで)。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x02機能コード0x02
開始アドレス高 8 ビット0x00バイト数0x03
開始アドレス低 8 ビット0xC4入力状態 204-1970xAC
出力数量高 8 ビット0x00入力状態 212-2050xDB
出力数量低 8 ビット0x16入力状態 218-2130x35
チェック CRC 低 8 ビット0xB8チェック CRC 低 8 ビット0x22
チェック CRC 高 8 ビット0x39チェック CRC 高 8 ビット0x88

(0x03) 保持レジスタの読み取り#

ホスト要求#

アドレスフィールド機能コード開始アドレス保持レジスタ数チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コードバイト数保持レジスタ状態チェックフィールド
1 バイト1 バイト1 バイト (計算保持レジスタ状態部分のバイト数)n バイト2 バイト (CRC-MB16)

#

108〜110 アドレスの保持レジスタデータを読み取る要求をします。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x03機能コード0x03
開始アドレス高 8 ビット0x00バイト数0x06
開始アドレス低 8 ビット0x6Bレジスタ値高 8 ビット(108)0x02
レジスタ数量高 8 ビット0x00レジスタ値低 8 ビット(108)0x2B
レジスタ数量低 8 ビット0x03レジスタ値高 8 ビット(109)0x00
チェック CRC 低 8 ビット0x74レジスタ値低 8 ビット(109)0x00
チェック CRC 高 8 ビット0x17レジスタ値高 8 ビット(110)0x00
レジスタ値低 8 ビット(110)0x64
チェック CRC 低 8 ビット0x05
チェック CRC 高 8 ビット0x7A

(0x04) 入力レジスタの読み取り#

ホスト要求#

アドレスフィールド機能コード開始アドレス入力レジスタ数チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コードバイト数入力レジスタ状態チェックフィールド
1 バイト1 バイト1 バイト (計算入力レジスタ状態部分のバイト数)n バイト2 バイト (CRC-MB16)

#

9〜10 アドレスの保持レジスタデータを読み取る要求をします。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x04機能コード0x04
開始アドレス高 8 ビット0x00バイト数0x06
開始アドレス低 8 ビット0x6Bレジスタ値高 8 ビット(9)0x02
レジスタアドレス高 8 ビット0x00レジスタ値低 8 ビット(9)0x2B
レジスタアドレス低 8 ビット0x03レジスタ値高 8 ビット(10)0x00
チェック CRC 低 8 ビット0xC1レジスタ値低 8 ビット(10)0x00
チェック CRC 高 8 ビット0xD7チェック CRC 低 8 ビット0xF3
チェック CRC 高 8 ビット0xF4

(0x05) 単一コイルの書き込み#

[!NOTE]

単一コイルの書き込みでは、出力値部分は FF 00 が ON、00 00 が OFF を示すことのみ許可され、他の値は無効です。

ホスト要求#

アドレスフィールド機能コード出力アドレス出力値チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コードアドレス出力値チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

#

173 アドレスのコイルデータを ON に書き込む要求をします。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x05機能コード0x05
レジスタアドレス高 8 ビット0x00レジスタアドレス高 8 ビット0x00
レジスタアドレス低 8 ビット0xACレジスタアドレス低 8 ビット0xAC
レジスタ値高 8 ビット0xFFレジスタ値高 8 ビット0xFF
レジスタ値低 8 ビット0x00レジスタ値低 8 ビット0x00
チェック CRC 低 8 ビット0x4Cチェック CRC 低 8 ビット0x4C
チェック CRC 高 8 ビット0x1Bチェック CRC 高 8 ビット0x1B

(0x06) 単一保持レジスタの書き込み#

ホスト要求#

アドレスフィールド機能コード保持レジスタアドレスレジスタ値チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コード保持レジスタアドレスレジスタ値チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

#

2 アドレスの保持レジスタデータを 0x0003 に書き込む要求をします。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x06機能コード0x06
レジスタアドレス高 8 ビット0x00レジスタアドレス高 8 ビット0x00
レジスタアドレス低 8 ビット0x02レジスタアドレス低 8 ビット0x02
レジスタ値高 8 ビット0x00レジスタ値高 8 ビット0x00
レジスタ値低 8 ビット0x03レジスタ値低 8 ビット0x03
チェック CRC 低 8 ビット0x2Cチェック CRC 低 8 ビット0x2C
チェック CRC 高 8 ビット0x0Bチェック CRC 高 8 ビット0x0B

(0x0F) 複数コイルの書き込み#

ホスト要求#

アドレスフィールド機能コード開始アドレス設定数量バイト数設定値チェックフィールド
1 バイト1 バイト2 バイト2 バイト1 バイト (計算設定値部分のバイト数)n バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コード開始アドレス設定数量チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

#

20 アドレスから始まる 10 個のコイルを書き込む要求をします。

[!NOTE]

合計で 2 バイト (16 ビット) を書き込む必要があり、6 つの残りのビットをゼロで埋めます(高位端まで)。

コイルアドレス27262524232221202928
対応値1100110100000001

規格に従って埋めた後、実際の設定値セクションは 0xCD 0x01 であるべきです。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x0F機能コード0x0F
開始アドレス高 8 ビット0x00開始アドレス高 8 ビット0x00
開始アドレス低 8 ビット0x13開始アドレス低 8 ビット0x13
設定数量高 8 ビット0x00設定数量高 8 ビット0x00
設定数量低 8 ビット0x0A設定数量低 8 ビット0x0A
バイト数0x02チェック CRC 低 8 ビット0x24
設定値 (27〜20 アドレス)0xCDチェック CRC 高 8 ビット0x09
設定値 (29〜28 アドレス)0x01
チェック CRC 低 8 ビット0x72
チェック CRC 高 8 ビット0xCB

(0x10) 複数保持レジスタの書き込み#

ホスト要求#

アドレスフィールド機能コード開始アドレス設定数量バイト数設定値チェックフィールド
1 バイト1 バイト2 バイト2 バイト1 バイト (計算設定値部分のバイト数)n バイト2 バイト (CRC-MB16)

スレーブ応答#

アドレスフィールド機能コード開始アドレス設定数量チェックフィールド
1 バイト1 バイト2 バイト2 バイト2 バイト (CRC-MB16)

#

34 アドレスから始まる 4 つの保持レジスタを書き込む要求をします。

要求応答
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x10機能コード0x10
開始アドレス高 8 ビット0x00開始アドレス高 8 ビット0x00
開始アドレス低 8 ビット0x22開始アドレス低 8 ビット0x22
設定数量高 8 ビット0x00設定数量高 8 ビット0x00
設定数量低 8 ビット0x04設定数量低 8 ビット0x04
バイト数0x08チェック CRC 低 8 ビット0x61
設定値高 8 ビット (34 アドレス)0x00チェック CRC 高 8 ビット0xC0
設定値低 8 ビット (34 アドレス)0x40
設定値高 8 ビット (35 アドレス)0x00
設定値低 8 ビット (35 アドレス)0x24
設定値高 8 ビット (36 アドレス)0x00
設定値低 8 ビット (36 アドレス)0x01
設定値高 8 ビット (37 アドレス)0xBF
設定値低 8 ビット (37 アドレス)0x52
チェック CRC 低 8 ビット0x5F
チェック CRC 高 8 ビット0xCC

異常応答フレーム#

アドレスフィールド機能コード異常コードチェックフィールド
1 バイト1 バイト (機能コード + 0x80)1 バイト2 バイト (CRC-MB16)
異常コード名称意味
0x01不正な機能コード受信した要求命令の機能コードは許可されていない操作です。機能コードがサポートされていないか、エラー状態で要求を処理している可能性があります。
0x02不正なデータアドレス受信したデータアドレスは許可されていないアドレスです。特に、開始アドレスと転送長の組み合わせが無効です。100 個のレジスタを持つコントローラに対して、開始アドレス 96 と長さ 4 の要求は成功しますが、開始アドレス 96 と長さ 5 の要求は異常コード 0x02 を生成します。
0x03不正なデータ値実際にはデータセグメントが不正であることを意味します。たとえば、不正なデータセグメントの長さ、または書き込みまたは読み取りのレジスタ数とデータセグメントが一致しない場合です。レジスタに期待範囲外の値が書き込まれた場合や、実際に書き込みが失敗した場合(この場合は 0x04)を示すものではありません。
0x04スレーブデバイスの故障サーバー(またはスレーブ)がレジスタに対して要求された操作を実行する際にエラーが発生した場合、たとえばレジスタに期待範囲外の値が書き込まれた場合などです。
0x05確認実際にはエラーではなく、長時間の指令を受信したことを示し、受信して処理を開始したことを示します。
0x06従属デバイスが忙しい時間のかかる命令を処理中です(スレーブが空いている場合は、このエラーを引き起こした要求を再送信する必要があります)。
0x08ストレージのパリティエラー記録ファイルを読み取ろうとしましたが、メモリ内でパリティエラーが検出されました。
0x0A利用できないゲートウェイ経路ゲートウェイと一緒に使用され、ゲートウェイが要求を処理するために入力ポートから出力ポートへの内部通信経路を割り当てられないことを示します。通常、ゲートウェイが誤って構成されているか、過負荷であることを意味します。
0x0Bゲートウェイターゲットデバイスの応答失敗ゲートウェイと一緒に使用され、ターゲットデバイスからの応答が得られなかったことを示します。通常、デバイスがネットワークに存在しないことを意味します。

TCP シリーズ#

要するに、modbusTCP は RTU に比べて前のメッセージヘッダーをラッピングしただけで、CRC チェックを削除しました👍。== なぜなら、TCP 管理層のリンク伝送は非常に堅牢であり、シリアル伝送は堅牢ではないからです ==

メッセージヘッダーのトランザクション番号は、ホスト(TCP クライアント)が要求を開始する際に継続的に加算され、スレーブ(TCP サーバー)が要求に応答する際には、処理している要求を示すために同じトランザクション番号を返信します。したがって、modbusTCP は生まれつきマルチフレームの連続送信をサポートしており、ホストは応答を誤解することはありません👍。

個人的には、このようなスムーズな通信プロトコルがより好きです。|| 情報の正確性は物理リンク層に任せておけば良い、大雲大雲、チェックは依然として必要です ||

(0x01) コイルの読み取り#

ホスト要求#

トランザクション番号プロトコル識別子バイト総長アドレスフィールド機能コード開始アドレスコイル数
2 バイト2 バイト (全 0)2 バイト (後続バイト総長)1 バイト1 バイト2 バイト2 バイト

スレーブ応答#

トランザクション番号プロトコル識別子バイト総長アドレスフィールド機能コードバイト数コイル状態
2 バイト2 バイト (全 0)2 バイト (後続バイト総長)1 バイト1 バイト1 バイト (計算コイル状態部分のバイト数)n バイト

#

20〜38 アドレスのコイルデータを読み取る要求をし、返信アドレスは低位から高位に、最終バイトが不足している場合は高位に 0 を埋めます。

[!NOTE]

最終的な出力状態 38-36 の返信バイトは、5 つの残りのビットをゼロで埋めます(高位端まで)。

要求応答
トランザクション番号高 8 ビット0x00トランザクション番号高 8 ビット0x00
トランザクション番号低 8 ビット0x01トランザクション番号低 8 ビット0x01
プロトコル識別子 16 ビット (全 0)0x00 0x00プロトコル識別子 16 ビット (全 0)0x00 0x00
バイト総長高 8 ビット0x00バイト総長高 8 ビット0x00
バイト総長低 8 ビット0x06バイト総長低 8 ビット0x06
アドレスフィールド (スレーブ ID)0x01アドレスフィールド (スレーブ ID)0x01
機能コード0x01機能コード0x01
開始アドレス高 8 ビット0x00バイト数0x03
開始アドレス低 8 ビット0x13出力状態 27-200xCD
出力数量高 8 ビット0x00出力状態 35-280x6B
出力数量低 8 ビット0x13出力状態 38-360x05

他のプロトコルについては省略します

他のプロトコルについては省略します

要するに、modbusTCP は RTU に比べて前のメッセージヘッダーをラッピングしただけで、CRC チェックを削除しました👍。

この文は Mix Space によって xLog に同期更新されました。原始リンクは https://www.yono233.cn/posts/shoot/24_7_26_modbus

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。