Modbus関数コードの完全なParse:基本から高度までの21の標準関数コードの実践ガイド
キーワード:Modbus関数コード,Modbus Function Code,Modbus 0 1 0 2 0 3 0 4 0 5 0 6 15 16,Modbusリードレジスタ,Modbus書き込みコイル
コードマスターがスレーブに対して実行するOperation(データの読み取りまたは書き込み、操作対象がコイル、ディスクリート入力、ホールドレジスタ、または入力レジスタ)を定義します。各関数コードの目的、メッセージフォーマット、シナリオを理解することは、Modbus Communicationをマスターするための基盤です。
Modbusプロトコル仕様V 1.1 b 3をベースに、21の標準機能コード(共通機能コード、ユーザー定義機能コード、予約機能コードを含む)を体系的にParseし、完全なメッセージングサンプルとプログラミング実装を提供し、“熟練したエンジニア”から“真に理解したエキスパート”に移行するのに役立ちます。
Modbusデータモデルと関数コードの関係
関数コードを掘り下げる前に、Modbusのデータモデルを理解する必要があります。Modbusは4つのデータ領域を定義する。
| データ領域 | アクセスの種類 | サイズは | アドレス範囲 | 典型的な用途 |
|---|---|---|---|---|
| コイル | 読み取りと書き込み | 1 bit | 00001-09999 | デジタル量出力DO |
| “入力”rete Inputs | 読み取り専用 | 1 bit | 10001-19999 | 数値入力(DI) |
| レジスターの保持Holding Registers | 読み取りと書き込み | 16 bit | 40001-49999 | アナログ出力/パラメータ |
| 入力レジスタ | 読み取り専用 | 16 bit | 30001-39999 | アナログ入力(AI) |
重要なヒント:実プロトコルメッセージでは,0から始まる“プロトコルアドレス”を用いる.例えば、保持レジスタ40001に対応するプロトコルアドレスは0 x 0000である。この“オフセット1”のデザインは、初心者が最も混同しやすいところです。
2.機能コード分類システム
Modbus関数コードは大きく3つのカテゴリーに分類される。
- 公開機能コード(1- 6 4、73-99、11 1 - 1 27)Modbus組織によって標準化され、異なるベンダーのデバイス間の相互運用性を保証
- ユーザー定義機能コード(65- 7 2、100-110):機器メーカーにカスタム実装を任せ、汎用性はない
- 機能コードの保存:従来の製品(8-11、12-15など)で使用されています。
三、ビット操作機能コードBit Access深度解析
3.1ファンクションコード0x01-リードコイルRead Coils
機能性:スレーブからの連続コイルDOのON/OFF状態を読み取ります。これは最も基本的なビット読み取りOperationです。
要求メッセージRTU
駅からの住所|0 x 0 1|開始アドレスが高い|低アドレス開始|高いvalueの|低ボリュームです|CRCは
例:ステーション1からのコイル0 x 0 0 1 3 ~ 0 x 0 0 3 7(コイル番号20~56、合計37個)の読み取り
0 1 0 1 0 0 13 0 0 25【CD】
→スレーブアドレス=1、ファンクションコード= 0x01、開始アドレス= 0x0013 19、Quantity= 0x0025 37メッセージへの応答:
駅からの住所|0 x 0 1| Bytesの数|データは..。| CRCは
0 1 0 1 0 5 CD 6 B 2 0 E 1 B(CRC)
→ 5バイトデータ、CD=1100 1101コイル27-20の主な制約:
- 1回の読み取りで最大2,000コイル(0 x 0 7 D0)
- 応答におけるビットパッキング規則:最初のバイトのLSBが開始アドレスコイルに対応する
- リクエストの数が8の倍数でない場合、最後のバイトの上位ビットは0で埋められます。
3.2ファンクションコード0x02-ディスクリート入力を読み取りRead Discrete Inputs
機能性:スレーブステーションから連続離散入力(DI)の状態を読み取ります。メッセージ形式は0 x 0 1とまったく同じですが、読み取り専用のディスクリート入力領域をOperationします。
0 x 0 1との違い:0 x 01は読み書き可能なコイル(通常は物理 DO)を読み取り、0 x 02は読み取り専用のディスクリート入力(通常はリミットスイッチ、センサ状態などの物理 DI)を読み取ります。
例:ステーション1からのディスクリート入力0 x 0 0 C 4 ~ 0 x 0 0 DB(197~220、合計24個)を読み取る
要求01 02 00 C4 00 18 [CRC]
応答01 02 03 AC DB 35 [CRC]
→ 3バイト、AC=1010 1100、DB=1101 1011、35=0011 01013.3ファンクションコード0x05-単一コイルに書き込むWrite Single Coil
機能性:個々のコイルをONまたはOFFにします。これは最も簡単な書き込みOperationです。
メッセージのリクエスト:
駅からの住所|0 x 0 5|コイルアドレスHigh| Coil Address Lowシングル|出力が高い。|出力値が低い。|CRCは
出力値0xFF00はON、0x0000はOFF
例スレーブ1のコイル0 x 00AC(No. 173)をONにする
0 1 0 5 0 0 AC FF 00(CRC)メッセージへの応答:通常のレスポンスはリクエストと完全に一致しています(エコー)。
プログラミング例Python
minimalmodbusのインポート
instr = minimalmod.Instrument/dev/ttyUSB01
instrument.serial.baudrate = 96 00
#単一コイルへの書き込みアドレス0x00 AC = ON
instrument.write_bit 0x00AC 13.4ファンクションコード0x0F-複数のコイルを書き込むWrite Multiple Coils
機能性:複数の連続したコイルを一度に書き込む。複数のDOを同時に制御する必要がある場合、0 x 0Fは0 x 0 5を複数回呼び出すよりもはるかに効率的です。
要求メッセージ形式
駅からの住所|0 x 0 F|開始アドレスが高い|低アドレス開始|高いvalueの|低ボリュームです|Bytesの数|データは..。| CRCは
例:スレーブステーション1のコイル0 x 0 0 1 3 ~ 0 x 0 01 C(20~29、合計10コイル)をそれぞれVrefとします。
20 ON、21 OFF、22 ON、23 ON、24 OFF、25 ON、26 ON、27 OFF、28 ON、29 OFF
2进01 0110 1101 →上位补0 → 0xCD01...ここでは慎重な計算が必要です
実際のメッセージ01 0F 00 13 00 0A 02 CD 01 [CRC]レジスタ操作関数コード(16ビットアクセス)の詳細解析
4.1機能コード0 x 03 -リード·ホールド·レジスタRead Holding Registers
機能性:连続保持レジスタの値を読み込む。これはModbusで最も頻繁に使用される関数コードの1つではない。ほとんどのデータ収集シナリオでは0 x 03が使用されます。
要求メッセージ形式
駅からの住所|0 x 0 3|開始アドレスが高い|低アドレス開始|レジスタ数が多い。|レジスタ数が少ない|CRCは
例:スレーブ1の保持レジスタ0 x 006B~ 0 x 006D(108~110、计3レジスタ)を読み出す
要求01 03 00 6B 00 03 [CRC]
応答01 03 06 02 2B 00 00 00 64 [CRC]
6バイト= 3レジスタ× 2
→レジスタ108 0x022 B = 555
→レジスタ109 0 x 0000 = 0
→レジスタ110 0x0064 = 100主な制約:
- 最大125個のレジスタ(0 x 0 0 7 D)を1回に読み出す
- 32ビットデータ(float32/int32)を読み込む場合は、レジスタ数が偶数であることを確認します。
- エンディアンの問題:異なるデバイスがビッグエンディアンまたはリトルエンディアンを使用してマルチバイトのデータを格納することがある
4.2機能コード0 x 0 4-リード入力レジスタRead Input Registers
機能性:連続入力レジスタの値を読み出す。メッセージ形式は0 x 0 3とまったく同じですが、読み取り専用の入力レジスタ領域(ADCサンプル値、センサ生値など)をOperationします。
例:ステーション1から入力レジスタ0 x 0 0 08(アドレス9、AIチャネル1)を読み取る
要求01 04 00 08 00 01 [CRC]
応答01 04 02 00 0A [CRC]
入力レジスタ9の値= 0 x 000A = 104.3ファンクションコード0x06-単一レジスタへの書き込みWrite Single Register
機能性:単一の保持レジスタに16ビットの値を書き込む。
要求メッセージ形式
駅からの住所|0 x 0 6|レジスタアドレスが高い|レジスタアドレスが低い|書き込み値が高い|書き込み値が低い|CRCは
例:ステーション1の保持レジスタ0 x 00 01から0 x 00 03への書き込み
リクエスト01 06 00 01 00 03 [CRC]
応答01 06 00 01 00 03 [CRC]エコープログラミングの例(C#):
//NModbus4ライブラリの使用
Modbus.Deviceの使用
システム.IO.Portsの使用
var port = new SerialPort(“COM3”,96 00,Parity.None,8,StopBits.One);
port.Open;
var master = ModbusSerialMaster. Rport;
master.WriteSingleRegister 1 0x0001 3; //スレーブ1アドレス1値34.4ファンクションコード0 x 10 -複数のレジスタを書き込むWrite Multiple Registers
機能性:複数の連続保持レジスタを一度に書き込む。これは、バッチ構成パラメータの効率ツールです。
要求メッセージ形式
駅からの住所|0 x 10|開始アドレスが高い|低アドレス開始|レジスタ数が多い。|レジスタ数が少ない|Bytesの数|データは..。| CRCは
例:スレーブ1のレジスタ0 x 00 01と0 x 00 02にそれぞれ0 x 000Aと0 x 0102を書き込む
要求01 10 00 01 00 02 04 00 0A 01 02 [CRC]
→バイト数=4(レジスタ2個×2)
応答01 10 00 01 00 02 [CRC]
→レスポンスは開始アドレスとレジスタ数のみを返します。主な制約:
- 1回の書き込みで最大123個のレジスタ(0 x 0 0 7 B)
- バイト数は“レジスタ数× 2”になること。
- 書き込み失敗によりスレーブのパラメータが混乱する可能性があるため、バックアップを先に推奨
5.高度な機能コードの詳細
5.1機能コード0x07-読み取り例外ステータスRead Exception Status
機能性:スレーブステーションの8つの異常状態ビットを高速に読み取ります。これはシンプルで強力な診断機能コードで、リクエストはわずか2バイト(アドレス+機能コード)で、レスポンスはわずか3バイトです。
要求01 07 [CRC]
応答01 07 6D [CRC]
→ステータスバイト0 x 6 D = 0 1 10 1101、各ベンダーが定義したビットの意味5.2機能コード0x08-診断
機能性:Communicationリンク診断には16のサブ機能コードがあります。最も一般的な使用法は、スレーブがオンラインでメッセージを正常に処理できるかどうかを検出する“ループバックテスト”(サブファンクションコード0 x 0000)です。
| サブ機能コード | 名前は | 目的は |
|---|---|---|
| 0x0000 | ループテスト | 要求データのエコー、Communicationリンクの検証 |
| 0x000A | クリアカウンター。 | Communicationイベントカウンタをクリア |
| 0x000B | リードバスメッセージ数 | スレーブ検出されたバス·メッセージの合計数の読み取り |
| 0x000C | 読み取りCommunicationエラー数 | CRCチェックエラーの読み取り回数 |
| 0x000D | 読み取り例外エラー数 | ステーションから返された例外応答の読み取り回数 |
| 0x000E | 読み取りスレーブメッセージ数 | スレーブで処理されたメッセージの読取り数 |
| 0x000F | 読み取りスレーブ応答数 | ブロードキャストのために応答が不要なメッセージの読み取り数 |
回路テスト例
要求01 08 00 00 12 34 [CRC] →サブファンクションコード= 0x0000、データ= 0x1234
レスポンス01 08 00 00 12 34 [CRC] →要求データを完全にエコーする必要があります5.3機能コード0 x 0B -読み取りCommunicationイベントカウンタ
通信品質を監視するためにスレーブのCommunicationイベントカウンタとステータスワードを返します。
5.4機能コード0 x 16 -マスク書き込みレジスタ
機能性:ANDマスクとORマスクを使用して、単一のレジスタをビットOperationします。これはModbusの最も独創的な関数コードの1つで、現在の値を読み取ることなくレジスタの特定のビットをアトミックに変更することができます。
要求メッセージ形式
駅からの住所|0 x 16|アドレスは高い。|アドレスは低い。|マスクが高い。|マスクが低い。|マスクが高い。|マスクが低い。|CRCは
オペレーションロジックResult = Current_Value AND And_Mask OR Or_Mask AND NOT And_Mask
例:レジスタ0 x 00 04のビット0~3をクリアし、ビット4~7 = 0 b 1010を設定します。
ANDマスク= 0xFFF0下位4ビットをクリア、ORマスク= 0x00 A0ビット5とビット7を
要求01 16 00 04 FF F0 00 A0 [CRC]六、機能コード比較クイックチェック表
| 関数コードの特徴 | 名前は | オペレーショナルオブジェクト | オペレーションの種類 | 最大のvalue。 | 使用頻度は |
|---|---|---|---|---|---|
| 0x01 | Read Coils | コイルコイルコイル | 読書をする。 | 2000 | ★★★★☆ |
| 0x02 | Read Discrete Inputs | ショップ型入力 | 読書をする。 | 2000 | ★★★☆☆ |
| 0x03 | Read Holding Registers | レジスタを保持する。 | 読書をする。 | 125 | ★★★★★ |
| 0x04 | Read Input Registers | 入力レジスタ。 | 読書をする。 | 125 | ★★★★☆ |
| 0x05 | Write Single Coil | コイルコイルコイル | 書くこと。 | 1 | ★★★☆☆ |
| 0x06 | Write Single Register | レジスタを保持する。 | 書くこと。 | 1 | ★★★★★ |
| 0x0F | Write Multiple Coils | コイルコイルコイル | 書くこと。 | 1968 | ★★★☆☆ |
| 0x10 | Write Multiple Registers | レジスタを保持する。 | 書くこと。 | 123 | ★★★★★ |
| 0x16 | Mask Write Register | レジスタを保持する。 | 読み取りと書き込み | 1 | ★★☆☆☆ |
| 0x17 | Read/Write Multiple Regs | レジスタを保持する。 | 読み取りと書き込み | 125/121 | ★★☆☆☆ |
関数コード選択決定木
実際の開発では、適切な作業コードを選択することが重要な決定です。選択の意思決定プロセスを次に示します。
- デジタル出力ステータスが必要ですか?→ 0 x 0 1(コイル)/0 x 0 2(ディスクリート入力)
- シミュレーションやパラメータが必要ですか?→ 0 x 0 3(保持レジスタ)/0 x 0 4(入力レジスタ)
- 単一のデジタル出力が必要ですか?→ 0x05
- 単一パラメータが必要?→ 0x06
- パラメータが必要?→ 0x10
- デジタル出力が必要ですか?→ 0x0F
- 他のビットに影響を与えずにパラメータの一部を変更する必要がありますか?→ 0x16
- 読み書きを同時に行う必要がありますか(古いパラメータを読み取り、新しいパラメータを書き込むアトミックOperationなど)。→ 0x17
一般的な落とし穴とベストプラクティス
8.1バイトオーダー·トラップ
Modbusプロトコルは16ビットレジスタでビッグエンディアンを使用することを規定しているが、32ビットデータ(float32など)のエンディアンはプロトコルレベルでは規定されていない。一般的には4つの配置がある。
| 配置の仕方 | レジスタ1。 | レジスタ2。 | 通常のメーカー。 |
|---|---|---|---|
| ABCD (Big-Endian) | トップ16。 | 背番号は16。 | シュナイダー、ABB |
| CDAB (Little-Endian) | 背番号は16。 | トップ16。 | シーメンスS 7 - 200 |
| BADC (Word-Swap Big) | バイトスワップ | - | 一部の国産ブランド |
| DCBA (Word-Swap Little) | 完全に逆さま。 | - | 少数の特殊装備 |
8.2アドレス(アドレス0)
RTUモードでは、ブロードキャストはスレーブアドレス0を使用します。すべてのスレーブがコマンドを実行しますが、応答は返されません。ブロードキャストは、書き込み機能コード(0 x 0 5、0 x 0 6、0 x 0F、0 x 10)のみサポートされます。
8.3 1回のリクエストは不要。
0 x 0 3は一度に125個のレジスタを読み取ることができるが、一度に多くのレジスタを読み取ることは推奨されない。理由は:
- 通信遅延の増加(ボーレート96 00で125レジスタで約270ms)
- CRCチェックエラーの確率を高める
- 一部のスレーブのメモリ制限によりバッファオーバーフローが発生する可能性がある
推奨事項:単回の読み出しは20~50レジスタ以内に抑え、の小ロットにminけて読み出す。
ケーススタディ:Modbusデータ収集システムの構築
以下は、異なる関数コードを組み合わせる方法を示す典型的なModbusデータ収集フローです。
// C擬似コード- 典型的なModbus取得プロセス
void modbus_acquisition_task void {
//ステップ1デバイスステータスの読み取りディスクリート入力
uint8_t di_data[2];
mod_read_inputs 0x02 di_data 16; //16个のDIを読み込む
//ステップ2アナログvalueを読み込む(レジスタ入力)
uint16_t ai_data[8];
mod_read_input_regs 0x00 ai_data 8; //8つのAIチャネルを読み込む
//ステップ3ランパラメータの読み込み(レジスタを保持)
uint16_t params[20];
mod_read_hing_regs 0x00 params 20;
//ステップ4ビジネスロジックに基づいて制御コマンドを書き込む
if need_start_motor {
modbus_write_coil 0 x 0005,1; //モーターを始動
}
//手順5パラメータを変更する必要がある場合
if need_set_temp {
mod__register 0x0010 250; //temperature 25.0°C
}
}X.サマリー
関数コードはModbusプロトコルの“動詞”であり、マスターがスレーブに対して行うことを定義します。ファンクションコードのメッセージフォーマットと適用シナリオをマスターすることは、Modbus Communicationのコア構文をマスターすることに等しい。本稿の関数コードクイックチェックテーブルと決定木は、日常開発のリファレンスマニュアルとして使用し、実際のデバッグで徐々に理解を深めることを提案する。
次の記事では、Modbus RTUとModbus TCPの2つの伝送モードの違いを深く比較し、物理層からアプリケーション層までの適用シナリオと性能特性を包括的に分析します。
関連する読書:Modbus例外応答コードとトラブルシューティング完全マニュアル|Modbus RTUとTCPの比較|Modbus CRC検証原理とプログラミング実装
Leave a Reply