Перенесён из репозитория protocan-transport, который подключался сабмодулем в CAN_to_RS485. Кадрирование AA 55 с CRC16 поверх любого байтового потока (RS485, RS232, USB CDC), разбор 29-битного идентификатора, общее адресное пространство регистров и каталог с подпиской на поток значений для SETGUI. Состояние живёт в структурах вызывающего, поэтому в одной прошивке поднимается сколько угодно независимых каналов. Порт STM32F4 (USART + DMA) в комплекте. Хостовые тесты test_transport и test_gui проходят.
4.3 KiB
Транспортный кадр
Формат
+------+------+-----+-----+-------+----------------+-------------+-------+-------+
| 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.