Практическая реализация интерфейса CAN FD в микроконтроллерах STMicroelectronics

3 декабря 2020

системы безопасностиучёт ресурсовпотребительская электроникаинтернет вещейуниверсальное применениеSTMicroelectronicsстатьяинтегральные микросхемыМикроконтроллерCANCAN-FDCortex-M33STM32L5

Гавриков Вячеслав (г. Смоленск)

Протокол CAN FD – результат развития классического протокола CAN. Благодаря ряду изменений эффективная скорость передачи данных CAN FD может быть увеличена в несколько раз. При этом физическая реализация самой шины осталась без изменений. Все это делает CAN FD наиболее привлекательной альтернативой для CAN-устройств. В статье кратко анализируются особенности CAN FD, а также рассматривается пример практической реализации CAN FD на базе микроконтроллеров STM32.

История CAN началась в 1986 году, и с тех пор он стал одним из наиболее популярных протоколов. CAN широко применяют в автомобилях, промышленном оборудовании, системах освещения и других приложениях. Главными достоинствами CAN является простота реализации, так как наиболее сложные элементы протокола (в частности арбитраж, формат кадра, физическая реализация), оказываются реализованными на уровне CAN-контроллера и CAN-трансиверов. Таким образом, разработчик может сразу приступать к передаче данных.

Несмотря на все достоинства CAN, в последнее время все чаще стали возникать проблемы с пропускной способностью этого интерфейса. Дело в том, что объем информации постоянно возрастает и скорости передачи 1 Мбит/с уже не всегда хватает для современных приложений. Кроме того, если раньше нормой были 8- и 10-битные датчики, то сейчас разрядность данных может составлять 24 бита и более, поэтому становится сложнее умещать всю информацию в одном фрейме (8 байт), а переход к многофреймовым сообщениям оказывается неудобным.

Одним из решений проблемы может стать интерфейс CAN FD, который позволяет передать больше данных в одном фрейме и повысить частоту передачи [1]. Данная статья состоит из следующих разделов, помогающих разобраться с особенностями CAN FD:

Основные разделы статьи

Краткий обзор физической реализации классической версии CAN

Архитектура шины CAN, согласно ISO 11898, предполагает использование витой пары с импедансом 120 Ом и двумя концевыми терминаторами 120 Ом (рисунок 1) [2].

Рис. 1. Организация шины CAN [2]

Рис. 1. Организация шины CAN [2]

За формирование физических сигналов на шине отвечают специальные CAN-трансиверы, которые преобразуют логические сигналы от CAN-контроллера в дифференциальный сигнал. Используется двоичное кодирование: логической единице соответствует низкое дифференциальное напряжение, а логическому нулю – высокое.

При передаче логического нуля на линии CANH формируется напряжение около 3,5 В, а на линии CANL – напряжение 1,5 В (дифференциальный сигнал 2 В). При передаче логической единицы на обеих линиях присутствует напряжение 2,5 В (дифференциальное напряжение близко к 0 В). При этом рецессивным является состояние с низким дифференциальным напряжением (логическая единица), а доминантным – состояние с высоким напряжением (логический ноль). Другими словами, если один из узлов будет передавать «1», а другой узел будет в то же время передавать «0», то на шине будет присутствовать «0». Эта важная особенность позволяет организовывать неразрушающий арбитраж.

Архитектура CAN-шины является одновременно простой, удобной и недорогой, что во многом и определяет популярность CAN. Но, к сожалению, стандарт ISO 11898 ограничивает максимальную скорость обмена по CAN в 1 Мбит/с. Это связано с особенностями арбитража.

Согласно ISO 11898, при обмене данными по CAN используется неразрушающий арбитраж с индивидуальными идентификаторами узлов. Перед началом передачи данных любое устройство передает свой идентификатор и одновременно контролирует шину. При обнаружении несоответствия между передаваемым сигналом и состоянием шины узел теряет арбитраж и прекращает передачу. Механизм арбитража поясняется на рисунке 2 [2]. В первый момент времени узлы С и В начинают передавать свои идентификаторы. Узел С предает свой идентификатор, который начинается последовательностью 100, а узел В передает свой идентификатор, который начинается последовательностью 101:

  • Первый шаг. Узел С передает «1», узел В передает «1», в итоге на шине наблюдается рецессивное состояние с низким дифференциальным напряжением.
  • Второй шаг. Узел С передает «0», узел В передает «0», в итоге на шине наблюдается доминантное состояние с высоким дифференциальным напряжением.
  • Третий шаг. Узел С передает «0», узел В передает «1», в итоге на шине наблюдается доминантное состояние с высоким дифференциальным напряжением.
  • Четвертый шаг. Узел В обнаруживает несоответствие и проигрывает арбитраж. Он заканчивает передачу и переводит выходы в принудительное рецессивное состояние, чтобы не мешать узлу С. Узел С выигрывает арбитраж и продолжает передачу.

Рис. 2. Арбитраж на шине CAN [2]

Рис. 2. Арбитраж на шине CAN [2]

Очевидно, что обязательным условием нормальной работы такого механизма арбитража является высокая степень синхронизации между узлами. Однако этому мешают различные задержки, такие как задержка линии передачи, задержка приемников, задержка передатчиков и прочие, а также другие эффекты, искажающие сигнал, например, переотражения и так далее. В частности, витая пара вносит задержку 5 нс/м. Таким образом, разработчик должен гарантировать, что два наиболее удаленных друг от друга узла могут осуществить арбитраж.

Из вышесказанного становится понятной причина зависимости между скоростью передачи и длиной шины. Чем выше скорость передачи, тем меньше должна быть задержка сигнала. В таблице 1 представлены рекомендуемые значения длин шины, квантов времени и точек выборки битов при различных скоростях передачи [3]. При максимальной скорости передачи 1 Мбит/с рекомендуемая длина линии составляет всего 25 м.

Таблица 1. Рекомендуемые значения длины CAN-шины при различных скоростях передачи

Битрейт, кбит/с Номинальная длительность бита, tb, мкс Число квантов в бите Длительность кванта tq, нс Точка выборки, tq Рекомендуемая длина шины (худший случай), м
1000 1 8 125 6 (750 нс) 25
800 1,25 10 125 8 (1 мкс) 50
500 2 16 125 14 (1,75 мкс) 100
250 4 16 250 14 (3,5 мкс) 250
125 8 16 500 14 (7 мкс) 500
50 20 16 1250 14 (17,5 мкс) 1000
20 50 16 3125 14 (43,75 мкс) 2500
10 100 16 6250 14 (87,5 мкс) 5000

Представленные значения рассчитаны для худшего случая. Но в практических устройствах при нормальном согласовании линии, выборе хороших передатчиков и минимизации задержек длина шины может быть увеличена.

С одной стороны, у разработчиков нет возможности увеличить частоту передачи CAN «в лоб» из-за проблем с синхронизацией при арбитраже. С другой — после выполнения арбитража ничто не мешает увеличить скорость передачи. Именно по такому пути и пошли создатели CAN FD.

Анализ формата фрейма в классической версии CAN

В таблице 2 демонстрируется формат фрейма в классическом CAN. Фрейм содержит следующие поля [1]:

  • SOF – стартовый доминантный бит (Start of Frame), сообщающий о начале фрейма и позволяющий синхронизировать узлы после фазы ожидания;
  • ID – идентификатор узла (Identifier). Может иметь 11- или 29-битный размер. Устройство с меньшим ID выигрывает арбитраж. Соответственно, чем меньше ID, тем выше приоритет у устройства;
  • RTR – бит запроса сообщения (Remote Transmission Request). Если устройство передает данные, то бит RTR принимает рецессивное состояние. Если устройство запрашивает сообщение от другого узла – бит RTR принимает доминантное состояние;
  • IDE – бит-указатель на расширенный ID. Если IDE принимает доминантное состояние – это значит, что используется стандартный 11-битный идентификатор. Если IDE принимает рецессивное состояние, то принимающий контроллер должен быть готов к приему оставшейся части расширенного 29-битного идентификатора;
  • r0 – резервный бит;
  • DLC – 4-битное поле длины данных (Data Length Code), которое кодирует, сколько байтов данных будет передано в сообщении. В классическом CAN DLC может принимать значение в диапазоне 0…8.
  • DATA – поле данных. В классическом CAN фрейм может содержать 0…8 байтов данных;
  • CRC – 15-битный контрольный CRC-код для переданных данных;
  • CRC D – бит-ограничитель (Delimiter) для поля CRC;
  • ACK – бит подтверждения сообщения. В исходном фрейме передатчик использует рецессивное состояние этого бита. В свою очередь приемники при отсутствии ошибок должны установить в этом бите доминантное состояние. Другими словами, если на шине есть хотя бы один активный приемник, то в этом бите будет установлено доминантное состояние;
  • ACK D – бит-ограничитель (Delimiter) для ACK;
  • EOF – 7-битное поле окончания фрейма (End-of-Frame);
  • IFS – межфреймовый интервал (Interframe Space), необходимый для того чтобы приемник успел поместить сообщение в буфер.

Таблица 2. Формат фрейма в классическом CAN (стандартный 11-битный ID)

Параметр Классический фрейм CAN
Арбитраж – заголовок Полезная нагрузка Арбитраж – окончание
Поле SOF ID RTR IDE r0 DLC DATA CRC CRC D ACK ACK D EOF IFS
Длина, бит 1 11 1 1 1 4 64 15 1 1 1 7 3

В классическом CAN-фрейме можно увидеть сразу два недостатка:

  • низкая эффективность даже при использовании 11-битных идентификаторов и максимальной длины данных. В лучшем случае на 64 бита полезных данных приходится 47 бит служебной информации, то есть эффективность не превышает 58%;
  • сам по себе объем данных внутри фрейма относительно мал – всего 8 байт. В старых системах этого было вполне достаточно, но сейчас объем данных значительно вырос. Узлам приходится отправлять несколько фреймов.

С первого взгляда кажется, что обе проблемы можно разом решить «в лоб», увеличив длину поля данных, но в таком случае шина может быть занята большую часть времени и недоступна для устройств с низким приоритетом. Несложно посчитать, что фрейм с 8 байтами данных (длина фремйа 111 бит) занимает шину на 0,4 мс при частоте обмена 250 кбит/с. Если увеличить объем данных до 64 байт (длина фрейма не менее 559 бит), то шина будет занята в течение 5,6 мс. То есть ни одно устройство не сможет в течение этого времени что-либо передать. Очевидно, что это неприемлемо для современных систем.

При разработке CAN FD были учтены ограничения классического CAN.

Анализ формата фрейма в CAN FD

Для увеличения максимальной длины данных потребовалось скорректировать формат фрейма CAN FD.

Формат фрейма CAN FD представлен в таблице 3 [1]. Он имеет несколько важных отличий от формата фрейма классического CAN:

  • после передачи ID вместо бита RTR передается бит RRS, который всегда имеет доминантное состояние. Таким образом, в CAN FD поддерживаются только фреймы данных;
  • вместо зарезервированного бита R0, который всегда является доминантным в классическом CAN, передается рецессивный бит EDL (Extend Data Length), сообщающий о том, что это фрейм CAN FD;
  • бит BRS (Bit Rate Switching) сообщает приемнику о переключении частоты передачи при передаче данных (подробнее о переключении частот будет рассказано далее);
  • бит ESI (Error State Indicator) сообщает, что узел находится в режиме Error-active или Error-passive;
  • поле DLC осталось 4-битным и кодирует длину поля данных. В таблице 4 представлено соответствие между значениями DLC и длиной поля данных;
  • поле данных может иметь длину до 64 байт;
  • защита от потери данных кодируется 17/21-битным кодом CRC, который сопровождается полем счетчика бит-стаффинга (поле STC).

Таблица 3. Формат фрейма в CAN FD (стандартный 11-битный ID)

Параметр Фрейм CAN FD
Арбитраж – заголовок Полезная нагрузка Арбитраж – окончание
Поле SOF ID RRS IDE EDL r0 BRS ESI DLC DATA STC CRC CRC D ACK ACK D EOF IFS
Длина, бит 1 11 1 1 1 1 1 1 4 512 6 21 1 1 1 7 3

Таблица 4. Кодирование длины данных в поле DLC в CAN FD

Значение DLC (десятичное) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Длина данных CAN 2.0, байт 0 1 2 3 4 5 6 7 8 8 8 8 8 8 8 8
Длина данных CAN-FD, байт 0 1 2 3 4 5 6 7 8 12 16 20 24 32 48 64

Большинство из перечисленных изменений выглядит достаточно понятным. Стоит лишь несколько подробнее рассмотреть поле контрольной суммы CRC [5]. В классическом CAN использовался 15-битный код CRC, который потенциально мог обнаруживать до 5 ошибочных битов. К сожалению, это было возможно только при фиксированной длине поля данных, однако из-за битстаффинга длина поля данных могла меняться.

Суть битстаффинга заключается в добавлении дополнительных неинформационных битов в исходный поток данных. В случае с CAN запрещена передача последовательности из шести бит одинаковой полярности. При обнаружении шести последовательных одинаковых битов передатчик вставляет после пятого бита бит противоположной полярности. Таким образом, длина поля данных меняется. Из-за этого в классическом CAN гарантировалось обнаружение только одного «испорченного» бита.

В CAN FD данная проблема была решена за счет добавления счетчика битов стаффинга (+ бит паритета) и фиксированных битов стаффинга – Fixed-Stuff Bits, FSB (таблица 5). Разрядность CRC в CAN FD зависит от длины данных. Если поле данных содержит 16 байт и менее, то используется 17-битный CRC. Если длина данных превышает 16 байт, применяется 21-битный CRC.

Таблица 5. Формат поля STC и контрольной суммы CRC [4]

Счетчик стафф-битов CRC
FSB Бит 2 Бит 1 Бит 0 Паритет FSB CRC16 CRC15 CRC14 CRC13 FSB CRC12 CRC11 CRC10 CRC9 FSB CRC8
CRC7 CRC6 CRC5 FSB CRC4 CRC3 CRC2 CRC1 FSB CRC4 Delimiter

Таким образом, CAN FD позволяет передавать в 8 раз больше данных за фрейм, чем классический CAN. Доля полезных битов в фрейме CAN FD увеличивается, следовательно, эффективность возрастает.

Еще более важным изменением CAN FD стало увеличение частоты передачи данных.

Анализ частоты передачи в CAN FD

CAN FD использует ту же физическую реализацию шины, что и классический CAN. При этом он позволяет использовать более высокую скорость передачи. Как было показано выше, ограничение скорости передачи связано с необходимостью выполнения арбитража в начале фрейма и передачи служебных данных в его конце. В то же время при передаче полезной нагрузки жесткая синхронизация между приемником и передатчиком не так важна и скорость может быть значительно выше.

CAN FD имеет следующие особенности:

  • при передаче служебных частей фрейма (в начале и в конце) можно использовать максимальную скорость не более 1 Мбит/с (как и в классическом CAN). Таким образом, не возникает никаких проблем с арбитражем, так как все остается без изменений;
  • при передаче полезной нагрузки (поля ESI, DLC, DATA, STC, CRC и CRC D) частота увеличивается по усмотрению пользователя и может достигать 8 Мбит/с. Это позволяет существенно поднять эффективную скорость передачи. Стандартными скоростями по CiA являются 2/5/8 Мбит/с.

Оценим повышение эффективности CAN FD при различных скоростях передачи и различной длине данных.

Сравнение эффективности и средней скорости передачи CAN и CAN FD

Один из недостатков формата фрейма классического CAN заключается в большом объеме служебной информации. При использовании коротких 11-битных идентификаторов и 8 байт данных полная длина фрейма составляет 111 бит (без учета битов стаффинга), что продемонстрировано в таблице 6. Таким образом, на 64 бита полезных данных будет приходиться 47 бит служебной информации, то есть эффективность классического CAN не превышает 58% (таблица 7).

CAN FD позволяет передавать в 8 раз больше данных за фрейм, а значит, его эффективность значительно выше. В фрейме из 574 битов на данные будет приходится 512 битов, что составляет 89% [5].

Стоит отметить, что если фрейм CAN FD содержит ≤ 8 байт данных, то его эффективность будет меньше чем у классического CAN. Это вполне очевидно, так как объем служебной информации в фрейме CAN FD больше.

Таблица 6. Сравнение длин фреймов CAN и CAN FD [5]

Тип фрейма Секции
Арбитраж – заголовок Полезная нагрузка Арбитраж – окончание
SOF ID RTR/RRS IDE r0/FDF res BRS ESI DLC DATA STC CRC CRC D ACK ACK D EOF IFS
Классический CAN 1 11 1 1 1 4 64 15 1 1 1 7 3
CAN FD 8 байт 1 11 1 1 1 1 1 1 4 64 6 17 1 1 1 7 3
CAN FD 24 байт 1 11 1 1 1 1 1 1 4 192 6 21 1 1 1 7 3
CAN FD 64 байт 1 11 1 1 1 1 1 1 4 512 6 21 1 1 1 7 3

Таблица 7. Сравнение эффективности фреймов CAN и CAN FD [5]

Тип фрейма Длина секций, бит Эффективность, %
Заголовок Полезная нагрузка (без данных) Данные Окончание Всего
Классический CAN 15 20 64 12 111 58
CAN FD 8 байт 17 29 64 12 122 52
CAN FD 24 байт 17 33 192 12 254 76
CAN FD 64 байт 17 33 512 12 574 89

Эффективность использования фрейма не полностью отражает увеличение пропускной способности CAN FD. Если в классическом CAN скорость передачи являлась фиксированной, то в CAN FD полезные данные могут передаваться в несколько раз быстрее полей арбитража. В результате средняя скорость передачи также возрастает.

Для оценки средней скорости передачи можно воспользоваться специальным калькулятором [5]. Результаты расчета для различных скоростей передачи представлены в таблице 8. Из нее видно, что средняя скорость передачи для CAN FD может достигать 5,9 Мбит/с, что почти в 6 раз выше, чем у классического CAN!

Таблица 8. Средняя скорость передачи CAN FD [5]

Частота передачи полезной нагрузки, Мбит/с Классический CAN CAN FD, 8 байт данных CAN FD, 16 байт данных CAN FD, 24 байт данных CAN FD, 48 байт данных CAN FD, 64 байт данных
1,0 1,0 1,0 1,0 1,0 1,0 1,0
2,0 1,0 1,6 1,7 1,8 1,9 1,9
3,0 1,0 2,0 2,3 2,4 2,7 2,7
4,0 1,0 2,3 2,7 3,0 3,3 3,5
5,0 1,0 2,5 3,1 3,4 4,0 4,2
6,0 1,0 2,7 3,4 3,8 4,5 4,8
7,0 1,0 2,9 3,6 4,1 5,0 5,4
8,0 1,0 3,0 3,8 4,4 5,5 5,9

Вполне очевидно, что средняя скорость передачи зависит от длины поля данных. Чем длиннее поле данных, тем выше средняя скорость (рисунок 3).

Рис. 3. Средняя скорость передачи CAN FD [5]

Рис. 3. Средняя скорость передачи CAN FD [5]

Теперь можно перейти к рассмотрению конкретных особенностей практической реализации CAN FD. 

Обзор рынка трансиверов CAN FD от ведущих производителей

Приемопередатчики для CAN FD

Как было показано на рисунке 1, узел CAN должен содержать два обязательных компонента: CAN-трансивер и CAN-контроллер. CAN-трансиверы преобразуют логические сигналы от CAN-контроллера в дифференциальный сигнал. В классическом случае CAN-приемопередатчик должен обеспечивать скорость передачи до 1 Мбит/с. Для реализации всех преимуществ CAN FD требуются более скоростные трансиверы. Сейчас стандартными являются скорости 2 и 5 Мбит/с, однако ряд производителей уже освоил выпуск трансиверов с пропускной способностью до 8 Мбит/с. Тем не менее, стоит отметить, что на скоростях до 1 Мбит/с в CAN FD могут использоваться и старые «медленные» приемопередатчики.

В качестве примера приведем ссылки на CAN-трансиверы, предлагаемые лидерами рынка:

Семейства от STMicroelectronics с поддержкой CAN-FD

Компания STMicroelectronics выпускает различные семейства микроконтроллеров STM32 c поддержкой классического CAN. Поддержка CAN FD есть в следующих семействах [6]:

  • микроконтроллеры общего назначения STM32G0 с процессорным ядром ARM Cortex-M0+;
  • микроконтроллеры общего назначения STM32G4 с процессорным ядром ARM Cortex-M4;
  • производительные микроконтроллеры STM32H7 с процессорным ядром ARM Cortex-M7;
  • малопотребляющие микроконтроллеры STM32L5 с процессорным ядром ARM Cortex-M33.

Для практической реализации мы будем использовать микроконтроллер STM32L5.

Блок-схема STM32L5 представлена на рисунке 4.

Рис. 4. Блок-схема микроконтроллеров STM32L5

Рис. 4. Блок-схема микроконтроллеров STM32L5

Для быстрого знакомства с CAN FD можно воспользоваться бюджетной платой NUCLEO-L552ZE-Q с микроконтроллером STM32L552ZET6QU (рисунок 5). На этой плате нет CAN-трансивера, однако выйти из ситуации поможет один из отладочных режимов EXTERNAL_LOOPBACK. В этом режиме встроенный FDCAN-контроллер передает и принимает свои же сообщения и сохраняет их в буфере Rx FIFO.

Рис. 5. Отладочная плата NUCLEO-L552ZE-Q

Рис. 5. Отладочная плата NUCLEO-L552ZE-Q

Рассмотрим особенности модуля FDCAN в STM32L5.

Особенности реализации контроллера CAN FD на примере модуля FDCAN микроконтроллеров STM32L5

Основные особенности модуля FDCAN в STM32L5

Модуль FDCAN, реализованный в STM32L5, совместим с ISO 11898-1: 2015 (версии 2.0 A, B) и протоколом CAN FD версии 1.0. Он имеет 0,8 кбайт ОЗУ, используемого для хранения принимаемых и передаваемых сообщений и идентификаторов.

Контроллер FDCAN в STM32L5 имеет следующие возможности и особенности:

  • поддержку сообщений с длиной поля данных до 64 байт;
  • мониторинг ошибок;
  • поддержку AUTOSAR и J1939;
  • два приемных FIFO-буфера вместимостью три сообщения (каждое сообщение может содержать до 64 байт данных);
  • два сигнала прерываний;
  • передающий FIFO-буфер вместимостью три сообщения (каждое сообщение может содержать до 64 байт данных);
  • FIFO-буфер событий;
  • поддержку отладочных режимов;
  • независимой домен тактирования ядра CAN;
  • поддержку режимов пониженного потребления.

Структура FDCAN в STM32L5 представлена на рисунке 6 [7].

Рис. 6. Блок-схема модулей FDCAN [9]

Рис. 6. Блок-схема модулей FDCAN [9]

ОЗУ

Для хранения идентификаторов фильтров, приемных и передающих буферов в FDCAN используется специальное ОЗУ (рисунок 7). Данные в ОЗУ храниться в виде 32-битных слов. Объем ОЗУ составляет 212 слов. Структура ОЗУ является фиксированной и не требует настройки со стороны пользователя. Она имеет следующие области:

  • фильтр 11-битных идентификаторов принимаемых сообщений – 28 элементов (структура и пояснения по работе элементов приводятся в следующем разделе);
  • фильтр 29-битных идентификаторов принимаемых сообщений – 8 элементов (структура и пояснения по работе элементов приводятся в следующем разделе);
  • приемный буфер RxFIFO 0 – 3 элемента;
  • приемный буфер RxFIFO 1 – 3 элемента;
  • буфер событий Tx event FIFO – 3 элемента;
  • буфер передатчика Tx buffer – 3 элемента.

Далее рассмотрим структуру элементов каждой из областей.

Рис. 7. Адресация встроенного ОЗУ

Рис. 7. Адресация встроенного ОЗУ

Фильтр ID входящих сообщений

FDCAN позволяет выполнять фильтрацию принимаемых сообщений по их идентификатору. Пользователю предоставляются сразу два фильтра: фильтр стандартных 11-битных идентификаторов (28 элементов) и фильтр расширенных 29-битных идентификаторов (8 элементов).

Форматы элементов фильтров представлены в таблицах 9 и 10.

Таблица 9. Формат элемента фильтра 11-битных ID [7]

Бит 31…24 23…16 15…8 7…0
S0 SFT[1:0] SFEC[2:0] SFID1[10:0] Res SFID2[10:0]

Таблица 10. Формат элемента фильтра 29-битных ID [7]

Бит 31…24 23…16 15…8 7…0
F0 EFEC[2:0] EFID1[28:0]
F1 EFTI[1:0] Res. EFID2[28:0]

Каждый из элементов фильтра может использоваться в различных режимах:

  • для фильтрации диапазона идентификаторов от SFID1 до SFID2 (аналогично для EFID1[28:0] и EFID2[28:0]);
  • для фильтрации двух конкретных идентификаторов SFID1 и SFID2 (аналогично для EFID1[28:0] и EFID2[28:0]);
  • для фильтрации по маске: маска 1 задается SFID1, маска 2 задается SFID2 (аналогично для EFID1[28:0] и EFID2[28:0]).

Алгоритм фильтрации достаточно прост: при приеме сообщения его идентификатор последовательно сравнивается со значениями фильтров, при совпадении фрейм копируется в приемный буфер. Если совпадений нет – кадр игнорируется.

RxFIFO-буферы принятых сообщений

Кадры, прошедшие фильтрацию, помещаются в приемный буфер RxFIFO 0 или RxFIFO 1. Каждый из буферов может хранить до 3 кадров длиной поля данных 64 байта. Формат элементов буферов представлен в таблице 11.

Таблица 11. Формат элемента приемного FIFO-буфера [7]

Бит 31…24 23…16 15…8 7…0
R0 ESI XTD RTR ID[28:0]
R1 ANMF FIDX[6:0] Резерв FDF BRS DLC[3:0] RXTS[15:0]
R2 DB3[7:0] DB2[7:0] DB1[7:0] D[7:0]
R3 DB7[7:0] DB6[7:0] DB5[7:0] DB4[7:0]
Rn DBm[7:0] DBm-1[7:0] DBm-2[7:0] DBm-3[7:0]

TxFIFO-буфер и TxQueue

Для отправки сообщений также используется буфер объемом до 3 элементов (3 кадра). Формат элемента представлен в таблице 12. Передающий буфер может работать в двух режимах:

  • в режиме FIFO-буфера, когда кадры передаются в порядке помещения в буфер;
  • в режиме TxQueue – очереди. Передача кадров ведется по их приоритету, определяемому идентификатором.

Таблица 12. Формат элемента передающего FIFO-буфера [7]

Бит 31…24 23…16 15…8 7…0
T0 ESI XTD RTR ID[28:0]
T1 MM[7:0] EFC Резерв FDF BPS DLC[3:0] Резерв
T2 DB3[7:0] DB2[7:0] DB1[7:0] D[7:0]
T3 DB7[7:0] DB6[7:0] DB5[7:0] DB4[7:0]
Tn DBm[7:0] DBm-1[7:0] DBm-2[7:0] DBm-3[7:0]

FIFO-буфер событий передаваемых сообщений

При передаче сообщений информация может сохраняться в специальном буфере событий. Формат элемента данного буфера представлен в таблице 13. Поле MM необходимо для хранения метки сообщения, назначаемой пользователем.

Таблица 13. Формат элемента буфера событий [7]

Бит 31…24 23…16 15…8 7…0
E0 ESI XTD RTR ID[28:0]
E1 MM[7:0] ET[1:0] EDL BRS DLC[3:0] TXTS[15:0]

Режимы работы

FDCAN может работать в нескольких режимах передачи, таких как:

  • классический CAN;
  • CAN FD без переключения частоты передачи;
  • CAN FD с переключением частоты передачи.

За настройку режимов отвечают биты регистров управления, как показано в таблице 14.

Таблица 14. Выбор режима работы FDCAN [7]

CCCR Элемент TX-буфера Тип фрейма
BRSE FDOE FDF BRS
Игнорируется 0 Игнорируется Игнорируется Классический фрейм CAN
0 1 0 Игнорируется Классический фрейм CAN
0 1 1 Игнорируется Фрейм CANFD без переключения скорости передачи
1 1 0 Игнорируется Классический фрейм CAN
1 1 1 0 Фрейм CANFD без переключения скорости передачи
1 1 1 1 Фрейм CANFD с переключением скорости передачи

Тестовые режимы работы

FDCAN может работать в нескольких режимах, таких как:

  • Normal – нормальный режим с возможностью приема и передачи;
  • Restricted Operation, при котором возможен прием сообщений и отправка сигнала подтверждения ACK;
  • Bus monitoring mode, в котором осуществляется только прием сообщений, отправка сообщений и подтверждений ACK запрещены;
  • Internal LoopBack mode, когда приемник и передатчик подключаются друг к другу внутри чипа, но отключаются от внешних выводов.
  • External LoopBack mode, когда приемник и передатчик подключаются друг к другу внутри чипа, кроме того, сигнал передатчика выведен на внешний вывод микроконтроллера.

Тестовые режимы Internal LoopBack Mode и External LoopBack Mode очень полезны при отладке приложений (рисунок 8). В частности, режим External LoopBack Mode позволяет проверить работу модуля и при передаче, и при приеме, а также отследить физические сигналы без необходимости подключения трансивера.

Рис. 8. Тестовые режимы работы FDCAN [7]

Рис. 8. Тестовые режимы работы FDCAN [7]

Битовая синхронизация

Для битовой синхронизации FDCAN предлагает задавать делитель тактового сигнала, длительность битовых сегментов и ширину скачка повторной синхронизации (SJW). Эти параметры задаются отдельно для нормальной и для ускоренной передач (рисунок 9).

Рис. 9. Битовая синхронизация FDCAN [7]

Рис. 9. Битовая синхронизация FDCAN [7]

Для нормальной передачи:

$$t_{q} = (FDCAN\_NBTP.NBRP[8:0] + 1) \times t_{fdcan\_tq\_clk}\\SyncSeg = 1\times t_{q}\\t_{BS1} = t_{q} \times (FDCAN\_NBTP.NTSEG1[7:0] + 1)\\t_{BS2} = t_{q} \times (FDCAN\_NBTP.NTSEG2[6:0] + 1)$$

Для фазы ускоренной передачи полезных данных:

$$t_{q} = (FDCAN\_DBTP.DBRP[4:0] + 1) \times t_{fdcan\_tq\_clk}\\SyncSeg = 1\times t_{q}\\t_{BS1} = t_{q}\times (FDCAN\_DBTP.DTSEG1[4:0] + 1)\\t_{BS2} = t_{q}\times (FDCAN\_DBTP.DTSEG2[3:0] + 1)$$

Практическое исследование возможностей CAN FD с помощью платы NUCLEO-L552ZE-Q

Создаем новый проект в STM32CubeIDE

Перед тем как приступить к созданию нового проекта в бесплатной среде STM32CubeIDE, следует скачать программный пакет STM32CubeL5 Firmware Package или обновить его, если он уже был ранее установлен. В этом пакете содержаться библиотеки для микроконтроллеров STM32L552ZET6QU. Там же можно найти шаблоны и примеры проектов для отладочных плат, в частности для NUCLEO-L552ZE-Q.

Для получения программного пакета STM32CubeL5 Firmware Package необходимо запустить STM32CubeIDE и войти в меню Help → Manage embedded software package, как показано на рисунке 10.

Рис. 10. Открытие менеджера программных пакетов в STM32CubeIDE

Рис. 10. Открытие менеджера программных пакетов в STM32CubeIDE

В менеджере программных пакетов требуется найти и установить/обновить STM32CubeL5 Firmware Package. Как видно на рисунке 11, в момент написания статьи актуальной была версия STM32CubeL5 Firmware Package V1.2.0 / 12-February-2020.

Рис. 11. Установка актуальной версии пакета STM32CubeL5 Firmware Package

Рис. 11. Установка актуальной версии пакета STM32CubeL5 Firmware Package

Далее создаем новый проект с помощью меню File → New → STM32 Project. Программа предложит выбрать подходящий контроллер. В нашем случае можно сразу перейти на вкладку Board Selector и выбрать отладочную плату NUCLEO-L552ZE-Q (рисунок 12). Это самый простой вариант, так как в этом случае нам не придется настраивать пины микроконтроллера вручную.

Рис. 12. Создание проекта для отладочной платы NUCLEO-L552ZE-Q

Рис. 12. Создание проекта для отладочной платы NUCLEO-L552ZE-Q

Последним шагом при создании нового проекта становится выбор имени и типа. В нашем случае это будет исполняемый проект для STM32Cube на языке С (рисунок 13).

Рис. 13. Настройка параметров проекта

Рис. 13. Настройка параметров проекта

Настраиваем периферию и тактирование в STM32CubeMX

Одним из преимуществ STM32CubeIDE является встроенный графический кодогенератор STM32CubeMX. С его помощью можно очень быстро настроить необходимую периферию, тактирование и даже ПО промежуточного уровня.

Для оценки работы нам потребуется настроить модуль FDCAN, систему тактирования и таймер TIM1. Таймер нужен исключительно для удобства работы с осциллографом. Будем передавать CAN-сообщения каждые 100 мс и измерять их длительность.

Новый проект является шаблоном для платы NUCLEO-L552ZE-Q, поэтому на диаграмме выводов некоторые контакты микроконтроллера уже заняты (рисунок 14).

Рис. 14. Пустой проект для платы NUCLEO-L552ZE-Q

Рис. 14. Пустой проект для платы NUCLEO-L552ZE-Q

Для начала настроим тактирование. Переходим на вкладку Clock Configuration. Выбираем встроенный генератор 16 МГц HSI для тактирования PLL. Для простоты не будем выполнять калибровку этого резонатора, но это приведет к некоторому отклонению от расчетных данных, полученных при сравнении эффективности CAN и CAN FD.

Далее в соответствии с рекомендациями CiA задаем частоту тактирования FDCAN 80 МГц, как показано на рисунке 15. При этом система автоматически подберет коэффициенты деления и умножения для получения необходимого сигнала PLLQ. Кроме того, система автоматически установит частоту тактирования APB timers clock 80 МГц – этот сигнал используется для тактирования таймера TIM1, – оставим ее без изменения.

Рис. 15. Частота тактирования FDCAN 80 МГц

Рис. 15. Частота тактирования FDCAN 80 МГц

Возвращаемся на вкладку Pinout & Configuration. Теперь настроим работу таймера TIM1. Он должен работать в базовом режиме (без внешних сигналов) и генерировать прерывания каждые 100 мс. Выбираем таймер TIM1 в панели Categories → Timers. В окне свойств задаем параметры, как показано на рисунке 16. Так как таймер работает в базовом режиме, все каналы остаются неактивными (Disabled). Частота тактирования таймера составляет 80 МГц, поэтому задаем делитель (Prescaler) 40000 и период (Counter period) 200.

Рис. 16. Настройка таймера TIM1

Рис. 16. Настройка таймера TIM1

Для простоты будем использовать прерывания таймера по обновлению. Для этого необходимо установить галочку напротив TIM1 Update Interval в панели NVIC Settings (рисунок 17).

Рис. 17. Настройка прерывания таймера TIM1 по обновлению

Рис. 17. Настройка прерывания таймера TIM1 по обновлению

Теперь приступим к настройке модуля FDCAN. Переходим на вкладку Categories → Connectivity → FDCAN. Дадим краткую характеристику всем доступным полям (рисунок 18):

  • Mode – режим работы CAN. Поддерживаются три режима работы:
    • Disable – выключен;
    • Classic Master – классический CAN;
    • FD – CAN FD.
  • Frame format – формат фрейма:
    • Classic mode – классический формат CAN;
    • FD mode without BitRate switching – формат CAN FD без переключения частоты;
    • FD mode with BitRate switching – формат CAN FD с переключением частоты.
  • Mode – режимы работы (подробнее о нем сказано выше):
    • Normal – нормальный режим с возможностью приема и передачи;
    • Restricted Operation – возможен прием сообщений и отправка сигнала подтверждения ACK;
    • Bus monitoring mode – только прием сообщений, отправка сообщений и подтверждений ACK запрещена;
    • Internal LoopBack mode – приемник и передатчик подключаются друг к другу внутри чипа, но отключаются от внешних выводов.
    • External LoopBack mode – приемник и передатчик подключаются друг к другу внутри чипа, кроме того, сигнал передатчика выведен на внешний вывод микроконтроллера.
  • Auto Retransmission – автоматическая повторная посылка сообщений;
  • Transmit Pause – дополнительная пауза при передаче. Такая пауза необходима для того чтобы дать другим передатчикам доступ к шине в случае, если их приоритет мал;
  • Protocol Exception – разрешение события Protocol Exception. При нормальной работе за битом FDF должен следовать резервный доминантный бит (res). Событие Protocol Exception генерируется в случаях, когда резервный бит имеет рецессивное значение;
  • Nominal Prescaler – номинальный делитель входной тактовой частоты FDCAN для генерации квантовых интервалов (tq). Используется при нормальной передаче.
  • Nominal Sync Jump Width – номинальная ширина скачка повторной синхронизации. Определяет допустимое расширение границ битовых сегментов Time Seg1 и Time Seg Используется при нормальной передаче;
  • Nominal Time Seg1 – номинальная длительность первого битового сегмента Time Seg1 в квантах tq. Используется при нормальной передаче;
  • Nominal Time Seg2 – номинальная длительность второго битового сегмента Time Seg2 в квантах tq. Используется при нормальной передаче;
  • Data Prescaler – делитель входной тактовой частоты FDCAN. Используется для генерации квантовых интервалов (tq) в фазе ускоренной передачи CAN FD;
  • Data Sync Jump Width – ширина скачка повторной синхронизации. Определяет допустимое расширение границ битовых сегментов Time Seg1 и Time Seg2 в фазе ускоренной передачи CAN FD;
  • Data Time Seg1 – длительность первого битового сегмента Time Seg1 в квантах tq в фазе ускоренной передачи CAN FD;
  • Data Time Seg2 – длительность второго битового сегмента Time Seg2 в квантах tq в фазе ускоренной передачи CAN FD;
  • Std Filter Nbr – число фильтров стандартных 11-битных ID;
  • Ext Filter Nbr – число фильтров расширенных 29-битных ID.
  • Tx FIFO Queue Mode – режим работы передающего буфера – FIFO-буфер или очередь (Queue).

В качестве отправной точки настроим модуль FDCAN для работы в режиме классического CAN с частотой 1 Мбит/с. Настройки модуля представлены на рисунке 18. Значения таймингов (Nominal Prescaler, Nominal Sync Jump Width, Nominal Time Seg1 и Nominal Time Seg2) выбраны, исходя из частоты тактирования FDCAN (80 МГц) и рекомендаций CiA. Будем использовать режим External LoopBack Mode, чтобы определить длительность фреймов на выводе микроконтроллера.

Рис. 18. Настройка FDCAN для работы в режиме классического CAN с частотой 1 Мбит/с

Рис. 18. Настройка FDCAN для работы в режиме классического CAN с частотой 1 Мбит/с

На этом первоначальная настройка в CubeMX закончена. Далее нажимаем иконку в виде шестеренки, тем самым генерируя код инициализации для нашего проекта. Теперь можно перейти к программированию на C.

Базовая С-программа

Выполним несколько опытов для различных настроек FDCAN, однако в каждом из них основная часть программы меняться не будет.

Для начала стоит отметить, что поскольку кодогенератор STM32CubeMX уже создал код инициализации, то от нас потребуется только добавить несколько строчек кода в файл main.c.

Важно! Добавлять пользовательский код следует только в разделы User Code, чтобы не потерять его при следующих обновлениях проекта.

Рассмотрим main.c и укажем, какие изменения в него нужно внести.

Кодогенератор автоматически определил переменные для инициализации периферии (листинг 1). Часть из этих переменных (hadc1, hlpuart1, hpcd_USB_FS) были определены в исходном шаблоне проекта, мы их использовать не будем.

Листинг 1. Переменные для инициализации периферии


/* Private variables ---------------------------------------------------------*/

ADC_HandleTypeDef hadc1;

FDCAN_HandleTypeDef hfdcan1;

UART_HandleTypeDef hlpuart1;

TIM_HandleTypeDef htim1;

PCD_HandleTypeDef hpcd_USB_FS;

Нам нужно определить массив данных, который мы будем передавать по CAN. Для этого объявим и сразу инициализируем массив TxData0 размером 64 байта в секции /* USER CODE BEGIN PV */ (листинг 2).

Листинг 2. Массив передаваемых данных



/* USER CODE BEGIN PV */

uint8_t TxData0[] = {     0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,

                          0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,

                          0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,

                          0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,

                          0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,

                          0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,

                          0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,

                          0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88

                      };

FDCAN_TxHeaderTypeDef TxHeader;

/* USER CODE END PV */

Функции инициализации периферии также созданы кодогенератором (листинг 3). Новых функций нам определять не потребуется.

Листинг 3. Функции инициализации периферии



/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_ADC1_Init(void);

static void MX_FDCAN1_Init(void);

static void MX_LPUART1_UART_Init(void);

static void MX_TIM1_Init(void);

static void MX_UCPD1_Init(void);

static void MX_USB_PCD_Init(void);

Из всех функций инициализации для нас представляет интерес только MX_FDCAN1_Init(void) (листинг 4). В ней происходит настройка FDCAN в точном соответствии с полями кодогенератора. HAL-функция HAL_FDCAN_Init использует переменную hfdcan1 для инициализации FDCAN.

Листинг 4. Функция инициализации MX_FDCAN1_Init(void)



static void MX_FDCAN1_Init(void)

{

  /* USER CODE BEGIN FDCAN1_Init 0 */

  /* USER CODE END FDCAN1_Init 0 */

  /* USER CODE BEGIN FDCAN1_Init 1 */

  /* USER CODE END FDCAN1_Init 1 */

  hfdcan1.Instance = FDCAN1;

  hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;

  hfdcan1.Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK;

  hfdcan1.Init.AutoRetransmission = DISABLE;

  hfdcan1.Init.TransmitPause = DISABLE;

  hfdcan1.Init.ProtocolException = DISABLE;

  hfdcan1.Init.NominalPrescaler = 1;

  hfdcan1.Init.NominalSyncJumpWidth = 10;

  hfdcan1.Init.NominalTimeSeg1 = 69;

  hfdcan1.Init.NominalTimeSeg2 = 10;

  hfdcan1.Init.DataPrescaler = 1;

  hfdcan1.Init.DataSyncJumpWidth = 2;

  hfdcan1.Init.DataTimeSeg1 = 7;

  hfdcan1.Init.DataTimeSeg2 = 2;

  hfdcan1.Init.StdFiltersNbr = 0;

  hfdcan1.Init.ExtFiltersNbr = 0;

  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;

  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)

  {

    Error_Handler();

  }

  /* USER CODE BEGIN FDCAN1_Init 2 */

  /* USER CODE END FDCAN1_Init 2 */

}

В основной функции int main(void) последовательно вызываются все функции инициализации. От нас требуется только запустить работу таймера и FDCAN. Для этого необходимо добавить соответствующий код в секцию /* USER CODE BEGIN 2 */ (листинг 5).

Листинг 5. Добавление кода для запуска таймера и FDCAN



  /* USER CODE BEGIN 2 */

  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK) // Запускаем FDCAN

  {

    Error_Handler();

  }

  if(HAL_TIM_Base_Start_IT(&htim1) != HAL_OK) // Запускаем таймер

  {

    /* Starting Error */

    Error_Handler();

  }

  /* USER CODE END 2 */

Ранее мы решили передавать сообщения CAN каждые 100 мс по прерыванию от таймера. Обработчик прерывания добавляем в секцию USER CODE BEGIN 4 */ (листинг 6). Здесь стоит отметить, что мы будем отправлять два сообщения подряд. Это нужно для правильного измерения длительности фреймов. В таком случае конец первого фрейма можно будет определить по началу второго фрейма. В тексте кода приведены поясняющие комментарии.

Листинг 6. Обработчик прерывания таймера в режиме CAN



/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

//первое сообщение

     TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

     TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

     TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

     TxHeader.DataLength = FDCAN_DLC_BYTES_8; // Длина данных 8 байт

     TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

     TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Без переключения частоты передачи

     TxHeader.FDFormat = FDCAN_CLASSIC_CAN; // Формат классического кадра CAN

     TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

     TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            } 

// Второе сообщение идентично первому

     TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

     TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

     TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

     TxHeader.DataLength = FDCAN_DLC_BYTES_8; // Длина данных 8 байт

     TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

     TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Без переключения частоты передачи

     TxHeader.FDFormat = FDCAN_CLASSIC_CAN; // Формат классического кадра CAN

     TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

     TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            } 

}

/* USER CODE END 4 */

Теперь можно скомпилировать и запустить выполнение программы. Для этого кликаем по иконке с жуком или нажимаем клавишу F11.

Измеряем длину классического CAN-фрейма с помощью осциллографа

Так как мы выбрали режим External LoopBack Mode, то выходной сигнал передатчика CAN можно снять с вывода CAN _TX. Этот вывод доступен на колодке CN9, как показано на рисунке 19.

Рис. 19. Сигнал измеряется на выводе CAN Tx

Рис. 19. Сигнал измеряется на выводе CAN Tx

На осциллограмме, представленной на рисунке 20, видно, что посылки следуют каждые 100 мс, как и было запланировано.

Рис. 20. Передача сообщений происходит каждые 100 мс

Рис. 20. Передача сообщений происходит каждые 100 мс

Для измерения используем нормальный режим работы осциллографа с синхронизацией по срезу. Начало фрейма определяется автоматически, а конец определяем по началу второго фрейма (рисунок 21). Как видно из осциллограммы, длительность классического фрейма CAN c 11-битным идентификатором и 8 байт данных составила около 113 мкс. Так как длина фрейма равна 111 битам, то частота передачи примерно соответствует 1 Мбит/с. Таким образом, настройка FDCAN в режиме классического CAN была выполнена верно. Небольшое отклонение связано с погрешностью используемого резонатора HSI.

Рис. 21. Осциллограмма классического кадра CAN: 8 байт данных, 1 Мбит/с

Рис. 21. Осциллограмма классического кадра CAN: 8 байт данных, 1 Мбит/с

Полученный результат соответствует расчетам и будет использоваться в качестве ориентира для следующих опытов:

  • измерение длины фрейма CAN-FD: 8 байт данных при частоте передачи 1 Мбит/с;
  • измерение длины фрейма CAN-FD: 64 байт данных при частоте передачи 1 Мбит/с;
  • измерение длины фрейма CAN-FD: 8 байт данных с переключением частоты передачи 1 → 8 Мбит/с;
  • измерение длины фрейма CAN-FD: 64 байт данных с переключением частоты передачи 1 → 8 Мбит/с.

Измерение длины фрейма CAN-FD: 8 байт данных, частота передачи 1 Мбит/с

Теперь измерим длину фрейма CAN-FD с 8 байт данных при частоте передачи 1 Мбит/с (без переключения частоты передачи).

Для начала необходимо внести некоторые изменения в наш проект. Начинаем с внесения изменений в настройки FDCAN в STM32CubeMX, как показано на рисунке 22:

  • режим работы – FD;
  • формат фрейма – FD mode without BitRate switching (формат CAN FD без переключения частоты);
  • Data Prescaler = 1 (в соответствии с рекомендациями CiA);
  • Data Sync Jump Width =2 (в соответствии с рекомендациями CiA);
  • Data Time Seg1 = 7 (в соответствии с рекомендациями CiA);
  • Data Time Seg2 =2 (в соответствии с рекомендациями CiA);
  • остальные характеристики не меняем.

Рис. 22. Настройка FDCAN для работы в режиме FD 1 Мбит/с без переключения частоты

Рис. 22. Настройка FDCAN для работы в режиме FD 1 Мбит/с без переключения частоты

Далее генерируем код. Система автоматически корректирует код инициализации, при этом пользовательские секции остаются без изменений.

Нам нужно поменять только содержимое функции HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim) (листинг 7).

Листинг 7. Обработчик прерывания таймера в режиме CAN FD c фреймом 8 байт без переключения частоты



/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

// Первое сообщение

     TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

     TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

     TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

     TxHeader.DataLength = FDCAN_DLC_BYTES_8; // Длина данных 8 байт

     TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

     TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Без переключения частоты передачи

     TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

     TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

     TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            } 

// Второе сообщение идентично первому

      TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_8; // Длина данных 8 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Без переключения частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            }

На рисунке 23 представлена осциллограмма кадра CAN FD. Длительность кадра составила около 129 мкс, что больше чем у классического CAN. Объясняется это тем, что объем служебной информации фрейма CAN FD больше (его полная длина 122 бит). Таким образом, в режиме без переключения частоты и длине данных 8 и менее байт CAN FD оказывается менее эффективным. Однако все меняется при увеличении объема данных и повышении частоты передачи.

Рис. 23. Осциллограмма кадра CAN FD: 8 байт данных, 1 Мбит/с, без переключения частоты

Рис. 23. Осциллограмма кадра CAN FD: 8 байт данных, 1 Мбит/с, без переключения частоты

Измерение длины фрейма CAN-FD: 64 байт данных, частота передачи 1 Мбит/с

Теперь измерим длину фрейма CAN-FD с 64 байт данных при частоте передачи 1 Мбит/с (без переключения частоты передачи).

Менять конфигурацию FDCAN в CubeMX не требуется. Изменения касаются только кода функции HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim) (листинг 8).

Листинг 8. Обработчик прерывания таймера в режиме CAN FD c фреймом 64 байта без переключения частоты



/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

// Первое сообщение

      TxHeader.Identifier = 0x555; // идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_64; // Длина данных 64 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Без переключения частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            } 

// Второе сообщение идентично первому

      TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_64; // Длина данных 64 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_OFF; // Без переключения частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            }

Из осциллограммы, представленной на рисунке 24, видно, что длительность фрейма составила около 586 мкс. Это отличный результат. Передача такого же объема информации (64 байта) потребует 8 классических кадров, что займет около 900 мкс. Преимущество CAN FD становится еще более очевидным при увеличении частоты передачи.

Рис. 24. Осциллограмма кадра CAN FD: 64 байт данных, 1 Мбит/с, без переключения частоты

Рис. 24. Осциллограмма кадра CAN FD: 64 байт данных, 1 Мбит/с, без переключения частоты

Измерение длины фрейма CAN-FD: 8 байт данных, с переключением частота передачи 1 → 8 Мбит/с

Теперь измерим длину фрейма CAN-FD с 8 байт данных и с переключением частота передачи 1 → 8 Мбит/с.

Необходимо внести некоторые изменения в настройки FDCAN в STM32CubeMX, как показано на рисунке 25:

  • формат фрейма – FD mode with BitRate switching (формат CAN FD без переключения частоты);
  • остальные характеристики не меняем.

Рис. 25. Настройка FDCAN для работы в режиме FD с переключением частоты

Рис. 25. Настройка FDCAN для работы в режиме FD с переключением частоты

Теперь изменим функцию HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim) (листинг 9).

Листинг 9. Обработчик прерывания таймера в режиме CAN FD c фреймом 8 байт и с переключением частоты



/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

// Первое сообщение

      TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_8; // Длина данных 8 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_ON; // C переключением частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            } 

// Второе сообщение идентично первому

      TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_8; // Длина данных 8 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_ON; // C переключением частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            }

Как показано на следующей осциллограмме (рисунок 26), длительность фрейма уменьшилась до 42 мкс, то есть примерно в три раза. Это в 2,5 раза меньше чем у классического CAN.

Рис. 26. Осциллограмма кадра CAN FD: 8 байт данных, с переключением частота передачи 1 → 8 Мбит/с

Рис. 26. Осциллограмма кадра CAN FD: 8 байт данных, с переключением частота передачи 1 → 8 Мбит/с

Измерение длины фрейма CAN-FD: 64 байт данных, с переключением частота передачи 1 → 8 Мбит/с

Теперь измерим длину фрейма CAN-FD с 64 байт данных и с переключением частоты передачи 1 → 8 Мбит/с.

Менять конфигурацию FDCAN в CubeMX не требуется. Изменения касаются только кода функции HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim) (листинг 10).

Листинг 10. Обработчик прерывания таймера в режиме CAN FD c фреймом 10 байт и с переключением частоты



/* USER CODE BEGIN 4 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

// Первое сообщение

      TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_64; // Длина данных 64 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_ON; // C переключением частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            } 

// Второе сообщение идентично первому

      TxHeader.Identifier = 0x555; // Идентификатор передаваемого сообщения

      TxHeader.IdType = FDCAN_STANDARD_ID; // 11-битный ID

      TxHeader.TxFrameType = FDCAN_DATA_FRAME; // Передача обычного кадра данных

      TxHeader.DataLength = FDCAN_DLC_BYTES_64; // Длина данных 64 байт

      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Индикатор ошибок активен

      TxHeader.BitRateSwitch = FDCAN_BRS_ON; // C Переключением частоты передачи

      TxHeader.FDFormat = FDCAN_FD_CAN; // Формат кадра CAN FD

      TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;// Сохранение параметров события

      TxHeader.MessageMarker = 0x52;// Метка сообщения

            if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData0) != HAL_OK)

            {

            Error_Handler();

            }

Длительность фрейма составила 99 мкс (рисунок 27). То есть для передачи 64 байт информации CAN FD потратил меньше времени, чем классический CAN на передачу 8 байт. Таким образом, средняя скорость передачи CAN FD, полученная при переключении частоты 1 → 8 Мбит/с, примерно равна 5,8 Мбит/с (574 бита/99 мкс). Это почти в 6 раз выше чем у классического CAN.

Рис. 27. Осциллограмма кадра CAN FD: 64 байт данных, с переключением частота передачи 1 → 8 Мбит/с

Рис. 27. Осциллограмма кадра CAN FD: 64 байт данных, с переключением частота передачи 1 → 8 Мбит/с

Краткое сравнение CAN и CAN FD

В сводной таблице 15 сравниваются основные параметры CAN и CAN FD.

Таблица 15. Итоговое сравнение CAN и CAN FD

Параметр CAN 2.0 CAN-FD
Совместимость Не поддерживает CAN-FD Совместим с CAN 2.0 A/B
Максимальная частота передачи, Мбит/с До 1 До 8
Эффективная скорость передачи, Мбит/с До 1 До 5,9
Объем данных в одном фрейме, байт До 8 До 64
Эффективность использования фрейма, % До 58 До 89
Поддержка BRS +
Поддержка EDL +
Поддержка ASI +
CRC, бит 15 17/21
Поддержка RTR +

Итог

Мы рассмотрели основные особенности реализации модулей FDCAN микроконтроллеров STM32L552ZET6QU и разобрали пример практической реализации CAN FD с помощью платы NUCLEO-L552ZE-Q. Данная реализация носила ограниченный характер, так как не использовала реальный трансивер, а модуль FDCAN работал в режиме с внешней синхронизацией (External LoopBack mode). Тем не менее, в ходе испытаний удалось оценить длительность фреймов FDCAN и измерить реальную среднюю скорость передачи. Практические данные соответствовали расчетным с учетом погрешности используемого тактового резонатора HSI.

Расчет эффективности и средней скорости передачи данных для классического CAN и CAN FD показал, что при использовании максимальной частоты ускоренной передачи 8 Мбит/с и длины данных 64 байта средняя скорость передачи CAN FD будет почти в шесть раз выше.

Литература

  1. CAN FD – The basic idea
  2. Application Report. Introduction to the Controller Area Network. SLOA101B–August 2002–Revised May 2016. (CAN)
  3. CiA 301 version 4.2.0. CANopen application layer and communication profile
  4. Cyclic redundancy check (CRC) in CAN frames
  5. Калькулятор эффективности CAN
  6. FDCAN peripheral on STM32 devices
  7. Reference manual. STM32L552xx and STM32L562xx advanced Arm®-based. 32-bit MCUs
•••

Наши информационные каналы

О компании ST Microelectronics

Компания STMicroelectronics является №1 производителем электроники в Европе. Компоненты ST широко представлены в окружающих нас потребительских товарах – от iPhone до автомобилей разных марок. Лидеры индустриального рынка выбирают компоненты ST за их надежность и выдающиеся технические параметры. В компании ST работает 48 000 сотрудников в 35 странах. Производственные мощности расположены в 12 странах мира. Более 11 тысяч сотрудников заняты исследованиями и разработками – инновационное лидерство ...читать далее

Товары
Наименование
STM32L562E-DK (ST)
NUCLEO-L552ZE-Q (ST)
STM32L552CCT6 (ST)
STM32L552VCT6Q (ST)
STM32L552CEU6P (ST)
STM32L552RET6Q (ST)
STM32L552RET6 (ST)
STM32L562CET6 (ST)
STM32L562CET6P (ST)
STM32L552RET6P (ST)