# 唯讀型記憶體-讀取指令(04)

{% hint style="info" %}
當數值較大時，若分別以不同資料格式（例如 float32 或 int64）進行讀取與換算，因內部計算方式不同，可能會出現非常小的差異，通常小於 1/10,000，屬於正常現象。讀取指令中register長度必需小於等於 20個 register。超過該長度的指令會被忽略。
{% endhint %}

### Function Code 功能碼 04

用途： 此記憶體區域專門用於儲存設備的即時狀態、測量結果和流量狀態相關的記憶體。

特性： 數據具有唯讀特性，只能通過讀取指令獲取數值，無法通過寫入指令進行修改。

### 唯讀型記憶體-讀取指令(04)格式 <a href="#kong-zhi-duan-fa-zhi-ling-04-ge-shi" id="kong-zhi-duan-fa-zhi-ling-04-ge-shi"></a>

<div align="left"><figure><img src="https://598628291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYbqXsfQyaXKmr6mxssGy%2Fuploads%2FNbUtM56PS7bOkGdRstwm%2Fmodbus-04-TX-diagram.png?alt=media&#x26;token=38bb50de-7a42-4d96-b360-578d2ee1dbbe" alt="" width="563"><figcaption></figcaption></figure></div>

<div align="left"><figure><img src="https://598628291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYbqXsfQyaXKmr6mxssGy%2Fuploads%2FhIqr4fxmvoEIw9VI04RU%2Fmodbus-04-RX-diagram.png?alt=media&#x26;token=55bb4c37-affc-4ce1-bdab-aed317ef8e51" alt="" width="563"><figcaption></figcaption></figure></div>

### Modbus RTU 讀取唯讀型記憶體讀取指令 (04) 範例

以唯讀型記憶體讀取指令（04）為例，說明在累積流量為 20000.5 公升時，應如何發送指令並將回傳的資料解析為十進位數值。

#### **主站發送讀取指令 (TX 訊框)**

根據設備規格，累積流量採 Float32 格式，佔用 2 個暫存器（共 4 bytes），因此讀取數量需設定為 00 02。主站需發送 Modbus 功能碼 04（讀取輸入暫存器），以讀取從位址 `0000` 開始的 2 個暫存器數據。

```
TX 請求指令： 01 04 00 00 00 02 71 CB
```

* Slave Address = 01
* Function Code = 04
* 起始暫存器位址 = 00 00
* 讀取數量 = 00 02 (2 個暫存器)
* CRC 校驗碼 = 71 CB

#### **從站回覆數據 (RX 訊框)**

從站收到讀取請求後，將內部儲存的 20000.5 升（Float32）數據，依 Modbus Register Big Endian（高位元組在前） 與 IEEE 754 Float32 格式，封裝為 4 個位元組回傳。

```
RX 回覆數據： 01 04 04 45 9C 40 00 E2 56
```

* Slave Address = 01
* Function Code = 04
* Byte Count（資料位元組數）= 04 (4 Bytes)
* Data（資料欄位） = 45 9C 40 00
* CRC 校驗碼 = E2 56&#x20;

#### **數據解析與轉換 (轉回十進制)**

步驟 A：排列數據

由於設定為 大端模式 (Big Endian)，資料的最高位元組放在最前面，因此 4 個位元組的順序就是收到的順序：

<p align="center">459C4000 ₁₆</p>

步驟 B：拆解 Float32 結構 (SEM: S-符號位, E-指數位, M-尾數位)

將 459C4000 ₁₆ 轉換為32位二進位制

<figure><img src="https://598628291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYbqXsfQyaXKmr6mxssGy%2Fuploads%2FOBAu8EKcArxKEYWqJFiH%2F459C4000.png?alt=media&#x26;token=15b8df15-a583-4d37-ae54-8b6053c909ad" alt=""><figcaption></figcaption></figure>

<table data-header-hidden><thead><tr><th width="112.7470703125"></th><th width="140.84765625"></th><th width="115.1005859375"></th><th></th></tr></thead><tbody><tr><td>部分</td><td>二進制數值</td><td>位元數</td><td>說明</td></tr><tr><td>S (符號位)</td><td>0</td><td>1 bit</td><td>0=正數</td></tr><tr><td>E (指數位)</td><td>10001011</td><td>8 bits</td><td><p>139₁₀。 實際指數：</p><p>139 - 127 (Float 32 偏移量) = 12</p></td></tr><tr><td>M (尾數位)</td><td>001110001...</td><td>23 bits</td><td>有效數字 1.M </td></tr></tbody></table>

#### 步驟 C：計算數值

根據 IEEE 754 公式：

<div align="left"><figure><img src="https://598628291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYbqXsfQyaXKmr6mxssGy%2Fuploads%2FV0v7wKL1pvweYHdPFgbh%2Fieee754.png?alt=media&#x26;token=bbf3be22-ea84-428c-a665-2a2ae17d3018" alt="" width="352"><figcaption></figcaption></figure></div>

• 指數位：E = 10001011 轉換為10 進位制

```
10001011₂ 
= (1 x 2⁷) + (0 x 2⁶) + (0 x 2⁵) +  (0 x 2⁴)
  + (1 x 2³) +  (0 x 2²) +  (1 x 2¹) +  (1 x 2⁰) 
= 128 + 0 + 0 + 0 + 8 + 0 + 2 + 1 
= 139₁₀
```

在 IEEE 754 Float32 標準中，指數位採用偏移表示法表示正指數和負指數，標準規定的偏移量 (Bias) 是 127，因此實際指數是 139 - 127 = 12

• 尾數部分：M=0011100100000000000000

&#x20;  有效數字 1.M：1.001110001 (後面的零可以忽略)

•  得根據 IEEE754 浮點數數值表示為

$$
(-1)⁰  ×  1.001110001 × 2¹²
$$

將小數點向右移動 12 位：

<div align="left"><figure><img src="https://598628291-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FYbqXsfQyaXKmr6mxssGy%2Fuploads%2FsyMJCnFtgiFB1kl3oLw9%2F20000.5.png?alt=media&#x26;token=4fc24d18-95b9-41ff-a5f0-3e2fd380417f" alt="" width="375"><figcaption></figcaption></figure></div>

•  將這個二進制數轉換回十進制：

```
數值 = 2¹⁴+2¹¹+2¹⁰+2⁹+2⁵+2⁻¹
    = 16384 + 2048 + 1024 + 512 + 32 + 0.5
    = 20000.5
```

得請求<mark style="background-color:red;">累積流量，RX 回覆數據： 01 04 04 45 9C 40 00 E2 56  值為 20000.5 升</mark>

### Modbus 不同格式間的轉換器

{% embed url="<https://codepen.io/philo_lorric/pen/BagqoRj>" %}
