Files
templates/c/protocan-transport/docs/FRAME.md
Andrey Kruchinkin 3dc636e012 feat(protocan-transport): транспортный уровень ProtoCAN и каталог GUI
Перенесён из репозитория protocan-transport, который подключался
сабмодулем в CAN_to_RS485.

Кадрирование AA 55 с CRC16 поверх любого байтового потока (RS485, RS232,
USB CDC), разбор 29-битного идентификатора, общее адресное пространство
регистров и каталог с подпиской на поток значений для SETGUI. Состояние
живёт в структурах вызывающего, поэтому в одной прошивке поднимается
сколько угодно независимых каналов. Порт STM32F4 (USART + DMA) в комплекте.

Хостовые тесты test_transport и test_gui проходят.
2026-08-23 01:15:35 +03:00

4.3 KiB
Raw Blame History

Транспортный кадр

Формат

+------+------+-----+-----+-------+----------------+-------------+-------+-------+
| 0xAA | 0x55 | LEN | SEQ | FLAGS | ID0 ID1 ID2 ID3| DATA[0..8]  | CRC_L | CRC_H |
+------+------+-----+-----+-------+----------------+-------------+-------+-------+
Поле Байт Описание
SOF 2 сигнатура 0xAA 0x55
LEN 1 длина участка SEQ..DATA = 6 + DLC, диапазон 6..14
SEQ 1 счётчик кадров 0..255, инкремент на каждый успешно отданный кадр
FLAGS 1 см. ниже
ID 4 29-битный CAN-идентификатор, little-endian (старшие 3 бита = 0)
DATA 0..8 DLC = LEN - 6 байт данных CAN
CRC 2 CRC-16/CCITT-FALSE, little-endian

CRC считается по байтам от LEN до последнего байта DATA включительно; сигнатура SOF в расчёт не входит. Полином 0x1021, начальное значение 0xFFFF, без рефлексии и без финального XOR — контрольное значение для строки 123456789 равно 0x29B1.

Максимальный размер кадра — 19 байт (PCAN_FRAME_MAX).

FLAGS

Бит Имя Значение
0 IDE 1 = расширенный ID (29 бит), 0 = стандартный (11 бит)
1 RTR 1 = remote frame
2 DIR 0 = кадр пришёл из CAN, 1 = кадр надо передать в CAN
3 ERR 1 = служебный кадр моста (диагностика), не трафик шины
7..4 резерв, передавать нулями

Синхронизация

Приёмник ищет 0xAA 0x55, читает LEN, проверяет диапазон 6..14, набирает LEN + 2 байт и сверяет CRC. При неверном LEN или несовпадении CRC разборщик возвращается к поиску сигнатуры, причём байт, оборвавший разбор, сам проверяется на 0xAA — последовательность AA AA 55 тоже распознаётся. Потеря синхронизации стоит не больше одного кадра.

Счётчики разбора (pcan_parse_stats_t) отдельно считают кадры, ошибки CRC, неверные LEN и байты вне кадров — по ним видно, шумит линия или сбоит источник.

SEQ

SEQ инкрементируется только на успешно отданном кадре: если кадр не влез в очередь передачи, счётчик не двигается, и приёмник не засчитает потерю там, где кадра просто не было. Разрыв в SEQ на приёме означает реальную потерю в линии.

Почему так

  • Длина плюс CRC, без байт-стаффинга. Стаффинг раздувает кадр непредсказуемо и усложняет расчёт таймингов на полудуплексной линии. Фиксированный заголовок даёт заранее известный максимум 19 байт.
  • Сигнатура из двух байт. Один байт слишком часто встречается в случайных данных; два дают приемлемую вероятность ложного старта, который всё равно отсеет CRC.
  • LEN в начале. Приёмник сразу знает, сколько байт набирать, и не зависит от содержимого данных.
  • Little-endian везде. Совпадает с порядком регистров в PROTOCAN_SEND_GENERAL_ADDRESS_SPACE() и с обоими целевыми МК.

Пример

CAN-кадр: ID 0x1234567, DLC 2, данные AA BB, SEQ = 1, флаг IDE.

AA 55 08 01 01 67 45 23 01 AA BB FE 14

LEN = 6 + 2 = 8, FLAGS = 0x01, CRC = 0x14FE.