FDCAN, это аббревиатура от Flexible Data-Rate Controlled Area Network (гибкая сеть с контролируемой скоростью передачи данных). Как следует из названия, это существенное усовершенствование по сравнению с обычным CAN, особенно в тех областях, где CAN был очень ограничен, например, в объеме данных и пропускной способности. FDCAN преодолевает эти недостатки, что делает его пригодным для современных приложений.Рассмотрим настройку FDCAN, а также простой тест, выполненный в режиме
обратной связи.
Формат FDCAN
Ниже приведено изображение, демонстрирующее формат FDCAN.
- Первый этап арбитража — это сообщение, содержащее:
- начало кадра ( SOF )
- Идентификационный номер и другие биты, указывающие на назначение сообщения (предоставление или запрос данных), а также конфигурацию скорости и формата (CAN или CAN-FD).
- Этап передачи данных состоит из:
- Код длины данных ( DLC ) указывает, сколько байтов данных содержит сообщение.
- данные , которые пользователь желает отправить
- контрольная циклическая избыточность ( CRC )
- доминирующий фрагмент
- Второй этап арбитражного разбирательства включает в себя:
- получатель подтверждения ( ACK ), передаваемого другими узлами в шине.
- конец кадра ( EOF )
В процессе IFS никакие сообщения не передаются : цель состоит в том, чтобы отделить текущий кадр от следующего.
Давайте сравним архитектуру Frame между CAN-FD и CAN 2.0.
- CAN 2.0 отправляет бит RTR для уточнения типа кадра: кадр данных (RTR является доминирующим) или удаленный кадр (RTR является рецессивным), тогда как CAN-FD всегда отправляет доминирующий бит RRS (зарезервированный), поскольку поддерживает только кадры данных.
- В формате CAN-FD в поле управления добавлены три новых бита по сравнению с CAN 2.0:
- Бит расширения длины данных ( EDL ): является рецессивным и указывает на то, что кадр относится к типу CAN-FD; в противном случае этот бит является доминирующим (называемым R0) в кадре CAN 2.0.
- Переключение битовой скорости ( BRS ): указывает, включены ли две битовые скорости (например, когда фаза данных передается с другой битовой скоростью, чем фаза арбитража).
- Индикатор состояния ошибки ( ESI ): указывает, находится ли узел в активном или пассивном режиме обработки ошибок.
Основные различия между CAN-FD и CAN 2.0 показаны ниже:
Настройка
Этот раздел будет очень обширным, поскольку мы рассмотрим настройку cubeMX, а также огромное количество параметров и причины, по которым они имеют такие значения.
В этом руководстве я выбираю внутреннюю тактовую частоту 64 МГц . Причина этого будет объяснена чуть позже. Также обратите внимание, что тактовая частота FDCAN составляет 50 МГц. Она будет использоваться в последующей части руководства.
Здесь я включил FDCAN для Cortex M7. Обратите внимание, что контакты PH13 — это контакт TX, а PH14 — контакт RX.
В используемом мной контроллере H745 Discovery трансивер расположен непосредственно на плате. Микросхема MCP2562FDT подключена к контактам PH13 и PH14. Разъемы на плате предназначены для CANH и CANL. Это показано на рисунке ниже.
В модуле CAN-FD много параметров для настройки, поэтому мы рассмотрим лишь некоторые из них за раз.
- Здесь я использую формат FD Mode без переключения битрейта.
- На самом деле, FD CAN может передавать поле арбитража и поле данных с разной скоростью передачи. Но я хочу использовать одинаковую скорость передачи для обоих устройств.
- В режиме установлен режим внешней обратной связи (External LoopBack Mode). Вы также можете использовать режим внутренней обратной связи (Internal LoopBack), поскольку они в основном идентичны.
- Я включил автоматическую повторную передачу в случае ошибок и отключил остальные несущественные параметры.
В режиме обратной связи (LoopBack Mode) FDCAN обрабатывает передаваемые им сообщения как принятые и сохраняет их, если они проходят фильтрацию на соответствие требованиям. Фактически, вывод TX внутренне соединен с выводом RX, как показано ниже.
Для расчета этого набора параметров нам потребуется использовать внешний калькулятор, который можно найти по адресу https://www.kvaser.com/support/calculators/can-fd-bit-timing-calculator/
Первые 3 параметра, которые нам необходимо ввести, это частота тактового сигнала FDCAN, допуск входного тактового сигнала и задержка приемопередающего узла.
Тактовая частота FDCAN составляет 50 МГц , и мы уже рассматривали это в начале данного раздела.
Далее следует допуск тактовой частоты . В начале я упоминал, что в этом руководстве использую внутреннюю тактовую частоту, потому что так проще определить допуск тактовой частоты для входного сигнала. На рисунке ниже это наглядно показано:
Наконец, у нас есть задержка узла или задержка распространения. Ее можно найти в характеристиках переменного тока используемого вами трансивера.
Как я уже упоминал, на используемой мной плате установлен встроенный трансивер MCP2562FD. Выше приведены его характеристики переменного тока, и я использую задержку 180 нс.
После ввода всех значений необходимо добавить CAN-устройство.
Далее нам необходимо ввести битрейт , который мы хотим установить для CAN-шины.
Как я уже упоминал, FD CAN может передавать поле арбитража и данные с разной скоростью передачи. Но я хочу использовать одинаковую скорость передачи для обоих полей, а именно 500 Кбит/с. После ввода скорости передачи нажмите «Пересчитать», чтобы получить значения.
После нажатия кнопки «Пересчитать» мы получим значения параметров. Это показано на рисунке ниже.
Эти значения можно ввести в параметры FDCAN.
Теперь рассмотрим остальные параметры. Стрелками отмечены параметры, которые были изменены.
- На изображении выше смещение оперативной памяти (Ram offset) установлено на 0. Это используется в нескольких экземплярах FDCAN и будет рассмотрено в следующем уроке.
- Std Filters Nbr— это количество используемых нами стандартных (ID) фильтров.
- Мы можем использовать до 128 различных фильтров, настроенных для приема или отклонения сообщений с разными идентификаторами.
- Я использую только один фильтр.
- Ext Filters NbrЗначение установлено на 0, поскольку в этом руководстве мы не используем расширенные идентификаторы.
- Для приема сообщения мы будем использовать RX FIFO 0. Всего мы можем использовать до 64 элементов FIFO, и каждый элемент может хранить до 64 байт данных.
- Здесь я использую всего один элемент для приема 12 байт данных.
- Я не использую буферы приема и передачи, поэтому все эти параметры установлены на 0.
- Блок TX Fifo будет использоваться для отправки данных на шину CAN. Таким образом, здесь я использую один элемент блока TX Fifo для отправки 12 байт данных.
И последнее, что нам нужно сделать, это включитьПрерывание RX Fifo 0Это прерывание будет срабатывать всякий раз, когда мы получим новое сообщение в буфере приема RX Fifo 0.
На этом настройка FDCAN завершена. Теперь давайте рассмотрим код.
Конфигурация фильтра
Как и в обычном CAN-шине, в FDCAN тоже есть фильтры. Здесь всё немного сложнее, поскольку существует множество типов фильтров. Давайте рассмотрим их подробнее.
В FDCAN доступны 4 типа фильтров:
- Фильтр диапазона (RANGE Filter ) фильтрует сообщения, поступающие от идентификаторов, находящихся в диапазоне от ID1 до ID2.
- Фильтр DUAL , который фильтрует сообщения, относящиеся исключительно к двум идентификаторам: ID1 и ID2.
- Фильтр MASK , который фильтрует сообщения на основе идентификатора (ID1) и маски (ID2). Это похоже на то, что мы делали в уроке по CAN, и сегодня мы будем следовать этому принципу.
- Фильтр диапазона без внешних идентификаторов , который фильтрует данные так же, как и обычный фильтр диапазона, но внешние идентификаторы в этом случае фильтроваться не будут.
Помимо типов фильтров, у нас также есть раздел «Конфигурация фильтров». В этом поле определяется, что следует делать с отфильтрованными сообщениями. Например, следует ли отправлять сообщения в FIFO, отклонять их, помечать как сообщения с высоким приоритетом и т. д.
По сути, вы можете настроить несколько фильтров одновременно, и конфигурация каждого фильтра будет храниться в отдельном индексе фильтров.
В этом уроке я буду использовать фильтр «Маска», и отфильтрованные сообщения будут отправляться в FIFO. Ниже приведена конфигурация для этого.
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x11;
sFilterConfig.FilterID2 = 0x11;
sFilterConfig.RxBufferIndex = 0;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
Error_Handler();
}
- Параметр IdType определяет, используем ли мы стандартные или расширенные идентификаторы.
- Filterindex используется при настройке нескольких фильтров. Поскольку я использую только один фильтр, он установлен на 0.
- FilterType — это тип используемого нами фильтра. Как я уже упоминал, я использую фильтр MASK.
- В этом фильтре MASK ID1 (0x11) будет выступать в качестве идентификатора, а ID2 (0x11) — в качестве битов маски.
- Если вы хотите узнать больше о том, как это работает, я бы посоветовал вам посмотреть видео по ссылке https://youtu.be/JfWlIY0zAIc
- FilterConfig определяет, что следует делать с сообщениями, проходящими через фильтр. Он настроен на отправку в RX FIFO 0.
- Параметр RxBufferIndex используется, если вы используете буфер приема (RX Buffer) вместо FIFO, поэтому здесь он установлен на 0.
В заключение функция ConfigFilter настроит указанный выше фильтр.
Кодекс
Начнём с нескольких определений.
FDCAN_TxHeaderTypeDef TxHeader;
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t TxData[12];
uint8_t RxData[12];
int indx = 0;
- Здесь я определил заголовки и буферы для передачи и приема.
- Индексная переменная будет увеличена позже в коде.
В основной функции мы запустим FDCAN и настроим уведомление о новом сообщении в буфере RX Fifo 0.
if(HAL_FDCAN_Start(&hfdcan1)!= HAL_OK)
{
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
/* Notification Error */
Error_Handler();
}
Здесь FDCAN_IT_RX_FIFO0_NEW_MESSAGE — это флаг прерывания. Он, по сути, включает прерывание для нового сообщения в RX FIFO 0.
Когда в буфер приема RX FIFO 0 поступает новое сообщение, вызывается обработчик прерывания. Мы будем обрабатывать полученные данные внутри этого обработчика прерывания.
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
{
/* Retreive Rx messages from RX FIFO0 */
if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
{
/* Reception Error */
Error_Handler();
}
if (HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
/* Notification Error */
Error_Handler();
}
}
}
- Здесь мы скопируем заголовок сообщения в RXHeader , а данные сообщения — в RxData .
- Мы снова активируем уведомление, поскольку прерывание отключается после каждого вызова.
В основной функции мы настроим заголовок TX перед отправкой сообщения на шину CAN.
TxHeader.Identifier = 0x11;
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_12;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_FD_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
- Идентификатор — это идентификатор передатчика, который будет равен 0x11.
- В этом руководстве для параметра IdType установлено значение Standard ID, поскольку мы не используем Extended ID.
- Параметр TxFrameType указывает, отправляем ли мы кадр данных или удаленный кадр. В этом случае он устанавливается в значение Data Frame.
- Параметр DataLength установлен на 12 байт. Это длина фактических данных, которые мы собираемся отправить.
- Индикатор ErrorStateIndicator активен и уведомит нас в случае возникновения ошибок при передаче данных.
- Функция BitrateSwitch отключена, как я уже упоминал, мы будем использовать один и тот же битрейт как для поля арбитража, так и для поля данных.
- Параметр FDFormat указывает, хотите ли вы использовать стандартный CAN или FD CAN. В данном случае он установлен на FD CAN.
- Мы не используем TxEvent или MessageMarker.
В цикле while мы будем отправлять данные с интервалом в 1 секунду.
while (1)
{
for (int i=0; i<12; i++)
{
TxData[i] = indx++;
}
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData)!= HAL_OK)
{
Error_Handler();
}
HAL_Delay (1000);
}
- Здесь мы сначала заполним массив TxData целочисленными значениями.
- Затем функция HAL_FDCAN_AddMessageToTxFifoQдобавит сообщение в очередь FIFO.
- После добавления сообщения в очередь FIFO, оно будет передано в шину CAN.
- Наконец, задержка в 1000 мс обеспечит повторение цикла каждую секунду.
Результат
Ниже представлены изображения, полученные из функции Live Expression в отладчике. Вы можете видеть, что значения TxData и RxData совпадают.
Мы обновляем данные в транзакции TxData, которые затем поступают в буфер FIFO и передаются в транзакцию RxData.


















