Обнови спецификацию и таблицы единого Modbus

This commit is contained in:
2026-10-23 16:15:37 +03:00
parent 41f5b879fc
commit 83fb9b6fe8
9 changed files with 180 additions and 70 deletions
+33 -5
View File
@@ -3,7 +3,7 @@
> GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Полный контракт: [ОАП](../../../../doc/setcan/protocan/OAP.md). Существующие регистровые сервисы сохраняют свои адреса. > GAS `0x3` использует адреса отдельных 16-битных регистров. GAS SLOT `0x4` — отдельный сервис с маской в Word0 и тремя значениями Word1…Word3. Полный контракт: [ОАП](../../../../doc/setcan/protocan/OAP.md). Существующие регистровые сервисы сохраняют свои адреса.
Статус: **Stable с зарезервированным загрузочным расширением** Статус: **Stable с зарезервированным загрузочным расширением**
Версия: **2.1: GAS 0x3 и масочный GAS SLOT 0x4**<br> Версия: **2.2: единый Modbus 0x5, функции и количество 1…4**<br>
Порядок байтов payload: **little-endian**, если явно не указано иное Порядок байтов payload: **little-endian**, если явно не указано иное
## Назначение ## Назначение
@@ -63,9 +63,8 @@ can_id =
| `0x2` | `ANALOG` | оба | 0…8 | stable | | `0x2` | `ANALOG` | оба | 0…8 | stable |
| `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 | | `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 |
| `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения | | `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения |
| `0x5` | `MODBUS_DISCRETE` | оба | 0…8 | stable | | `0x5` | `MODBUS` | оба | 0/1/2/4/6/8 | функции 1…4, количество 1…4 |
| `0x6` | `MODBUS_HOLDING` | оба | 0…8 | stable | | `0x6…0x7` | резерв | — | — | свободны |
| `0x7` | `MODBUS_INPUT` | оба | 0…8 | stable |
| `0x8` | `ERROR` | прибор → ПМ | 0 | stable | | `0x8` | `ERROR` | прибор → ПМ | 0 | stable |
| `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft | | `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft |
| `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft | | `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft |
@@ -83,7 +82,7 @@ can_id =
|---|---| |---|---|
| broadcast | команда `[15:4]`, параметр `[3:0]` | | broadcast | команда `[15:4]`, параметр `[3:0]` |
| discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` | | discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` |
| Modbus | начальный адрес `[15:4]`, количество `[3:0]` | | Modbus 0x5 | адрес `[15:4]`, функция − 1 `[3:2]`, количество − 1 `[1:0]` |
| GAS 0x3 | адрес первого 16-битного регистра `[15:0]` | | GAS 0x3 | адрес первого 16-битного регистра `[15:0]` |
| GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 | | GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 |
| error | дополнительная информация `[15:8]`, код `[7:0]` | | error | дополнительная информация `[15:8]`, код `[7:0]` |
@@ -91,6 +90,35 @@ can_id =
| boot control/status | `SessionID[15:8]`, команда `[7:0]` | | boot control/status | `SessionID[15:8]`, команда `[7:0]` |
| boot data | `BlockIndex[15:0]` | | boot data | `BlockIndex[15:0]` |
## Единый Modbus `0x5`
Все четыре банка используют один `MsgType=0x5`. Коды `0x6` и `0x7` свободны.
Начальный адрес занимает `[15:4]` и лежит в диапазоне `0x000…0xFFF`.
Биты `[3:2]` содержат `Function − 1`, биты `[1:0]` — `RegCount − 1`.
Физические значения функции и количества: **1…4**. Всё окно должно помещаться
в 4096 адресов: `StrAdr + RegCount ≤ 4096`.
| Функция | Банк | Элемент | DLC данных |
|---:|---|---|---|
| 1 | Coil | дискретный выход | 1 байт для 1…4 битов |
| 2 | Discrete | дискретный вход | 1 байт для 1…4 битов |
| 3 | Holding | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт |
| 4 | Input | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт |
Это селектор банка в ProtoCAN по нумерации функций Modbus, без RTU-заголовка
и CRC. Сохраняется правило ProtoCAN: `Route=0, DLC=0` читает окно;
непустой payload записывает Coil/Holding, Discrete/Input доступны только
для чтения. Ответ имеет `Route=1`, сохраняет `MsgBody` и содержит значения
либо эхо успешной записи. RTR запрещён. Биты упакованы начиная с младшего,
старшие неиспользуемые биты нулевые. Регистры передаются little-endian.
Пример: адрес `0x123`, функция 3, четыре регистра дают
`MsgBody = (0x123 << 4) | ((3 − 1) << 2) | (4 − 1) = 0x123B`.
Изменение wire-формата несовместимо с прежними отдельными типами
`0x5/0x6/0x7`: узлы и клиенты обновляются согласованно. Тип GAS SLOT `0x4`
сохраняет своё назначение.
## Общие правила обмена ## Общие правила обмена
- Многобайтовые значения в `DATA` передаются little-endian. - Многобайтовые значения в `DATA` передаются little-endian.
File diff suppressed because one or more lines are too long
+80 -26
View File
File diff suppressed because one or more lines are too long
+3
View File
@@ -7,6 +7,9 @@
### Changed — 2026-10-23 ### Changed — 2026-10-23
- Modbus Discrete/Holding/Input объединены в MsgType 0x5; Coil/Discrete/Holding/Input выбираются функцией 1…4, количество ограничено 1…4.
- Body Modbus: адрес [15:4], функция минус один [3:2], количество минус один [1:0]; номера 0x6/0x7 освобождены.
- GAS 0x3 возвращён к адресации отдельных 16-битных регистров 0…65535, DLC 0/2/4/6/8. - GAS 0x3 возвращён к адресации отдельных 16-битных регистров 0…65535, DLC 0/2/4/6/8.
- Слотный GAS перенесён на 0x4 вместо MODBUS_COIL; Word0 содержит маску битов 1…3, Word1…Word3 — значения. - Слотный GAS перенесён на 0x4 вместо MODBUS_COIL; Word0 содержит маску битов 1…3, Word1…Word3 — значения.
- PERIPH сохраняет 200 значений на mode в 67 слотах; последний содержит два значения. - PERIPH сохраняет 200 значений на mode в 67 слотах; последний содержит два значения.
+1 -1
View File
@@ -62,7 +62,7 @@ Provider проверяет все выбранные права и значен
Word0 — метаданные кадра, не четвёртый хранимый регистр. Координата значения — Word0 — метаданные кадра, не четвёртый хранимый регистр. Координата значения —
`(SlotAddress, WordIndex)`, где `WordIndex=1…3`. Любой узел поддерживается общими `(SlotAddress, WordIndex)`, где `WordIndex=1…3`. Любой узел поддерживается общими
`pcan_gas_slot_id()` и `pcan_gas_slot_handle_address()`; адрес слота не ограничен страницами PERIPH. `pcan_gas_slot_id()` и `pcan_gas_slot_handle_address()`; адрес слота не ограничен страницами PERIPH.
Тип `0x4 MODBUS_COIL` заменён этим сервисом. Modbus `0x5/0x6/0x7` сохраняет номера. Тип `0x4 MODBUS_COIL` заменён этим сервисом. Единый Modbus использует `0x5`, функцию и количество 1…4 в Body; `0x6/0x7` свободны.
Старое оборудование с Coil 0x4 требует согласованного обновления; автоопределения формата нет. Старое оборудование с Coil 0x4 требует согласованного обновления; автоопределения формата нет.
## PERIPH: проекция 200 слов на слоты 0x4 ## PERIPH: проекция 200 слов на слоты 0x4
+33 -5
View File
@@ -1,7 +1,7 @@
# ProtoCAN — базовый протокол # ProtoCAN — базовый протокол
Статус: **Stable с зарезервированным загрузочным расширением**<br> Статус: **Stable с зарезервированным загрузочным расширением**<br>
Версия: **2.1: GAS 0x3 и масочный GAS SLOT 0x4**<br> Версия: **2.2: единый Modbus 0x5, функции и количество 1…4**<br>
Порядок байтов payload: **little-endian**, если явно не указано иное Порядок байтов payload: **little-endian**, если явно не указано иное
## Назначение ## Назначение
@@ -61,9 +61,8 @@ can_id =
| `0x2` | `ANALOG` | оба | 0…8 | stable | | `0x2` | `ANALOG` | оба | 0…8 | stable |
| `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 | | `0x3` | `GAS` | оба | 0/2/4/6/8 | регистры 0…65535 |
| `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения | | `0x4` | `GAS_SLOT` | оба | 0/8 | Word0 — маска, Word1…Word3 — значения |
| `0x5` | `MODBUS_DISCRETE` | оба | 0…8 | stable | | `0x5` | `MODBUS` | оба | 0/1/2/4/6/8 | функции 1…4, количество 1…4 |
| `0x6` | `MODBUS_HOLDING` | оба | 0…8 | stable | | `0x6…0x7` | резерв | — | — | свободны |
| `0x7` | `MODBUS_INPUT` | оба | 0…8 | stable |
| `0x8` | `ERROR` | прибор → ПМ | 0 | stable | | `0x8` | `ERROR` | прибор → ПМ | 0 | stable |
| `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft | | `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft |
| `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft | | `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft |
@@ -81,7 +80,7 @@ can_id =
|---|---| |---|---|
| broadcast | команда `[15:4]`, параметр `[3:0]` | | broadcast | команда `[15:4]`, параметр `[3:0]` |
| discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` | | discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` |
| Modbus | начальный адрес `[15:4]`, количество `[3:0]` | | Modbus 0x5 | адрес `[15:4]`, функция − 1 `[3:2]`, количество − 1 `[1:0]` |
| GAS 0x3 | адрес первого 16-битного регистра `[15:0]` | | GAS 0x3 | адрес первого 16-битного регистра `[15:0]` |
| GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 | | GAS SLOT 0x4 | адрес слота `[15:0]`; маска — в Word0 payload, значения — Word1…Word3 |
| error | дополнительная информация `[15:8]`, код `[7:0]` | | error | дополнительная информация `[15:8]`, код `[7:0]` |
@@ -91,6 +90,35 @@ can_id =
Контракт обоих GAS: [OAP.md](OAP.md). Тип 0x3 адресует отдельные слова; тип 0x4 имеет маску битов 1…3 в Word0 и три значения. Для PERIPH 0x4 используются 67 слотов `0xMM00…0xMM42`, последний содержит два значения. Старый Coil 0x4 заменён; формат определяется MsgType. Контракт обоих GAS: [OAP.md](OAP.md). Тип 0x3 адресует отдельные слова; тип 0x4 имеет маску битов 1…3 в Word0 и три значения. Для PERIPH 0x4 используются 67 слотов `0xMM00…0xMM42`, последний содержит два значения. Старый Coil 0x4 заменён; формат определяется MsgType.
## Единый Modbus `0x5`
Все четыре банка используют один `MsgType=0x5`. Коды `0x6` и `0x7` свободны.
Начальный адрес занимает `[15:4]` и лежит в диапазоне `0x000…0xFFF`.
Биты `[3:2]` содержат `Function − 1`, биты `[1:0]` — `RegCount − 1`.
Физические значения функции и количества: **1…4**. Всё окно должно помещаться
в 4096 адресов: `StrAdr + RegCount ≤ 4096`.
| Функция | Банк | Элемент | DLC данных |
|---:|---|---|---|
| 1 | Coil | дискретный выход | 1 байт для 1…4 битов |
| 2 | Discrete | дискретный вход | 1 байт для 1…4 битов |
| 3 | Holding | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт |
| 4 | Input | 16-битный регистр | `2 × RegCount`, 2/4/6/8 байт |
Это селектор банка в ProtoCAN по нумерации функций Modbus, без RTU-заголовка
и CRC. Сохраняется правило ProtoCAN: `Route=0, DLC=0` читает окно;
непустой payload записывает Coil/Holding, Discrete/Input доступны только
для чтения. Ответ имеет `Route=1`, сохраняет `MsgBody` и содержит значения
либо эхо успешной записи. RTR запрещён. Биты упакованы начиная с младшего,
старшие неиспользуемые биты нулевые. Регистры передаются little-endian.
Пример: адрес `0x123`, функция 3, четыре регистра дают
`MsgBody = (0x123 << 4) | ((3 − 1) << 2) | (4 − 1) = 0x123B`.
Изменение wire-формата несовместимо с прежними отдельными типами
`0x5/0x6/0x7`: узлы и клиенты обновляются согласованно. Тип GAS SLOT `0x4`
сохраняет своё назначение.
## Общие правила обмена ## Общие правила обмена
Профиль синхронизации часов и сообщения платы о завершении инициализации: Профиль синхронизации часов и сообщения платы о завершении инициализации:
+12 -13
View File
@@ -1205,20 +1205,21 @@ DATA[4..7] RunningCRC32, uint32 little-endian
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">Word3 | Word2 | Word1 | Word0: маска битов 1…3</td> <td colspan="8" class="x97">Word3 | Word2 | Word1 | Word0: маска битов 1…3</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:34px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td colspan="4" class="x144">&nbsp;</td> <td colspan="4" class="x144">&nbsp;</td>
<td colspan="4" class="x148">0x5. Modbus Discrete</td> <td colspan="4" class="x148">0x5. Modbus</td>
<td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td> <td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td>
<td colspan="4" class="x161">Кол-во регистров (0-15)</td> <td colspan="2" class="x161">Функция (1–4)</td>
<td colspan="2" class="x161">Кол-во регистров (1–4)</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="4" class="x97">&nbsp;</td> <td colspan="4" class="x97">0/1/2/4/6/8</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">NULL</td> <td colspan="8" class="x97">FC1/2: биты; FC3/4: слова LE</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:17px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
@@ -1227,13 +1228,12 @@ DATA[4..7] RunningCRC32, uint32 little-endian
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td colspan="4" class="x144">&nbsp;</td> <td colspan="4" class="x144">&nbsp;</td>
<td colspan="4" class="x148">0x6. Modbus Holding</td> <td colspan="4" class="x148">0x6. Резерв</td>
<td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td> <td colspan="16" class="x160">&nbsp;</td>
<td colspan="4" class="x161">Кол-во регистров (0-15(</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="4" class="x97">&nbsp;</td> <td colspan="4" class="x97">&nbsp;</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">NULL</td> <td colspan="8" class="x97">&nbsp;</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:17px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
@@ -1242,13 +1242,12 @@ DATA[4..7] RunningCRC32, uint32 little-endian
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td colspan="4" class="x144">&nbsp;</td> <td colspan="4" class="x144">&nbsp;</td>
<td colspan="4" class="x148">0x7. Modbus Input</td> <td colspan="4" class="x148">0x7. Резерв</td>
<td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td> <td colspan="16" class="x160">&nbsp;</td>
<td colspan="4" class="x161">Кол-во регистров (0-15)</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="4" class="x97">&nbsp;</td> <td colspan="4" class="x97">&nbsp;</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">NULL</td> <td colspan="8" class="x97">&nbsp;</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:17px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
+12 -13
View File
@@ -895,20 +895,21 @@ CRC32 обнаруживает случайное повреждение, но
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">Word3 | Word2 | Word1 | Word0: маска битов 1…3</td> <td colspan="8" class="x97">Word3 | Word2 | Word1 | Word0: маска битов 1…3</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:34px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td colspan="4" class="x144">&nbsp;</td> <td colspan="4" class="x144">&nbsp;</td>
<td colspan="4" class="x148">0x5. Modbus Discrete</td> <td colspan="4" class="x148">0x5. Modbus</td>
<td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td> <td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td>
<td colspan="4" class="x161">Кол-во регистров (0-15)</td> <td colspan="2" class="x161">Функция (1–4)</td>
<td colspan="2" class="x161">Кол-во регистров (1–4)</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="4" class="x97">&nbsp;</td> <td colspan="4" class="x97">0/1/2/4/6/8</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">NULL</td> <td colspan="8" class="x97">FC1/2: биты; FC3/4: слова LE</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:17px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
@@ -917,13 +918,12 @@ CRC32 обнаруживает случайное повреждение, но
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td colspan="4" class="x144">&nbsp;</td> <td colspan="4" class="x144">&nbsp;</td>
<td colspan="4" class="x148">0x6. Modbus Holding</td> <td colspan="4" class="x148">0x6. Резерв</td>
<td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td> <td colspan="16" class="x160">&nbsp;</td>
<td colspan="4" class="x161">Кол-во регистров (0-15(</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="4" class="x97">&nbsp;</td> <td colspan="4" class="x97">&nbsp;</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">NULL</td> <td colspan="8" class="x97">&nbsp;</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:17px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
@@ -932,13 +932,12 @@ CRC32 обнаруживает случайное повреждение, но
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td class="x27">&nbsp;</td> <td class="x27">&nbsp;</td>
<td colspan="4" class="x144">&nbsp;</td> <td colspan="4" class="x144">&nbsp;</td>
<td colspan="4" class="x148">0x7. Modbus Input</td> <td colspan="4" class="x148">0x7. Резерв</td>
<td colspan="12" class="x160">Стартовый адрес регистра (0x0 - 0xFFF)</td> <td colspan="16" class="x160">&nbsp;</td>
<td colspan="4" class="x161">Кол-во регистров (0-15)</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="4" class="x97">&nbsp;</td> <td colspan="4" class="x97">&nbsp;</td>
<td class="x14">&nbsp;</td> <td class="x14">&nbsp;</td>
<td colspan="8" class="x97">NULL</td> <td colspan="8" class="x97">&nbsp;</td>
</tr> </tr>
<tr style="height:17px"> <tr style="height:17px">
<td class="x26">&nbsp;</td> <td class="x26">&nbsp;</td>
Binary file not shown.