Пролог
CAN — это двухпроводный, дифференциальный, последовательный, полудуплексный интерфейс для передачи бинарных данных между электронными платами (PCB). В качестве кабеля чаще всего применяют одну экранированную витую пару проводов с именами: CAN_L и CAN_H. Образно выражаясь CAN — это труба для чисел.
CAN определяет аж два уровня модели OSI-7 (стек сетевых протоколов): физический и канальный. То есть CAN определяет также и бинарную структуру пакета в кабеле. В пакете CAN фигурируют такие переменные, как ID пакета, 8 байт данных, длина пакета, 15 битная контрольная сумма, биты подтверждения ACK, начало и конец пакета.
Где применяется интерфейс CAN?
В каждом автомобильном микроконтроллере есть CAN шина. CAN - это нервная система автомобиля. Именно по САN передаются сигналы от датчиков и команды к исполнительным механизмам агрегатов. Еще CAN используется в поездах, пожарных сигнализациях, лифтах, и даже космических орбитальных спутниках.
Теоретический минимум

CAN bus‑Off — это состояние CAN трансивера. Передатчик переходит в состояние BusOff, если счетчик неудачных передач TEC превысил значение 255. Находясь в состоянии BusOff, трансивер просто физически отключается от CAN шины. Он обязательно прекращает передачу и подтверждение CAN пакетов. Будет ли он продолжать получать кадры, зависит от реализации конкретного CAN трансивера и его настроек.
CAN‑матрица — это схема организации данных в сети CAN, определяющая, какие данные передаются между какими устройствами, и как эти данные интерпретируются. CAN‑матрица обычно представляет собой таблицу, в которой указаны идентификаторы сообщений, данные, которые они содержат, и устройства, которые их отправляют и получают. Она позволяет разработчикам настраивать и управлять обменом данными в сети CAN.
Погрешность — разность между измеренным (установленным) значением величины, и подлинным значением величины. При конфигурации CAN нужно минимизировать погрешность между желаемой и установившейся длительностью 1 бита передаваемых данных.
Физический уровень
Физика CAN очень проста. Есть два скрученных провода с именами CAN_H и CAN_L. Скрутка позволяет преодолевать электромагнитные помехи. Классический CAN позволяет подключить до 127 устройств. По концам шины нужны терминирующие резисторы. В режиме IDLE пины подтянуты одновременно и к земле и к питанию. Поэтому там как правило 2.5V

Стрелка осциллографа показывает вот твой CAN сигнал.

Шина CAN на минимальной битовой скорости 10 кбит/с может достигать аж 5ти км. На максимальной битовой скорости 1 Мбит/с - 40 метров. На одну шину можно пристегнуть максимум 127 абонентов.
Канальный уровень
Биты образуют массив, который формирует пакет CAN. Пакет содержит идентификаторы данные и служебные биты (подтверждение, длина поля данных). CAN пакет передает массив с цифрами (пакет). В пакете самое важное это 8 байт (64 бит) полезных данных. Это называют сообщением. Внутри сообщения есть параметры (они же сигналы). У каждого параметра есть номер. Параметры могут быть, как вдавлены друг в друга, так и размазаны по битам поля данных. Максимум в одном сообщении может быть 64 параметра (сигнала) (по одному биту на параметр в предельном случае). В идеологии CAN классического запрос-ответ нет, как в modbus. Обычно ноды просто непрерывно флудят в шину и тот, кому надо выхватывает то, что ему надо.
Главное преимущество интерфейса CAN - это разрешение коллизий без потери битовой скорости. Если два узла начнут передавать пакеты, то продолжит передачу, то устройство у которого меньше ID.
Бинарная структура пакета CAN Classic пакета
Пакет это по сути массив битов.

Бинарную структуру CAN пакета можно изучить тут

Пояснения битовых полей представлены в этой таблице.
№ |
Битовое поле |
Расшифровка |
bits |
Пояснение |
1 |
SOF |
Start of Frame |
1 |
сообщающий о начале фрейма и позволяющий синхронизировать узлы после фазы ожидания; |
2 |
ID |
Identifier |
11 |
Может иметь 11- или 29-битный размер. Устройство с меньшим ID выигрывает арбитраж. Соответственно, чем меньше ID, тем выше приоритет у устройства; |
3 |
RTR |
Remote Transmission Request |
1 |
Если устройство передает данные, то бит RTR принимает рецессивное состояние. Если устройство запрашивает сообщение от другого узла – бит RTR принимает доминантное состояние; |
4 |
IDE |
бит-указатель на расширенный ID |
1 |
Если IDE принимает доминантное состояние – это значит, что используется стандартный 11-битный идентификатор. Если IDE принимает рецессивное состояние, то принимающий контроллер должен быть готов к приему оставшейся части расширенного 29-битного идентификатора; |
5 |
r0 |
1 |
резервный бит |
|
6 |
DLC |
Data Length Code |
4 |
4-битное поле длины данных , которое кодирует, сколько байтов данных будет передано в сообщении. В классическом CAN DLC может принимать значение в диапазоне 0…8. |
7 |
DATA |
DATA |
64 |
В классическом CAN фрейм может содержать 0…8 байтов данных |
8 |
CRC |
CRC |
15 |
15-битный контрольный CRC-код для переданных данных |
9 |
CRC D |
Delimiter |
1 |
бит-ограничитель для поля CRC |
10 |
ACK |
1 |
бит подтверждения сообщения. В исходном фрейме передатчик использует рецессивное состояние этого бита. В свою очередь приемники при отсутствии ошибок должны установить в этом бите доминантное состояние. Другими словами, если на шине есть хотя бы один активный приемник, то в этом бите будет установлено доминантное состояние; |
|
11 |
ACK D |
1 |
бит-ограничитель (Delimiter) для ACK |
|
12 |
EOF |
End-of-Frame |
7 |
7-битное поле окончания фрейма |
13 |
IFS |
Interframe Space |
any |
меж фреймовый интервал, необходимый для того, чтобы приемник успел поместить сообщение в буфер. |
Если трансивер передатчика не увидит бит подтверждения ACK, то передатчик (CAN MAC) будет снова и снова непрерывно передавать этот же CAN пакет, до тех пор пока его кто-нибудь не примет или случится bus-off. Таким образом, шина будет занята на 100 %. Однако некоторые микроконтроллеры всё же позволяют настроить MAC на одиночную отправку.
А это структуру пакета с расширенным идентификатором. Это позволяет адресовать болше узлов.

Еще бывает так делают, что берут Ext ID в 29 бит, адреса узлов ставят, условно, 24 бита. А самые младшие 5 выделяют под приоритет сообщения. В результате каждый ID имеет свои отдельные уровни приоритетов (32 уровня).
Биты расширенного адреса |
Размер битового поля |
Назначение битового поля |
28-5 |
24 |
Адрес узла |
4-0 |
5 |
Приоритет сообщения |
Транспортный уровень Для классического CAN, чтобы передавать пакеты превышающие 8 байт нужен транспортный протокол. Обычно таким транспортом является протокол ISO-TP. Он же ISO 15765-2.
Уровень приложения В сетях на основе CAN на уровне приложения обычно гоняют следующие прикладные протоколы: CCP, XCP, CanOpen, UDS или J1939.
Как CAN борется с помехами и ошибками?
Протокол CAN определяет по меньшей мере пять различных способов обнаружения ошибок. Два из них работают на уровне битов, а остальные три — на уровне сообщений.
№ |
Способ обнаружения ошибок |
Уровень работы механизма защиты |
1 |
Bit Monitoring. |
бит |
2 |
Bit Stuffing |
бит |
3 |
Frame Check |
пакет |
4 |
Acknowledgement Check |
пакет |
5 |
Cyclic Redundancy Check |
пакет |
Bit Monitoring (Наблюдение за битами)
Каждый передатчик на шине CAN считывает уровень передаваемого сигнала. Если фактически считанный уровень бита отличается от переданного, выдается сигнал об ошибке бита. В процессе арбитража ошибка бита не возникает.
Bit Stuffing (Положительное выравнивание)
Когда узел передал пять последовательных битов одного уровня, он добавит шестой
бит противоположного уровня к исходящему потоку битов. Приемники удалят этот дополнительный бит. Это делается для того, чтобы избежать избыточных компонентов постоянного тока на шине, но также дает приемникам дополнительную возможность обнаруживать ошибки: если на шине встречается более пяти последовательных битов одного уровня, подается сигнал об ошибке заполнения.
Frame check (Проверка пакета)
Некоторые части сообщения CAN имеют фиксированный формат, т. е. стандарт точно определяет, какие уровни должны происходить и когда. (Этими частями являются разделитель CRC, разделитель ACK, конец кадра). Если контроллер CAN
обнаруживает недопустимое значение в одном из этих фиксированных полей, выдается сигнал об ошибке структуры пакета.
Acknowledgement Check (Проверка подтверждения)
Все узлы на шине, которые правильно получают сообщение (независимо от того, «интересуются» ли они его содержимым или нет), должны выполнить подтверждение, то есть отправить доминирующий уровень в так называемом слоте подтверждения в сообщении. Передатчик передаст здесь рецессивный уровень. Если передатчик не обнаружит доминирующий уровень в слоте ACK, выдается сообщение об ошибке подтверждения. Как правило начинается повторная отправка. После 255 повторных попыток отправки CAN трансивер электрически отключается от витой пары и генерирует прерывание CAN bus-off.
Трансиверы CAN-шины не имеют возможности выборочно подтверждать пакеты, как в шине I2C, например. Любой корректно сформированный пакет аппаратно подтверждается всеми, кто его слышит.
Если на шине несколько исправных устройств, очень сложно получить ситуацию, когда не слышит никто, и подтверждения нет.
Cyclic Redundancy Check (Циклический избыточный код)
Каждое сообщение содержит циклическую контрольную сумму (CRC), и любой узел, который обнаруживает в сообщении CRC, отличную от той, которую он рассчитал сам, сообщит об ошибке CRC.
А теперь внимание, все эти механизмы работают полностью аппаратно на уровне ASIC или MAC! То есть всё это происходит незаметно для программиста микроконтроллера с CAN. Вот так. Вам уже нравится CAN?
Схемотехника CAN интерфейса
Обычно физика CAN трансивера представлена микросхемой TJA10xx. Это дифференциальная пара проводов. На конце каждого CAN узла заложен резистор 120 Ом. Он нужен чтобы не было пере-отражений в длинных линиях проводов.

Программная часть
Алгоритм включения CAN
Что же надо сделать чтобы в микроконтроллере заработал CAN трансивер?
№ |
Действие в коде |
1 |
Настроить GPIO на CAN. Надо переключиться на альтернативную функцию. |
2 |
Подать тактирование на CAN трансивер |
3 |
Активировать маскированные прерывания глобально. |
4 |
Активировать номера прерываний, которые соответствуют нужному экземпляру CAN трансивера. |
5 |
Настроить битовую скорость шины. |
6 |
Написать обработчик CAN прерываний |
7 |
Определить call back функции для CAN |
8 |
Определить message buffer для CAN (фильтры приема ID) |
9 |
Определить параметры NVRAM для CAN. |
Настроить битовую скорость шины.
Это самый ответственный этап. CAN трансиверы каждый бит делят на четыре части (сегмента). Сегмент синхронизации, всегда имеет длину в один квант, используется для синхронизации тактов. Ожидается, что здесь будет иметь место фронт бита, когда данные изменяются на шине. Сегмент распространения необходим для компенсации задержки в линиях шины. Фазовые сегменты могут быть укорочены (фазовый сегмент 1) или удлинены (фазовый сегмент 2), если необходимо поддерживать синхронизацию тактов.

Чтобы уменьшить погрешность установки периода бита надо уменьшать продолжительность временного кванта (т.е. Tq). Образно, увеличивать гранулярность. Для этого надо увеличивать значение пред делителя в регистрах CAN MAC-а.

Второй момент. Как выбрать натуральные числа для sync, prop, seg1,seg2? С математической точки зрения, сумму N четырьмя натуральными числами можно составить C(N - 1, 3) = (N - 1)(N - 2)(N - 3) / 6 способами, где C(n, k) = n! / k!(n-k)!
Сумма |
Количество способов составить сумму 4мя слагаемыми. |
4 |
1 |
5 |
4 |
6 |
10 |
7 |
20 |
8 |
35 |
9 |
56 |
10 |
84 |
11 |
120 |
12 |
165 |
13 |
220 |
Уровни шины выбираются на границе между фазовым сегментом 1 и фазовым сегментом 2. Поэтому при настройке битовой скорости любого CAN драйвера вам надо будет из одного числа (желаемая битовая скорость), так или иначе вычислить 4 числа (sync, prop, seg1, seg2), которые непосредственно влияют на результирующую битовую скорость. Выбор этих четырех чисел - самое неясное при работе c CAN. Драйверы от вендоров судя по коду делают какие-то сложнейшие математический вычисления, чтобы сформировать этот пресловутый массив sync, prop, seg1, seg2.
Большинство CAN-трансиверов также предоставляют возможность делать ADC выборку три раза в течение 1го бита. В этом случае выборка происходит на границах двух квантов, которые предшествуют точке выборки. Финальное значение бита определяется электрическим голосованием внутри цифровых логических цепей CAN-трансивера. Называется это мажорирование сигналов.
Определить параметры NVRAM для CAN.
Битовую скорость CAN трансивера лучше хранить в NVRAM. По опыту могу сказать, что вы никогда заранее не знаете к какой шине и где будет подключаться очередное устройство в будущем. С NVRAM вы хоть сможете открыть UART-CLI и легко пере конфигурировать трансивер без пере сборки всей прошивки.
Обзор профессиональных средств аппаратной отладки для CAN-classic
Для пусконаладки CAN на незнакомом микроконтроллере вам, как ни крути, потребуется какой-то эталонный CAN-трансивер. Существует серия устройств-переходников для подключения CAN устройств через USB к компьютерам и LapTop-ам. Вот перечень широко распространенных вариантов для USB-CAN переходников .
№ |
Переходник |
Software |
1 |
SYS TEC USB-CANmodul1 |
CANinterpreter Lite for USB-CANmodul |
2 |
USBCAN-II C |
ECAN Tools |
3 |
canfox |
CANexplorer 4 |
4 |
CH-P |
CARBUS Analyzer |
5 |
CANable 2.0 |
Cangaroo |
6 |
CAN-bus-USBnp |
CANwise |
7 |
Peak CAN |
PCAN-View |
8 |
VSCOM USB-CAN Plus ISO |
? |
К слову, многие организации даже делают свои custom версии переходников с USB на CAN. Еще вам на первых порах скорее всего потребуется логический анализатор и осциллограф.
№ |
Название |
Версия |
Назначение |
1 |
DS View |
v1.3.2 |
Клиентская программа для логического анализатора DS Logic |
В отладке CAN главное сразу настроить нужную битовую скорость. Это можно сделать осциллографом. Далее если подключиться электродом к MCU пину CAN_RX, то структуру самого CAN пакета можно увидеть логическим анализатором DS-logic.

Затем пристегиваем переходники с USB-CAN и смотрим таблицу отправленных и принятых пакетов. Можно проанализировать сеанс связи. PCAN-View это образно локатор для CAN пакетов.

Когда у вас накопится очень много самодостаточных CAN пакетов, вы можете их организовать в базу данных. Для этого есть утилита CANdb++ Editor.

Это специальная база данных только заточена она для хранения CAN пакетов. Там есть поиск, сортировка конкретных переменных (сигналов), который покажет какие физические величины передаются в CAN и по каким ID сообщениям. Всё хранится в одном текстовом .dbc файле. Из которого, к слову, можно даже генерировать Си-код для синтактического разбора пакетов.
Итог
Удалось получить некоторое начальное представление о том, что такое CAN-интерфейс и с какой стороны следует подходить к CAN шине.
Семейство интерфейсов CAN это далеко не единственный и, к слову, не самый дешевый выбор для разворачивания сетей типа общая шина. Есть ещё RS485, LIN, 1-Wire, DALI, MIL-STD-1553, ARINC 429 и прочие. Сравнение интерфейсов можно произвести вот в этом реестре

Акронимы
Акроним |
Расшифровка |
CAN |
Controller Area Network |
MB |
message buffers (Mail Box) |
PC |
personal computer |
USB |
Universal Serial Bus |
MAC |
medium access control |
CRC |
Cyclic redundancy check |
CHI |
Controller Host Interface |
PHY |
physical layer |
FIFO |
first in, first out |
Ссылки
Название |
URL |
ЛикБез по CAN-FD |
|
CANdb++ Editor |
|
Протокол CAN |
|
Обзор Переходника USB-CAN (SYS TEC USB-CANmodul1) |
|
Обзор USB-CAN переходника USBCAN-II C |
|
Обзор Протокола ISO-TP [ISO 15765-2] |
|
Атрибуты Хорошего Канального Протокола Передачи Данных |
|
CAN sniffer @KruFFT |
|
CAN шина @Dorodnikov_viktor |
|
Использование сети CAN и стека CANopen @GreyM |
Вопросы
Что такое CAN bus-off?
Зачем в CAN нужен remote кадр? В протоколе CAN Remote-кадр служит для запроса данных у другого узла, позволяя одному узлу инициировать передачу данных, запрашивая у другого узла отправить информацию определённого идентификатора. Это позволяло более эффективно управлять трафиком, уменьшая необходимость в постоянной передаче всего набора данных.
Как определить сколько time quantum (Tq) следует выделить предделителем для одного CAN бита? 10? 20? 40? Проще говоря, какое разрешение нужно для одного CAN бита? Это можно как-то математически обосновать и рассчитать? На сколько квантов разбить один CAN бит?
Допустим мы как-то решили разбить один CAN бит на N квантов. Пусть N=24. Как теперь распределить кванты на интервалы CAN бита: sync, prop, seg1 и seg2?
Как в CAN можно повысить (или понизить) приоритет конкретного ID сообщения?
Что такое CAN-матрица?
Как измерить процент загрузки CAN шины трафиком в реальном времени?
Комментарии (13)
NutsUnderline
26.08.2025 15:45Сравнение интерфейсов можно произвести вот в этом реестре
что то как то много знаков вопроса в этой таблице.
Зачем в CAN нужен remote кадр?
многие похоже не осилили эту мощную технику. даже довольно сложные анализаторы не все умеют правильно реагировать на этот бит. изобретатели протоколов игнорируют эту возможность, реализуют ее на своем уровне, да еще инкапсуляция пакетов: теряется оригинальная изящная задумка.
Как определить сколько time quantum (Tq) следует выделить предделителем
самое интересное что есть некоторые рекомендации не делать слишком маленький квант помимо аппаратных ограничений, на вскидку не могу найти
aabzel Автор
26.08.2025 15:45самое интересное что есть некоторые рекомендации не делать слишком маленький квант
Для коротких Tq нужна нужна высокая частота тактирования CAN-трансиверов. Высокая частота - подскакивает энергопотребление. Следствие - сажается аккумулятор.
Результат - утром не завести автомобиль .
NutsUnderline
26.08.2025 15:45CAN-матрица
а это стандартизованный термин? вроде не вот часто встречаю
aabzel Автор
26.08.2025 15:45CAN-матрица — это схема организации данных в сети CAN, определяющая, какие данные передаются между какими устройствами, и как эти данные интерпретируются. CAN-матрица обычно представляет собой таблицу, в которой указаны идентификаторы сообщений, данные, которые они содержат, и устройства, которые их отправляют и получают. Она позволяет разработчикам настраивать и управлять обменом данными в сети CAN.
ahdenchik
26.08.2025 15:45CAN-шина (Теория)
У меня вопрос по теории: как проектировать системы, использующие CAN?
У нас есть N устройств, которые должны в гарантированные промежутки времени (обещали реалтайм!) "высказаться". Часть из них более приоритетные, часть - менее. Если устройств достаточно много то как определить успеют ли они высказаться все в какую-то единицу времени?
То есть, где гарантия что все устройства (разложенные по приоритетам и всё такое прочее) успеют высказаться? "Математически" это доказать можно?Что об этом говорят официальные гайды от производителей, например?
VBKesha
26.08.2025 15:45Зная скорость можно расчитать сколько шина через себя успеет прокачать. Если всё не сильно жестко, можно посчитать сколько пакетов шина через себя может пропустить. И посчитать сколько будут генерировать устройства. Если пакетов меньше чем шина через себя готова пропускать, то с большой вероятностью оно будет работать. Хорошо бы запас конечно иметь 10% на случай перепосылки.
ahdenchik
26.08.2025 15:45Именно про это мой вопрос: а как это посчитать? Оно ведь явно не просто суммируется, ведь могут быть коллизии
VBKesha
26.08.2025 15:45Именно про это мой вопрос: а как это посчитать?
Берем размер пакета, желательно максимального, считаем сколько в нем бит(включая все служебные), берем скорость и делим на это число. получаем число пакетов в секунду.
ведь могут быть коллизии
По идее и быть не должно, даже при одновремнной начале передачи пакета несколькими устройствами, арбитраж выигрывает устройство с меньшим адресом.
ahdenchik
26.08.2025 15:45Все узлы на шине, которые правильно получают сообщение (независимо от того, «интересуются» ли они его содержимым или нет), должны выполнить подтверждение, то есть отправить доминирующий уровень в так называемом слоте подтверждения в сообщении.
То есть, технически, все принимающие устройства одновременно подтянут шину вверх в нужный момент (в момент прохождения флага ask)?
rsashka
26.08.2025 15:45Для подтверждения достаточно всего одного узла, так как "вверх", это доминантный бит и наличие даже одного такого бита перекрывает все остальные "вниз".
eps
26.08.2025 15:45Как будет выглядеть вырожденный вариант шины на 2 устройства?
Я пробовал соединить их CAN_H и CAN_L, и даже ставить резистор в 60Ω между ними, связности нет
Albert2009Zi
"Стрелка осциллографа" - сразу плюс от меня вам. А вообще, я поражаюсь продуктивности таких, как вы авторов. Спасибо, что стараетесь!