190 lines
12 KiB
Markdown
190 lines
12 KiB
Markdown
# ProtoCAN — базовый протокол
|
||
|
||
Статус: **Stable с зарезервированным загрузочным расширением**<br>
|
||
Версия: **1.0**<br>
|
||
Порядок байтов payload: **little-endian**, если явно не указано иное
|
||
|
||
## Назначение
|
||
|
||
ProtoCAN — прикладной протокол поверх classic CAN 2.0B. Используются только
|
||
расширенные 29-битные идентификаторы (`IDE=1`) и payload длиной 0…8 байт.
|
||
|
||
## Термины
|
||
|
||
| Термин | Значение |
|
||
|---|---|
|
||
| ПМ | управляющий модуль |
|
||
| прибор | адресуемый узел на шине |
|
||
| `DeviceType` | тип прибора, 0…7 |
|
||
| `DeviceID` | экземпляр прибора данного типа, 0…15 |
|
||
| `MsgType` | класс сообщения или сервис |
|
||
| `MsgBody` | 16-битное поле, формат которого зависит от `MsgType` |
|
||
|
||
Пара `DeviceType/DeviceID` задаёт до `8 × 16 = 128` уникальных адресов.
|
||
|
||
## Расширенный CAN ID
|
||
|
||
```text
|
||
28 27 26...24 23...20 19...16 15........0
|
||
Priority Route DeviceType DeviceID MsgType MsgBody
|
||
1 бит 1 бит 3 бита 4 бита 4 бита 16 бит
|
||
```
|
||
|
||
```c
|
||
can_id =
|
||
((uint32_t)priority << 28) |
|
||
((uint32_t)route << 27) |
|
||
((uint32_t)device_type << 24) |
|
||
((uint32_t)device_id << 20) |
|
||
((uint32_t)msg_type << 16) |
|
||
msg_body;
|
||
```
|
||
|
||
| Поле | Значения | Назначение |
|
||
|---|---|---|
|
||
| `Priority` | `0` critical, `1` standard | CAN-арбитраж |
|
||
| `Route` | `0` от ПМ, `1` от прибора | логическое направление |
|
||
| `DeviceType` | `0…7` | тип прибора |
|
||
| `DeviceID` | `0…15` | номер экземпляра |
|
||
| `MsgType` | `0…15` | тип сообщения |
|
||
| `MsgBody` | `0…65535` | команда, адрес или номер блока |
|
||
|
||
`Route` не является направлением физического трансивера. Ответ прибора
|
||
сохраняет адрес `DeviceType/DeviceID` и устанавливает `Route=1`.
|
||
|
||
## Реестр `MsgType`
|
||
|
||
| Код | Имя | Основное направление | DLC | Статус |
|
||
|---:|---|---|---:|---|
|
||
| `0x0` | `BROADCAST` | ПМ → все | зависит от команды | stable |
|
||
| `0x1` | `DISCRETE` | оба | 0…8 | stable |
|
||
| `0x2` | `ANALOG` | оба | 0…8 | stable |
|
||
| `0x3` | `GAS` | оба | 0/2/4/6/8 | stable |
|
||
| `0x4` | `MODBUS_COIL` | оба | 0…8 | stable |
|
||
| `0x5` | `MODBUS_DISCRETE` | оба | 0…8 | stable |
|
||
| `0x6` | `MODBUS_HOLDING` | оба | 0…8 | stable |
|
||
| `0x7` | `MODBUS_INPUT` | оба | 0…8 | stable |
|
||
| `0x8` | `ERROR` | прибор → ПМ | 0 | stable |
|
||
| `0x9` | `BOOT_CONTROL` | ПМ → прибор | 0/8 | draft |
|
||
| `0xA` | `BOOT_DATA_A` | ПМ → прибор | 8 | draft |
|
||
| `0xB` | `BOOT_DATA_B` | ПМ → прибор | 8 | draft |
|
||
| `0xC` | `BOOT_STATUS` | прибор → ПМ | 8 | draft |
|
||
| `0xD` | `BOOT_DISCOVERY` | прибор → ПМ | 8 | draft |
|
||
| `0xE` | `SETTINGS` | оба | 0/1/8 | stable |
|
||
| `0xF` | `PULSE` | прибор → сеть | 1 | stable |
|
||
|
||
Подробный формат `0x9…0xD` находится в [BOOTLOADER.md](BOOTLOADER.md).
|
||
|
||
## Разметки `MsgBody`
|
||
|
||
| `MsgType` | Биты `MsgBody` |
|
||
|---|---|
|
||
| broadcast | команда `[15:4]`, параметр `[3:0]` |
|
||
| discrete/analog | подтип `[15:12]`, значение/адрес `[11:0]` |
|
||
| Modbus | начальный адрес `[15:4]`, количество `[3:0]` |
|
||
| GAS | адрес первого 16-битного регистра `[15:0]` |
|
||
| error | дополнительная информация `[15:8]`, код `[7:0]` |
|
||
| settings | номер сборки `[15:8]`, позиция `[7:0]` |
|
||
| boot control/status | `SessionID[15:8]`, команда `[7:0]` |
|
||
| boot data | `BlockIndex[15:0]` |
|
||
|
||
## Общие правила обмена
|
||
|
||
- Многобайтовые значения в `DATA` передаются little-endian.
|
||
- Узел игнорирует адресованные кадры с чужим `DeviceType/DeviceID`.
|
||
- Прибор принимает команды ПМ с `Route=0`; ПМ принимает ответы с `Route=1`.
|
||
- Стандартные 11-битные CAN ID не являются кадрами ProtoCAN.
|
||
- RTR для загрузочного сервиса запрещён.
|
||
- Неописанные комбинации `MsgType/MsgBody/DLC` должны отвергаться.
|
||
|
||
## Эталон упаковки ID
|
||
|
||
```text
|
||
Priority = 1
|
||
Route = 0
|
||
DeviceType = 3
|
||
DeviceID = 5
|
||
MsgType = 0x9
|
||
MsgBody = 0x0702
|
||
|
||
CAN ID = 0x13590702
|
||
```
|
||
|
||
Этот пример соответствует `ENTER_BOOT`, `SessionID=7`. Машинные варианты
|
||
находятся в [examples/test-vectors.json](examples/test-vectors.json).
|
||
|
||
## GAS: сквозная карта УКСС и профиль 167/v1
|
||
|
||
УКСС назначены десятичные ID **0…11999**, блоки по 1000 слов:
|
||
`GAS_ID = номер_узла × 1000 + смещение`. Блок 0 — общий резерв;
|
||
узлы 1…11 и все границы описаны в
|
||
[GAS_ADDRESS_ALLOCATION_167.md](GAS_ADDRESS_ALLOCATION_167.md).
|
||
Диапазон 12000…65535 свободен для последующего распределения.
|
||
|
||
УМП 1 (узел 5) назначены ID 5000…5127, УМП 2 (узел 6) —
|
||
6000…6127. Смещения 128…999 зарезервированы. Полный словарь 128 слов,
|
||
ограничения LOAD, биты Commands/LOAD_STATUS и соответствие Modbus приведены в
|
||
[GAS_MODBUS_MAP_167.md](GAS_MODBUS_MAP_167.md).
|
||
|
||
Новые ID пока назначены только в документации. Действующий профиль 167/v1
|
||
использует Modbus 0x0000…0x007F и окно GAS 0x5000…0x507F;
|
||
например, LOAD_CAN_TIMEOUT: Modbus 0x0052, GAS 0x5052,
|
||
новые ID 5082/6082. Десятичный ID 5000 не равен hex-адресу 0x5000.
|
||
Служебный CAN УМП с маркером 0x1F00 — отдельный транспорт;
|
||
его пакет нельзя интерпретировать как обычный payload ProtoCAN GAS.
|
||
|
||
Словарь и lookup находятся в `python/protocan/gas_167.py` и
|
||
`gas_167_registers.json` проекта templates. Парсер обычных кадров GAS
|
||
показывает назначенные имена, узел, старые адреса и статус для запросов
|
||
и каждого слова ответа; неизвестные и резервные адреса сохраняются raw.
|
||
Общая сводка `Decoded.summary` содержит имя каждого назначенного параметра,
|
||
УМП 1/2, десятичный ID, hex-адрес и значение в dec/hex. Поэтому имена видны
|
||
непосредственно в колонке «Расшифровка» всех клиентов общего декодера:
|
||
онлайн-монитор, трассировка, фильтр кадров, ручной разбор и DevBoard_V1.
|
||
Полный текст длинной строки доступен во всплывающей подсказке.
|
||
Тип сообщения отображается как `GAS (General Address Space)`.
|
||
Обычные демо-потоки шины и DevBoard также включают назначенные адреса УМП.
|
||
Низкие Modbus-адреса и старое окно не определяют профиль прибора автоматически.
|
||
DATA обычного ProtoCAN GAS — до четырёх u16 little-endian; Modbus RTU
|
||
передаёт каждое слово старшим байтом вперёд. GUI использует этот же словарь
|
||
через совместимый импорт, без собственной реализации карты.
|
||
|
||
### Демо УМП в SETGUI
|
||
|
||
Общий список «Протокол» позволяет выбрать `ProtoCAN / GAS`,
|
||
`УМП / Balsam 167 (legacy CAN)`, карту `GAS 167/v1` отдельно для УМП 1/2
|
||
или `УМП / ProtoCAN GAS — новые ID 5000/6000`.
|
||
Выбор перерисовывает уже полученные кадры. Для старой карты номер УМП
|
||
выбирается оператором и обозначается «выбран вручную»; низкие адреса
|
||
0…127 и окно 0x5000…0x507F сами по себе номер узла не кодируют.
|
||
Этот режим накладывает словарь на слова ProtoCAN GAS/Modbus Holding;
|
||
он не является декодером служебных CAN-пакетов с маркером 0x1F00.
|
||
Профиль Balsam принимает только собственный формат и показывает
|
||
несоответствие для чужих кадров. В сводке Commands показаны активные
|
||
биты с названиями команд; это не подтверждение их выполнения.
|
||
|
||
В режиме «Авто» legacy-ID Balsam проверяются первыми. Для корректного
|
||
ProtoCAN GAS с целыми словами все адреса кадра сверяются с назначенными
|
||
диапазонами УМП. Если все они принадлежат одному узлу, поля Device Name
|
||
и Msg Type показывают УМП 1/2; основание выбора записывается в подробности
|
||
«Автоопределение». Это распознавание назначенной карты, а не подтверждение
|
||
её поддержки прошивкой. Для старых/неизвестных адресов, смешанных диапазонов
|
||
и некорректного payload автоматический выбор УМП не выполняется;
|
||
сводка сообщает «профиль/узел не определены». Номер Device в ProtoCAN сам
|
||
по себе не считается номером УМП. «Демо УМП» запускается с режимом «Авто».
|
||
|
||
Открыть `CAN → Шина CAN / мост → Настройки → Демо УМП`.
|
||
Генератор `python/set_devices/bus_demo.py:UmpDemoSource` моделирует два
|
||
узла с демонстрационными адресами `Device Type=3`, `Device=5/6`.
|
||
Он передаёт PULSE раз в секунду и четыре GAS-слова каждого узла каждые
|
||
250 мс: ID 5000…5127 и 6000…6127, полный обход за 8 секунд.
|
||
Это имитация назначенной карты, а не эмуляция текущего транспорта 167/v1.
|
||
|
||
Кадры проходят обычное кадрирование AA 55, CRC и общий парсер ProtoCAN.
|
||
Их можно смотреть в онлайн-мониторе, трассировке и адресном пространстве;
|
||
в буфере сессии и его CSV источник обозначен `DEMO УМП`.
|
||
Значения синтетические, в формате raw u16. LOAD_STATUS показывает RUN
|
||
(бит 3), LOAD_ATTEMPTS — 0, LOAD_CAN_TIMEOUT — 1000 мс.
|
||
Кнопка «Стоп демо УМП» останавливает поток. Для запуска нужно отключить
|
||
COM-порт и CAN-снифер; генератор работает локально без передачи в оборудование.
|