Меню

Hal can stm32 обработка ошибок

Один из немаловажных аспектов работы CAN шины является обработка прерываний bxCan. Их не так уж и много, но при правильной их настройке и обработке мы сможем обеспечить максимальную работоспособность и высокую отказоустойчивость нашего устройства. Поэтому следует обратить наше внимание на то, как это сделать правильно — создать необходимый минимум.

Теория

Начнем опять с теории и обратимся к Reference Maanual от ST Microelectronics.

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

Прерывания

Для bxCan может быть назначено четыре прерывания. Каждый из источников прерываний может быть включен или выключен независимо друг от друга в регистре CAN_IER (CAN Interrupt Enable Register).

Вот схема отработки прерываний приведенная в мануале:

Рис. 1. Флаги событий и формирование прерываний

Как видим на рисунке 1, прерывания сгруппированы в четыре группы:

Transmit interrupt  (Прерывание при передаче сообщения) — может быть вызвано следующими событиями:

— Выполнена передача и освобожден mailbox 0. Бит RQCP0 в регистре CAN_TSR установлен;
— Выполнена передача и освобожден mailbox 1. Бит RQCP1 в регистре CAN_TSR установлен;
— Выполнена передача и освобожден mailbox 2. Бит RQCP2 в регистре CAN_TSR установлен.

FIFO0 interrupt (Прерывание связанное с входящим буфером FIFO0) — вызывается по следующим событиям:

— Прием нового сообщения, биты FMP0 в регистре CAN_RF0R не равны «00». В принципе значение этого регистра говорит нем о том, сколько сообщений в буфере FIFO еще не обработано программой;
— Буфер FIFO0 заполнен. Бит FULL0  в регистре CAN_RF0R установлен — сообщает нам о том, что в буфере FIFO0 больше нет свободного места;
— Переполнение буфера FIFO0. Бит FOVR0 в регистре CAN_RF0R установлен — возникает в случае когда буфер FIFO0 заполнен и по шине принято еще одно сообщение. Что с этим сообщением произойдет, мы указываем в настройках инициализации CAN (параметр CAN_RFLM).

FIFO1 interrupt (Прерывание связанное с входящим буфером FIFO1) — вызывается по следующим событиям:

— Прием нового сообщения, биты FMP1 в регистре CAN_RF1R не равны «00». В принципе значение этого регистра говорит нем о том, сколько сообщений в буфере FIFO еще не обработано программой;
— Буфер FIFO1 заполнен. Бит FULL1  в регистре CAN_RF0R установлен — сообщает нам о том, что в буфере FIFO1 больше нет свободного места;
— Переполнение буфера FIFO1. Бит FOVR1 в регистре CAN_RF0R установлен — возникает в случае когда буфер FIFO1 заполнен и по шине принято еще одно сообщение. Что с этим сообщением произойдет, мы указываем в настройках инициализации CAN (параметр CAN_RFLM).

 • Error and Status change Interrupt (Прерывание по возникновению ошибок и изменению состояния bxCAN) — вызывается по следующим событиям:

— Возникновение ошибки. Информация об ошибке хранится в регистре CAN Error (CAN_ESR);
— «Просыпание» контроллера — выход из режима сна, когда на Rx появился сигнал CAN шины;
— Переход в спящий режим.

Четвертая группа отвечает за прерывания не только ошибок, но, как видно из названия, и за изменения статуса (режима) bxCan. 

Регистры

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

Для того, чтобы мы смогли программно обработать прерывания bxCan, необходимо изучить регистры микроконтроллера, которые непосредственно связаны с этими прерываниями. Разработчики ST Microelectronix постарались для нас и большинство функционала для работы CAN шины возложили на аппаратную часть микроконтроллера, но все же нам придется выполнить некоторые действия самостоятельно.

За обработку ошибок, включение/выключение прерываний CAN шины, а также за информацию о текущем статусе шины и ошибок в bxCan отвечают шесть регистров, которые мы сейчас и изучим:

CAN master status register (CAN_MSR)

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

CAN Master Status Register предоставляет нам информацию о том, в каком состоянии находится bxCan и сообщает нам о прерываниях, если они установлены.

Рис. 2. CAN master status register.

Address offset: 0x04
Reset value: 0x0000 0C02

Биты Название Описание
 31:12 Зарезервировано   
11 RX — CAN Rx signal CAN Rx сигнал.
Контролирует фактическое состояние пина CAN_Rx
10  SAMP — Last sample point Последнее принятое значение.
Значение RX на последней точки выборки (фактически значение последнего принятого бита).
RXM — Receive mode Режим передачи.
Сообщает, что bxCan находится в режиме передачи сообщения.
TXM — Transmit mode Режим приема.
Сообщает, что bxCan находится в режиме приема сообщения.
7:5  Зарезервировано   
SLAKI — Sleep acknowledge interrupt Бит прерывания при переходе в спящий режим.
Когда SLKI = 1, то этот бит устанавливается аппаратно и сигнализирует о том, что bxCan вошел в режим «спячки». После установки этого бита генерируется прерывание по переходу в спящий режим (если установлен бит SLKIE в регистре CAN_IER).
SLAKI может сбрасываться программно или аппаратно, когда сбрасывается бит SLAK.
Примечание: когда бит SLKIE = 0, то нельзя выполнить опрос бита SLAKI. В этом случае необходимо читать значение бита SLAK.
WKUI — Wakeup interrupt Бит прерывания при возврате из «спящего» режима.
Этот бит аппаратно устанавливает сигнал о том, что бит SOF был обнаружен, в то время, как bxCan находился в спящем режиме.
Установка этого бита генерирует изменение статуса прерывания, если бит WKUIE регистра CAN_IER был установлен.
Сбрасывается этот бит с помощью программного обеспечения.
ERRI — Error interrupt Бит прерывание по ошибке.
Этот бит устанавливается аппаратно, когда бит в регистре CAN_ESR был установлен на обнаружение ошибок и при этом включено соответствующее прерывание в регистре CAN_IER.
Установка этого бита генерирует прерывание, если установлен бит ERRIE в регистре CAN_IER.
Очищается с помощью программного обеспечения.
SLAK — Sleep acknowledge Режим сна.
Этот бит устанавливается аппаратно и указывает на то, что bxCan находится в режиме сна. Этот бит подтверждает запрос о переходе в «спящий» режим из программного обеспечения (установка бита Sleep в регистре CAN_MCR).
Сбрасывается аппаратно, когда bxCan переходит в спящий режим (для синхронизации по CAN — шине). Для синхронизации устройств на шине необходимо контролировать последовательность 11-ти рецессивных бит подряд на сигнале CAN_RX.
Процесс выхода из сна запускается, когда сбрасывается бит SLEEP в регистре CAN_MCR.
Автоматическое пробуждение из режима сна происходит при установке бита AWUM регистра CAN_MCR.
INAK — Initialization acknowledge Режим инициализации.
Этот бит устанавливается аппаратно и указывает программному обеспечению на то, что bxCan находится в режиме инициализации. Этот бит подтверждает запрос инициализации из программного обеспечения (установлен бит INRQ в регистре CAN_MCR).
Бит INAK сбрасывается автоматически, когда bxCan выходит из режима инициализации.
Для того чтобы синхронизировать устройства с шиной, необходимо контролировать последовательность 11 рецессивных бит подряд на CAN_RX.

CAN transmit status register (CAN_TSR)

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

Рис. 3. CAN transmit status register.

Address offset: 0x08
Reset value: 0x1C00 0000

Биты Название Описание
31 LOW2 — Lowest priority flag for mailbox 2 Наименьший приоритет для почтового ящика №2.
Этот бит устанавливается аппаратно, когда более чем один почтовый ящик находится в обработке, а сообщение в почтовом ящике №2 имеет наименьший приоритет.
30 LOW1 — Lowest priority flag for mailbox 1 Наименьший приоритет для почтового ящика №1.
Этот бит устанавливается аппаратно, когда более чем один почтовый ящик находится в обработке, а сообщение в почтовом ящике №1 имеет наименьший приоритет.
29 LOW0 — Lowest priority flag for mailbox 0 Наименьший приоритет для почтового ящика №0.
Этот бит устанавливается аппаратно, когда более чем один почтовый ящик находится в обработке, а сообщение в почтовом ящике №0 имеет наименьший приоритет.

Примечание: Биты LOW[2:0] устанавливаются в ноль,  когда только один почтовый ящик находится на обработке.

28 TME2 — Transmit mailbox 2 empty Почтовый ящик №2 пуст.
Этот бит устанавливается аппаратно, когда нет запроса на обработку почтового ящика №2.
27 TME1 — Transmit mailbox 1 empty Почтовый ящик №1 пуст.
Этот бит устанавливается аппаратно, когда нет запроса на обработку почтового ящика №1.
26 TME0 — Transmit mailbox 0 empty Почтовый ящик №0 пуст.
Этот бит устанавливается аппаратно, когда нет запроса на обработку почтового ящика №0.
25:24 CODE[1:0] — Mailbox code Код почтового ящика.
В случае, когда по меньшей мере освобождается один почтовый ящик, значение CODE содержит номер следующего почтового ящика в очереди с наименьшим приоритетом.
23 ABRQ2 — Abort request for mailbox 2 Прервать запрос на обработку почтового ящика №2. 
Устанавливается программно с целью прервать передачу из почтового ящика №2. Сбрасывается автоматически после того, как bxCan очищает почтовый ящик. Установка этого бита не имеет никакого значения, если почтовый ящик не задерживается для передачи.
22:20 Зарезервировано   
19 TERR2 — Transmission error of mailbox 2 Ошибка передачи для почтового ящика №2.
Устанавливается, когда произошла ошибка при передаче сообщения из этого почтового ящика.
18 ALST2 — Arbitration lost for mailbox 2 Потеря арбитража для почтового ящика №2.
Бит устанавливается, если при передачи сообщения устройство проиграла арбитраж.
17 TXOK2 — Transmission OK of mailbox 2 Завершение передачи для почтового ящика №2.
bxCan обновляет этот бит после каждой попытки передачи из почтового ящика и устанавливает следующие значения:
0 — передача не удалась;
1 — передача была успешной.
Этот бит устанавливается аппаратно, когда успешно завершен запрос передачи для почтового ящика №2.
16 RQCP2 — Request completed mailbox2 Завершен запрос на передачу для почтового ящика №2.
Устанавливается аппаратно, когда был выполнен последний запрос (передан или прерван).
Очищается программно путем установки бита в «1» или аппаратно по факту завершения передачи (установка бита TXRQ2 в регистре CAN_TI2R).
Очистка этого бита сбрасывает все виды состояния для почтового ящика №2 (TXOK2, ALST2 и TERR2).
15 ABRQ1 — Abort request for mailbox 1 Прервать запрос на обработку почтового ящика №1.
Устанавливается программно с целью прервать передачу из почтового ящика №1. Сбрасывается автоматически после того, как bxCan очищает почтовый ящик.
Установка этого бита не имеет никакого значения, если почтовый ящик не задерживается для передачи.
14:12 Зарезервировано   
11 TERR1 — Transmission error of mailbox1 Ошибка передачи для почтового ящика №2.
Устанавливается, когда произошла ошибка при передаче сообщения из этого почтового ящика.
10 ALST1 — Arbitration lost for mailbox1 Потеря арбитража для почтового ящика №1.
Бит устанавливается, если при передачи сообщения устройство проиграла арбитраж.
9 TXOK1 — Transmission OK of mailbox1 Завершение передачи для почтового ящика №1.
bxCan обновляет этот бит после каждой попытки передачи из почтового ящика и устанавливает следующие значения:
0 — передача не удалась;
1 — передача была успешной.
Этот бит устанавливается аппаратно, когда успешно завершен запрос передачи для почтового ящика №1.
8 RQCP1 — Request completed mailbox1 Завершен запрос на передачу для почтового ящика №1.
Устанавливается аппаратно, когда был выполнен последний запрос (передан или прерван).
Очищается программно путем установки бита в «1» или аппаратно по факту завершения передачи (установка бита TXRQ1 в регистре CAN_TI1R).
Очистка этого бита сбрасывает все виды состояния для почтового ящика №1 (TXOK1, ALST1 и TERR1).
7 ABRQ0 — Abort request for mailbox0 Прервать запрос на обработку почтового ящика №0.
Устанавливается программно с целью прервать передачу из почтового ящика №0. Сбрасывается программно после того, как bxCan очищает почтовый ящик.
Установка этого бита не имеет никакого значения, если почтовый ящик не задерживается для передачи.
6:4 Зарезервировано   
3 TERR0 — Transmission error of mailbox0 Ошибка передачи для почтового ящика №0.
Устанавливается, когда произошла ошибка при передаче сообщения из этого почтового ящика.
2 ALST0 — Arbitration lost for mailbox0 Потеря арбитража для почтового ящика №0.
Бит устанавливается, если при передачи сообщения устройство проиграла арбитраж.
1 TXOK0 — Transmission OK of mailbox0 Завершение передачи для почтового ящика №0.
bxCan обновляет этот бит после каждой попытки передачи из почтового ящика и устанавливает следующие значения:
0 — передача не удалась;
1 — передача была успешной.
Этот бит устанавливается аппаратно, когда успешно завершен запрос передачи для почтового ящика №0.
0 RQCP0 — Request completed mailbox0 Завершен запрос на передачу для почтового ящика №0.
Устанавливается аппаратно, когда был выполнен последний запрос (передан или прерван).
Очищается программно путем установки бита в «1» или аппаратно по факту завершения передачи (установка бита TXRQ0 в регистре CAN_TI0R).
Очистка этого бита сбрасывает все виды состояния для почтового ящика №0 (TXOK0, ALST0 и TERR0).

Как правило необходимости напрямую обращаться к этому регистру у нас не будет — можно полностью доверится bxCan. Я вижу потребность в его чтении только в очень сложных проектах, где часть функционала ложится не только на аппаратную часть, но и на программную. Также может потребоваться в случаях, когда необходимо использовать парсер CAN-шины — необходимо более детальное изучение ошибок передачи данных, логирование всего и вся.

Для обработки прерываний передачи сообщений необходимо разрешить прерывание при отправке почтового сообщения (CAN_IT_TME) и, соответственно, добавить это обработчик этого прерывания в тело программы (USB_HP_CAN1_TX_IRQHandler()).

CAN receive FIFO 0 register (CAN_RF0R)

Первый из двух регистров, отвечающих за буфер входящих сообщений FIFO 0.

Из этого регистра мы можем узнать количество почтовых сообщений, а также текущее состояние буфера FIFO 0.

 

Рис. 4. CAN receive FIFO 0 register.

Address offset: 0x0C
Reset value: 0x0000 0000

Биты Название Описание
31:6 Зарезервировано  
5 RFOM0 — Release FIFO 0 output mailbox Буфер FIFO0 освобожден.
Устанавливается программно, чтобы освободить (очистить) почтовые ящики буфера FIFO0. Выходной почтовый ящик буфера может быть освобожден только в том случае, если на обработке FIFO0 имеется хотя бы одно сообщение. Устанавливать этот бит, когда FIFO0 пуст — не имеет никакого смысла.
Очищается автоматически с помощью аппаратных средств, когда обработаны все сообщения, находящиеся в почтовых ящиках буфера FIFO0.
4 FOVR0 — FIFO 0 overrun Буфер FIFO0 переполнен.
Этот бит устанавливается аппаратными средствами, когда получено новое сообщение, но буфер FIFO0 уже заполнен.
Этот бит необходимо сбрасывать программно.
3 FULL0 — FIFO 0 full Буфер FIFO0 заполнен.
Устанавливается аппаратно, когда заполнены все три почтовых ящика буфера FIFO0
Этот бит необходимо сбрасывать программно.
2 Зарезервировано  
1:0 FMP0[1:0] — FIFO 0 message pending Количество сообщений в буфере FIFO0.
Эти биты указывают, сколько сообщений находится на обработке в буфере FIFO0. FMP увеличивается каждый раз, когда поступает новое сообщение и уменьшается, после обработки каждого сообщения буфера.

Обработка прерываний для буфера FIFO 0 происходит в функции USB_LP_CAN1_RX0_IRQHandler(). В ней необходимо обработать получение почтовых сообщений, а также проверить состояние ошибок (заполнение или переполнение буфера FIFO 0). Естественно, необходимо включить эти прерывания при настройке bxCan.

Необходимо помнить, что биты FOVR0 и FULL0 сбрасываются вручную. 

CAN receive FIFO 1 register (CAN_RF1R)

А это второй регистр, предназначенный для чтения состояния буфера входящих сообщений, но уже для FIFO 1.

Из него мы также можем почерпнуть информацию о  том, сколько сообщений у нас хранится и текущий статус самого буфера FIFO 1.

Рис. 5. CAN receive FIFO 1 register.

Address offset: 0x10
Reset value: 0x0000 0000

Биты Название Описание
31:6 Зарезервировано  
5 RFOM1 — Release FIFO 1 output mailbox Буфер FIFO1 освобожден.
Устанавливается программно, чтобы освободить (очистить) почтовые ящики буфера FIFO1. Выходной почтовый ящик буфера может быть освобожден только в том случае, если на обработке FIFO1 имеется хотя бы одно сообщение. Устанавливать этот бит, когда FIFO1 пуст — не имеет никакого смысла.
Очищается автоматически с помощью аппаратных средств, когда обработаны все сообщения, находящиеся в почтовых ящиках буфера FIFO1.
4 FOVR1 — FIFO 1 overrun Буфер FIFO1 переполнен.
Этот бит устанавливается аппаратными средствами, когда получено новое сообщение, но буфер FIFO1 уже заполнен.
Этот бит необходимо сбрасывать программно.
3 FULL1 — FIFO 1 full Буфер FIFO1 заполнен.
Устанавливается аппаратно, когда заполнены все три почтовых ящика буфера FIFO1
Этот бит необходимо сбрасывать программно.
2 Зарезервировано  
1:0 FMP1[1:0] — FIFO 1 message pending Количество сообщений в буфере FIFO1.
Эти биты указывают, сколько сообщений находится на обработке в буфере FIFO1.
FMP увеличивается каждый раз, когда поступает новое сообщение и уменьшается, после обработки каждого сообщения буфера.

Для обработки прерываний для буфера FIFO 1 необходимо включить обработку этих прерываний при настройке bxCan и вставить в модуль функцию CAN1_RX1_IRQHandler(). Также как и с буфером FIFO 0, мы можем в обработчике прерываний выполнить обработку получения почтового сообщения в буфер FIFO 1, а также проверить состояние ошибок буфера и сбросить их после обработки.

Также напомню о необходимости сбрасывать биты FOVR1 и FULL1 вручную.

CAN interrupt enable register (CAN_IER)

Мы добрались до регистра, который непосредственно отвечает за включение прерываний bxCAN. Установив необходимые нам биты, мы сможем выполнить обработку прерываний. Напомню, что включение прерываний само по себе недостаточно, необходимо еще и включить сами прерывания и добавить их обработчики в тело программы, иначе наша программа при возникновении прерывания перейдет в прерывание по умолчанию и просто «зависнет». Но об этом поговорим чуть ниже, где я приведу несколько примеров.

Итак, нам необходимо включить прерывания. Сделать это мы можем установив соответствующие биты в регистре CAN interrupt enable register (CAN_IER).

Рис. 6. CAN interrupt enable register.

Address offset: 0x14
Reset value: 0x0000 0000

Биты Название Описание
31:18 Зарезервировано  
17 SLKIE — Sleep interrupt enable Прерывание при переходе в спящий режим.
Вызывается, когда bxCan переходит в «спящий» режим при установленном бите SLAKI регистра CAN_MSR.
0: Прерывание не генерируется
1: Прерывание генерируется
16 WKUIE — Wakeup interrupt enable Прерывание при выходе из спящего режима.
Вызывается, когда bxCan выходит из спящего режима при установленном бите WKUI регистра CAN_MSR.
0: Прерывание не генерируется
1: Прерывание генерируется
15 ERRIE — Error interrupt enable Прерывание при возникновении ошибки.
0: Прерывание не генерируется
1: Генерируется прерывание когда есть описание ошибки в регистре CAN_ESR.
14:12 Зарезервировано  
11 LECIE — Last error code interrupt enable Прерывание при возникновении ошибки приема-передачи.
Вызывается, когда установлены биты LEC[2:0] (регистр CAN_ESR) аппаратной частью bxCan.
0: Бит ERRI не будет установлен
1: Бит ERRI будет установлен при обнаружении ошибки на шине.
10 BOFIE — Bus-off interrupt enable Прерывание при переходе в режим Bus-Off.
Вызывается при переходе bxCan в режим Bus-Off при установленном бите BOFF регистра CAN_ESR.
0: Бит ERRI не будет установлен
1: Бит ERRI будет установлен
9 EPVIE — Error passive interrupt enable Прерывание при достижении пассивного уровня ошибок.
Вызывается когда счетчики ошибок приема или передачи превышают значение 127 при установленном бите EPVF регистра CAN_ESR.
0: Бит ERRI не будет установлен
1: Бит ERRI будет установлен
8 EWGIE — Error warning interrupt enable Прерывание при достижении предупреждающего уровня ошибок.
Вызывается когда счетчики ошибок приема или передачи превышают либо равны значению 96 при установленном бите EWGF.
0: Бит ERRI не будет установлен
1: Бит ERRI будет установлен
7 Зарезервировано  
6 FOVIE1 — FIFO overrun interrupt enable Прерывание при переполнении буфера FIFO1.
Вызывается, когда буфер FIFO1 заполнен и получено еще один пакет данных при установленном бите FOVR регистра CAN_RF1R.
0: Прерывание не генерируется
1: Генерируется прерывание
5 FFIE1 — FIFO full interrupt enable Прерывание при заполнении буфера FIFO1.
Вызывается когда в буфере FIFO1 заполнены все три почтовых ящика при установленном бите FULL регистра CAN_RF1R.
0: Прерывание не генерируется
1: Генерируется прерывание
4 FMPIE1 — FIFO message pending interrupt enable Прерывание при получении пакета из шины.
Вызывается когда в буфер FIFO1 получено очередное сообщение (при значении бита FMP[1:0] регистра CAN_RF1R не равном 00b).
0: Прерывание не генерируется
1: Генерируется прерывание
3 FOVIE0 — FIFO overrun interrupt enable Прерывание при переполнении буфера FIFO0.
Вызывается, когда буфер FIFO0 заполнен и получено еще один пакет данных при установленном бите FOVR регистра CAN_RF0R.
0: Прерывание не генерируется
1: Генерируется прерывание
2 FFIE0 — FIFO full interrupt enable Прерывание при заполнении буфера FIFO0.
Вызывается когда в буфере FIFO0 заполнены все три почтовых ящика при установленном бите FULL регистра CAN_RF0R.
0: Прерывание не генерируется
1: Генерируется прерывание
1 FMPIE0 — FIFO message pending interrupt enable Прерывание при получении пакета из шины.
Вызывается когда в буфер FIFO0 получено очередное сообщение (при значении бита FMP[1:0] регистра CAN_RF0R не равном 00b).
0: Прерывание не генерируется
1: Генерируется прерывание
0 TMEIE — Transmit mailbox empty interrupt enable Прерывание при освобождении исходящего почтового ящика.
Вызывается при окончании передачи сообщения при установленном бите RQCPx регистра CAN_TSR.
0: Прерывание не генерируется
1: Генерируется прерывание

Если Вы новичок и только начинаете изучать протокол CAN  и его использование на микроконтроллерах семейства STM32, то можно ограничиться одним прерыванием FMPIE0 (FIFO 0 message pending interrupt) и TMEIE (Transmit mailbox empty interrupt), которые отвечает за обработку получения входящего пакета в буфер FIFO 0, а также за обработку окончания отправки пакета в шину соответственно. Для первоначального изучения и тестирования этого вполне хватит, а дальше уже требуется более глубокое понимание физики процессов и специфики работы CAN шины.

CAN error status register (CAN_ESR)

Регистр отвечает за состояние ошибок при работе с bxCan.

Управление ошибками, как описано в протоколе CAN, обрабатывается полностью аппаратными средствами с помощью счетчиков ошибок передачи (TEC — Transmit error counter) и счетчиков ошибок приема сообщений (REC — Receive error counter), которые увеличивают или уменьшают свое значение в соответствии с состоянием ошибки.

Оба счетчика могут быть прочитаны с помощью программного обеспечения, чтобы определить стабильность сети.

Кроме того, аппаратное обеспечение может предоставлять более подробную информацию о текущем состоянии ошибок (LEC — Last error code).

Рис. 7. CAN error status register.

Address offset: 0x18
Reset value: 0x0000 0000

Биты Название Описание
31:24 REC[7:0] — Receive error counter Счетчик ошибок приема пакетов.
Исполняющая часть механизма контроля состояния протокола CAN. В случае возникновения ошибки во время приема пакета, этот счетчик увеличивается на 1 или на 8 в зависимости от состояния ошибки (по определению стандарта CAN).
После каждого успешного приема счетчик уменьшается на единицу или сбрасывается до 120, если его значение было выше, чем 128.
Если значение счетчика превышает 127, то контроллер bxCan переходит в пассивное состояние ошибки (устанавливается бит EPVF).
23:16 TEC[7:0] — Transmit error counter Счетчик ошибок передачи пакетов.
Аналогично REC, только для ошибок передачи.
15:17 Зарезервировано  
6:4 LEC[2:0] — Last error code Код последней ошибки.
Это поле устанавливается аппаратно и содержит значение, которое указывает на вид последней ошибки, обнаруженной на CAN шине.
Если сообщение было передано или получено без ошибок, то значение этих битов будет сброшено в ноль.
Также программно можно установить эти биты в значение 0b111, что указывает, что ошибка установлена с помощью программного обеспечения.
Коды ошибок:
000 — Нет ошибок
001 — Stuff error
010 — Form error
011 — Acknowledgment Error
100 — Bit recessive Error
101 — Bit dominant Error
110 — CRC Error
111 — Set by software

Описание ошибок приведено ниже в таблице №4.

3 Зарезервировано  
2 BOFF — Bus-off flag Bus-off флаг.
Этот бит устанавливается, когда bxCan переходит в режим Bus-off. Режим Bus-off вводится, когда счетчик ошибок передачи (TEC) становится больше чем 255.
1 EPVF — Error passive flag Флаг пассивной ошибки.
Этот бит устанавливается аппаратно, когда достигнут пассивный предел счетчиков ошибок (Счетчик приема и/или передачи больше 127).
0 EWGF — Error warning flag Флаг предупреждения об ошибках.
Бит устанавливается аппаратно, когда достигнут предел предупреждения (Счетчик ошибок приема и/или передачи ≥ 96).

Согласно описанию протокола CAN принято увеличивать счетчик ошибок REC (Receive error counter) на одну единицу при каждой обнаруженной ошибке приема на шине, а счетчик ошибок TEC (Transmit error counter) увеличивать на 8 при каждой ошибке передачи пакетов. Это связано стем, что существует предположение о том, что с наибольшей вероятностью источником ошибок на шине является передающий узел. 

Уменьшение счетчика ошибок происходит автоматически на единицу при каждом успешном приеме или передаче сообщений по шине для счетчиков REC и TEC соответственно.

Восстановление BUS-OFF

Состояние шины Bus-Off устанавливается, когда счетчик ошибок передачи превышает 255, при этом устанавливается бит BOFF регистра CAN_ESR. В этом режиме bxCan фактически перестает принимать и передавать пакеты по шине.

При настройке bxCAN можно установить бит ABOM, который отвечает за то, что если шина перейдет в режим Bus-off, то bxCan автоматически начнет проверять сигнал CAN_RX для восстановления шины. Если бит ABOM не установлен, то разработчику необходимо контролировать этот процесс самостоятельно и в случае возникновения ошибки и перехода в режим Bus-off необходимо заново проинициализировать bxCan.

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

Долгое время не мог понять, что это за 11 рецессивных бит 128 раз подряд и где их необходимо взять и куда подать. Путем гугления и раскурки мануалов понял, что это указывается время, через которое контроллер CAN шины автоматически выйдет из режима Bus-Off и оно равно времени, которое потребуется для передачи 11 рецессивных бит 128 раз подряд.

Другими словами, контроллер автоматически выйдет из режима Bus-Off, когда на CAN шине будет «тишина» в течении времени, равному времени передачи 11 бит * 128 раз. Естественно, если в настройках контроллера мы ему указали, что он может автоматически выходить из этого режима (установлен бит ABOM регистра CAN_MCR).

Практика

Вроде все моменты, которые касаются обработки прерываний bxCan мы рассмотрели. Текста очень много, но как это применить на практике?

Давайте разбираться.

Для начала нам необходимо определится с тем, какие прерывания bxCan мы будем использовать. Конечно можно ограничиться прерыванием на получение сообщения в буфер FIFO, но мы же не ищем легких путей, поэтому проинициализируем сразу все.

За включение/отключение прерываний bxCan отвечает функция CAN_ITConfig, эти действия выполняются в модуле инициализации can шины совместно с настройкой прерываний NVIC:

Листинг №1. Включение прерываний bxCan
	// CAN Transmit mailbox empty Interrupt enable
	// Обрабатывается в прерывании USB_HP_CAN1_TX_IRQHandler
	CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);         // Прерывание при освобождении исходящего почтового ящика
	// CAN Receive Interrupt enable
	// Обрабатывается в прерывании USB_LP_CAN1_RX0_IRQHandler
	CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);        // Прерывание получения пакета в буфер FIFO 0
	CAN_ITConfig(CAN1, CAN_IT_FF0, ENABLE);         // Прерывание при заполнении буфера FIFO 0
	CAN_ITConfig(CAN1, CAN_IT_FOV0, ENABLE);        // Прерывание при переполнении буфера FIFO 0
 
	// Обрабатывается в прерывании CAN1_RX1_IRQHandler
	CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE);        // Прерывание получения пакета в буфер FIFO 1
	CAN_ITConfig(CAN1, CAN_IT_FF1, ENABLE);         // Прерывание при заполнении буфера FIFO 1
	CAN_ITConfig(CAN1, CAN_IT_FOV1, ENABLE);        // Прерывание при переполнении буфера FIFO 1
 
	// CAN Operating Mode Interrupt enable
	// Обрабатывается в прерывании CAN1_SCE_IRQHandler
	CAN_ITConfig(CAN1, CAN_IT_WKU, ENABLE);         // Прерывание при "пробуждении" - выход из "спящего" режима
	CAN_ITConfig(CAN1, CAN_IT_SLK, ENABLE);         // Прерывание при переходе в "спящий" режим
 
	// CAN Error Interrupts
	// Обрабатывается в прерывании CAN1_SCE_IRQHandler
	CAN_ITConfig(CAN1, CAN_IT_EWG, ENABLE);         // Error warning Interrupt (error counter >= 96)
	CAN_ITConfig(CAN1, CAN_IT_EPV, ENABLE);         // Error passive Interrupt (error counter > 127)
	CAN_ITConfig(CAN1, CAN_IT_BOF, ENABLE);         // Bus-off Interrupt (error counter > 255)
	CAN_ITConfig(CAN1, CAN_IT_LEC, ENABLE);         // Last error code - при возникновении ошибок приема-передачи
	CAN_ITConfig(CAN1, CAN_IT_ERR, ENABLE);         // Прерывание при возникновении ошибок bxCan


	// NVIC Configuration
	NVIC_InitTypeDef NVIC_InitStructure;

	// Enable CAN1 TX0 interrupt IRQ channel
	NVIC_InitStructure.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	// Enable CAN1 RX0 interrupt IRQ channel
	NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	// Enable CAN1 RX1 interrupt IRQ channel
	NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

	// Enable CAN1 SCE (Status Change Error) interrupt IRQ channel
	NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);

После того, как с помощью функции CAN_ITConfig() мы проинициализировали необходимые нам прерывания, необходимо включить обработчики этих прерываний. Делается это через NVIC. Если мы забудем хотя бы одно из них включить, то микроконтроллер при возникновении прерывания, которое мы забыли обработать, выкинет нас в стандартный обработчик прерываний и просто зависнет. Поможет только перезагрузка процессора, так как он будет сидеть в «вечном» цикле и ни на что больше реагировать не будет.

А теперь, чтобы этого не произошло, нам необходимо вставить в наш программный код функции обработки прерываний. Всего их четыре: прерывание при освобождении исходящего почтового ящика, два прерывания для буферов FIFO 1 и 2, а также прерывание по обработке ошибок и входа/выхода в «режим сна».

Обработка прерываний при освобождении исходящего почтового ящика

За обработку прерывания при освобождении исходящего почтового ящика отвечает функция USB_HP_CAN1_TX_IRQHandler(). Нам необходимо проверить флаг прерывания и, если он установлен, сбросить его и выполнить код обработки прерывания:

Листинг №2. Обработка прерываний bxCan для исходящего почтового ящика
void USB_HP_CAN1_TX_IRQHandler(void)
{
	// CAN Transmit mailbox empty Interrupt enable
	// Обработаем прерывания при освобождении исходящего почтового ящика
	if (CAN_GetITStatus(CAN1, CAN_IT_TME)==SET) {       // Прерывание при освобождении исходящего почтового ящика
		CAN_ClearITPendingBit(CAN1, CAN_IT_TME);
   
		// Вставляем свой код по обработке прерывания
	}
}

Функция CAN_GetITStatus() возвращает текущее состояние флага прерывания, значение может быть равным SET или RESET («Установлен» или «сброшен» соответственно). Значение SET говорит нам о том, что бит установлен и нам необходимо обработать это прерывание и не забыть сбросить его флаг.

Следует помнить о том, что необходимо всегда производить сброс флага прерывания, иначе оно будет вызываться постоянно. Исключение составляют только флаги прерываний ошибок, они почти все сбрасываются аппаратно, подробнее можно посмотреть в описании функции CAN_ClearITPendingBit().

Проверять освобождение исходящего почтового ящика имеет смысл, если Вы пересылаете большой объем данных по Can-шине: при обработке отправки сообщения выставляется флаг отправки сообщения, а в прерывании проверяется была выполнена отправка данных или нет. Если отправка была завершена без ошибок, то устанавливаем в флаг значение без ошибок и отправляем следующий пакет данных, иначе устанавливаем в флаг код ошибки и обрабатываем ее в модуле программы.

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

Проверить статус отправки сообщения можно не только с помощью прерываний, но и в момент отправки сообщения (это наверное самый оптимальный вариант):

Листинг №3. Отправка сообщения с проверкой статуса отправки
	uint32_t i = 0;
	uint8_t TransmitMailbox = 0;
	
	...
	
	TransmitMailbox = CAN_Transmit(CAN1, &TxMessage);
	i = 0;
	while ((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFF)) 	{
		i++;
	}

При передаче сообщения через функцию CAN_Transmit, она нам возвращает номер исходящего почтового ящика, в который помещено сообщение. Затем мы в цикле проверяем, отправил ли bxCan наше сообщение или нет. Если отправка прошла успешно, то статус отправки сообщения из почтового ящика будет равен CANTXOK.

По окончанию цикла while() проверяем значение переменной «i». Если оно у нас равно 0xFF, значит отправка не удалась и тут мы уже думаем что сделать: то ли сбросить отправку сообщения, то ли обработать ошибку.

Вообщем все на усмотрение разработчика.

Обработка прерываний входящего буфера сообщений FIFO 0

За прерывания для входящего буфера сообщений FIFO 0 отвечают флаги CAN_IT_FMP0, CAN_IT_FF0 и CAN_IT_FOV0.

Наименование Описание
CAN_IT_FMP0 Прерывание срабатывает при получении очередного сообщения в буфер FIFO 0.
CAN_IT_FF0  Прерывание возникает при заполнении всех трех почтовых ящиков буфера FIFO 0.
CAN_IT_FOV0 А это прерывание возникает если у нас все три почтовых ящика буфера FIFO 0 заполнены и мы получаем четвертое сообщение по шине. У нас происходит переполнение буфера.
Таб. 1. Прерывания  буфера FIFO 0

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

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

Действия по обработке данных прерываний возлагаются на разработчика и описываются в функции USB_LP_CAN1_RX0_IRQHandler().

Листинг №4. Обработка прерываний bxCan для буфера FIFO 0
void USB_LP_CAN1_RX0_IRQHandler(void)
{
	CanRxMsg RxMessage;
	
	// CAN Receive Interrupt enable FIFO 0
	// Обработаем прерывания приемного буфера FIFO 0
	if (CAN_GetITStatus(CAN1, CAN_IT_FMP0) == SET) {                   // Прерывание получения пакета в буфер FIFO 0
		// Флаг сбрасывается автоматически после прочтения последнего сообщения
   
		// Обнулим данные пакета
		RxMessage.DLC =     0x00;
		RxMessage.ExtId =   0x00;
		RxMessage.FMI =     0x00;
		RxMessage.IDE =     0x00;
		RxMessage.RTR =     0x00;
		RxMessage.StdId =   0x00;
		RxMessage.Data [0] = 0x00;
		RxMessage.Data [1] = 0x00;
		RxMessage.Data [2] = 0x00;
		RxMessage.Data [3] = 0x00;
		RxMessage.Data [4] = 0x00;
		RxMessage.Data [5] = 0x00;
		RxMessage.Data [6] = 0x00;
		RxMessage.Data [7] = 0x00;
		
		CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);                   // Получим сообщение
   
		// Вставляем любой свой код обработки входящего пакета
   
		}
   
	if (CAN_GetITStatus(CAN1, CAN_IT_FF0)==SET) {                       // Прерывание при заполнении буфера FIFO 0
		CAN_ClearITPendingBit(CAN1, CAN_IT_FF0);
		
		// Вставляем свой код по обработке прерывания
 		
		// Не забываем после обработки сбросить флаг ошибки
		CAN_ClearFlag(CAN1, CAN_FLAG_FF0);
	}
	
	if (CAN_GetITStatus(CAN1, CAN_IT_FOV0)==SET) {                      // Прерывание при переполнении буфера FIFO 0
		CAN_ClearITPendingBit(CAN1, CAN_IT_FOV0);
		
		// Вставляем свой код по обработке прерывания
   
		// Не забываем после обработки сбросить флаг ошибки
		CAN_ClearFlag(CAN1, CAN_FLAG_FOV0);
	}
}

Следует обратить внимание на то, что функция USB_LP_CAN1_RX0_IRQHandler() предназначена как для обработки прерываний bxCan так и для обработки прерываний USB. Если Вы будете использовать USB в своем проекте, то нужно внимательно подойти к этому моменту, чтобы правильно обрабатывать сообщения для каждого устройства.

Обратите внимание, что в обработчике прерываний мы сбрасываем не только флаг прерывания, но также сбрасываем флаг ошибки bxCan. Это немного (точнее очень много) разные вещи: флаг прерывания отвечает за то, что мы попадем в обработчик прерывания при его установке и если его не сбросить, то мы можем сидеть вечно в этом обработчике. А флаг ошибки сигнализирует нам о том, что есть ошибка и его нужно снять после того, как мы обработали эту ошибку. Соответственно, если по какой-либо причине мы ее не обработали — этот флаг снимать не следует.

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

Обработка прерываний входящего буфера сообщений FIFO 1

За прерывания для входящего буфера сообщений FIFO 1 отвечают флаги CAN_IT_FMP1, CAN_IT_FF1 и CAN_IT_FOV1. Описание и действие аналогично с обработкой прерывания для буфера FIFO 0.

Наименование Описание
CAN_IT_FMP1 Прерывание срабатывает при получении очередного сообщения в буфер FIFO 1.
CAN_IT_FF1 Прерывание возникает при заполнении всех трех почтовых ящиков буфера FIFO 1.
CAN_IT_FOV1 А это прерывание возникает если у нас все три почтовых ящика буфера FIFO 1 заполнены и мы получаем четвертое сообщение по шине. У нас происходит переполнение буфера.
Таб. 2. Прерывания  буфера FIFO 1

В отличии от буфера FIFO 0, обработка этих прерываний происходит в функции CAN1_RX1_IRQHandler().

Листинг №5. Обработка прерываний bxCan для буфера FIFO 1
void CAN1_RX1_IRQHandler(void)
{
	CanRxMsg RxMessage;
   
	// CAN Receive Interrupt enable FIFO 1
	// Обработаем прерывания приеного буфера FIFO 1
	if (CAN_GetITStatus(CAN1, CAN_IT_FMP1) == SET) {              // Прерывание получения пакета в буфер FIFO 1
		// Флаг сбрасывается автоматически после прочтения последнего сообщения
   
		// Обнулим данные пакета
		RxMessage.DLC =     0x00;
		RxMessage.ExtId =   0x00;
		RxMessage.FMI =     0x00;
		RxMessage.IDE =     0x00;
		RxMessage.RTR =     0x00;
		RxMessage.StdId =   0x00;
		RxMessage.Data [0] = 0x00;
		RxMessage.Data [1] = 0x00;
		RxMessage.Data [2] = 0x00;
		RxMessage.Data [3] = 0x00;
		RxMessage.Data [4] = 0x00;
		RxMessage.Data [5] = 0x00;
		RxMessage.Data [6] = 0x00;
		RxMessage.Data [7] = 0x00;
   
		CAN_Receive(CAN1, CAN_FIFO1, &RxMessage);               // Получим сообщение
   
		// Вставляем любой свой код обработки входящего пакета
   
	}
   
	if (CAN_GetITStatus(CAN1, CAN_IT_FF1)==SET) {                   // Прерывание при заполнении буфера FIFO 1
		CAN_ClearITPendingBit(CAN1, CAN_IT_FF1);
   
		// Вставляем свой код по обработке прерывания
   
		// Не забываем после обработки сбросить флаг ошибки
		CAN_ClearFlag(CAN1, CAN_FLAG_FF1);
	}

	if (CAN_GetITStatus(CAN1, CAN_IT_FOV1)==SET) {                  // Прерывание при переполнении буфера FIFO 1
		CAN_ClearITPendingBit(CAN1, CAN_IT_FOV1);

		/ Вставляем свой код по обработке прерывания
   
		// Не забываем после обработки сбросить флаг ошибки
		CAN_ClearFlag(CAN1, CAN_FLAG_FF1);
	}
}

Обработчик для буфера FIFO 1 ничем не отличается от обработчика для буфера FIFO 0, разница есть только в наименовании функции обработчика и флагов, которые мы проверяем. Наполнение буфера FIFO 1 (как и FIFO 0) зависит исключительно от настроек фильтрации пакетов и в них же указывается какие сообщения в какой буфер будут попадать.

Подробно я о фильтрах рассказывал в статье STM32. Почтовые ящики. Фильтры пакетов CAN.

В своем проекте управления умным домом я с помощью фильтрации разделяю управляющие пакеты и пакеты с данными по разным буферам: сообщения данных попадают исключительно в буфер FIFO 0, а системные и приоритетные сообщения я помещаю в буфер FIFO 1.

Если у Вас нет задачи такой фильтрации сообщений, то можно вполне обойтись одним буфером FIFO 0  и в принципе не использовать буфер FIFO 1 (или наоборот, роли никакой не играет). Для большинства задач это будет вполне достаточно и сэкономит Вам несколько сотен байт прошивки.

Обработка прерываний по ошибкам и «спящему» режиму

Обработчик прерываний ошибок bxCan позволяет нам определить насколько стабильно работает наше устройство с протоколом CAN и вовремя принять меры для достижения максимально стабильного режима работы.

За обработку ошибок отвечают следующие флаги:

Наименование Описание
CAN_IT_ERR Error Interrupt — устанавливается при возникновении любой ошибки
CAN_IT_EWG Error warning Interrupt — предупреждение о том, что один из счетчиков ошибок достиг 96 или более ошибок
CAN_IT_EPV Error passive Interrupt — предупреждение о том, что один из счетчиков ошибок достиг более 127 ошибок
CAN_IT_BOF Bus-off Interrupt — Возникает при переходе шины в режим Bus-Off, когда любой из счетчиков ошибок превысил значение 255
CAN_IT_LEC Last error code Interrupt — активируется при возникновении ошибок приема передачи
CAN_IT_WKU Wake-up Interrupt — возникает при «пробуждении» bxCan, когда шина выходит из спящего режима.
CAN_IT_SLK Sleep acknowledge Interrupt — возникает при уходе шины в «спящий» режим.
Таб. 3. Прерывания ошибок и режима шины

Прерывание по флагам CAN_IT_WKU и CAN_IT_SLK срабатывают при входе или выходе в/из спящего режима. При этом флаг CAN_IT_ERR не устанавливается. А если же срабатывает прерывание по флагам CAN_IT_EWG, CAN_IT_EPV, CAN_IT_BOF или CAN_IT_LEC, то одновременно с ними устанавливается и флаг CAN_IT_ERR.

Флаги CAN_IT_EWG, CAN_IT_EPV и CAN_IT_BOF предназначены для контроля количества ошибок приема передачи по шине. Механизм bxxCan не только увеличивает счетчик ошибок, например когда на линии возникает помеха и счетчик ошибок увеличивается, но и уменьшает его, когда работа шины нормализуется. Флаги CAN_IT_EWG и CAN_IT_EPV являются предупреждающими о том, что идет рост ошибок и необходимо выявить причину их возникновения, а вот флаг CAN_IT_BOF нам сообщает, что счетчик ошибок достиг своего максимума и шина перешла в режим Bus-off. Выход из этого режима может произойти автоматически (при получении 128 раз 11 рецессивных бит подряд по шине) или принудительно — заново проинициализировав bxCan.

Напомню, что за автоматический выход из режима Bus-Off отвечает бит ABOM в регистре CAN_MCR. Рекомендую его устанавливать в Ваших проектах, тогда bxCan этот функционал возьмет на себя.

Флаг CAN_IT_LEC срабатывает, когда происходит ошибка приема или передачи пакета, при его обработке мы можем узнать последнюю ошибку шины или устройства.

С тем что обрабатывать — мы определились, теперь необходимо вставить в программный модуль и саму функцию обработки прерываний ошибок CAN1_SCE_IRQHandler().

В ней мы сформируем шаблон обработки исключений, возникающих при работе bxCan:

Листинг №6. Обработка прерываний засыпания/пробуждения и ошибок bxCan
void CAN1_SCE_IRQHandler(void)
{
	uint8_t errorcode = 0;

	if (CAN_GetITStatus(CAN1, CAN_IT_ERR)==SET)    {                   // Прерывание при возникновении ошибки
		CAN_ClearITPendingBit(CAN1, CAN_IT_ERR);

		// CAN Error Interrupts
		// Обработка прерываний по ошибке
		if (CAN_GetITStatus(CAN1, CAN_IT_EWG)==SET) {              // Error warning Interrupt (счетчик ошибок >= 96)
			CAN_ClearITPendingBit(CAN1, CAN_IT_EWG);

			// Вставляем свой код по обработке прерывания
		}
   
		if (CAN_GetITStatus(CAN1, CAN_IT_EPV)==SET) {              // Error passive Interrupt  (счетчик ошибок > 127)
			CAN_ClearITPendingBit(CAN1, CAN_IT_EPV);

			// Вставляем свой код по обработке прерывания
		}
   
		if (CAN_GetITStatus(CAN1, CAN_IT_BOF)==SET) {              // Bus-off. Прерывание при переполнении счетчика ошибок (>255)
			CAN_ClearITPendingBit(CAN1, CAN_IT_BOF);           // bxCan уходит в режим Bus-OFF

			// Вставляем свой код по обработке прерывания
		}
   
		if (CAN_GetITStatus(CAN1, CAN_IT_LEC)==SET) {              // Прерывание при ошибке приема передачи сообщения
			CAN_ClearITPendingBit(CAN1, CAN_IT_LEC);
			errorcode = CAN_GetLastErrorCode(CAN1);            // Получим код ошибки
   
			// Вставляем свой код по обработке прерывания

			// Не забываем после обработки сбросить флаг ошибки
			CAN_ClearFlag(CAN1, CAN_FLAG_LEC);
		}

	} else {

		// CAN Operating Mode Interrupt
		// Обработка прерываний по режимам сна/пробуждения
		if (CAN_GetITStatus(CAN1, CAN_IT_WKU)==SET) {             // Прерывание при "пробуждении" - выход из "спящего" режима
			CAN_ClearITPendingBit(CAN1, CAN_IT_WKU);

			// Вставляем свой код по обработке прерывания
   
			// Не забываем после обработки сбросить флаг ошибки
			CAN_ClearFlag(CAN1, CAN_FLAG_WKU);
		}

		if (CAN_GetITStatus(CAN1, CAN_IT_SLK)==SET) {             // Прерывание при переходе в "спящий" режим
			CAN_ClearITPendingBit(CAN1, CAN_IT_SLK);

			// Вставляем свой код по обработке прерывания
   
			// Не забываем после обработки сбросить флаг ошибки
			CAN_ClearFlag(CAN1, CAN_FLAG_SLAK);
		}
	}
}

Также как мы сбрасываем флаги прерываний, нам необходимо сбрасывать и флаги ошибок после их обработки. Но если обратить внимание на описание регистров, то мы видим, что часть флагов ошибок сбрасываются автоматически аппаратными средствами bxCan, а часть мы должны очищать вручную. Вот и сейчас при обработке ошибок мы можем сбросить только флаги CAN_IT_LEC, CAN_IT_WKU и CAN_IT_SLK, а остальные флаги ошибок в данном обработчике прерываний сбрасываются автоматически.

Не стоит забывать и о том, что перед сбросом флага ошибки мы должны ее (ошибку) обработать и уже потом менять флаг.

Еще стоит обратить внимание на обработку прерывания CAN_IT_LEC (Last Error Code), которая появляется при возникновении ошибок ввода-вывода.

В обработчике  с помощью функции CAN_GetLastErrorCode() мы заполняем переменную errorcode данными о последней ошибке. Она может принимать следующие значения:

Вид Определение Описание
0x00 CAN_ErrorCode_NoErr Нет ошибок
0x10 CAN_ErrorCode_StuffErr Когда узел передает последовательно в шину 5 бит с одинаковым значением, то он добавляет шестой бит с противоположным значением. Принимающие узлы этот дополнительный бит удаляют. Если узел обнаруживает на шине больше 5 последовательных бит с одинаковым значением, то он генерирует ошибку Stuff Error.
0x20 CAN_ErrorCode_FormErr Некоторые части CAN-сообщения имеют одинаковое значение во всех типах сообщений. Т.е. протокол CAN точно определяет какие уровни напряжения и когда должны появляться на шине. Если формат сообщений нарушается, то узлы генерируют ошибку Form Error.
0x30 CAN_ErrorCode_ACKErr Каждый узел получив правильное сообщение по сети посылает в сеть доминантный (0) бит. Если же этого не происходит, то передающий узел регистрирует ошибку Acknowledgement Error.
0x40 CAN_ErrorCode_BitRecessiveErr Ошибка установки рецессивного бита.
Каждый узел во время передачи битов в сеть сравнивает значение передаваемого им бита со значением бита которое появляется на шине. Если эти значения не совпадают, то узел генерирует ошибку Bit Error. Естественно, что во время арбитража на шине (передача поля арбитража в шину) этот механизм проверки ошибок отключается.
0x50 CAN_ErrorCode_BitDominantErr Ошибка установки доминантного бита.
Каждый узел во время передачи битов в сеть сравнивает значение передаваемого им бита со значением бита которое появляется на шине. Если эти значения не совпадают, то узел генерирует ошибку Bit Error. Естественно, что во время арбитража на шине (передача поля арбитража в шину) этот механизм проверки ошибок отключается.
0x60 CAN_ErrorCode_CRCErr Каждое сообщение CAN содержит CRC сумму, и каждый принимающий узел подсчитывает значение CRC для каждого полученного сообщения. Если подсчитанное значение CRC суммы, не совпадает со значением CRC в теле сообщения, принимающий узел генерирует ошибку CRC Error.
0x70 CAN_ErrorCode_SoftwareSetErr Установлено программно. Можно заполнить единицами данные битов LEC[2:0] регистра CAN_ESR. 
 Таб. 4. Виды ошибок, возвращаемые при вызове функции CAN_GetLastErrorCode()

Таким образом, обрабатывая флаг CAN_IT_LEC и изучая ошибки, которые происходят при работе с CAN, мы можем заблаговременно выявить причину и предпринять некоторые действия для того, что бы предотвратить рост ошибок и сваливание CAN контроллера в режим Bus-Off.

Заключение

В этой статье я постарался подробно описать механизмы обработки прерываний bxCan, а также механизмы связанные с обработкой ошибок и методы по их сокращению. Напомню, что все тестирование кода производилось на базе микроконтроллера STM32F103C6.

Вполне вероятно, что я что-то упустил, где то наоборот ошибся и был не точен. Поэтому если есть какие-либо замечания и/или предложения к статье — добро пожаловать в комменты и я исправлюсь.

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

З.Ы. Простите за много букафф )))

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

Для настройки периферии будем использовать STM32CubeMx, в качестве среды разработки я, как обычно, беру IAR. Осталось упомянуть про выбранный контроллер – им сегодня будет STM32F103VE. Но, как вы помните, при работе с STM32 нет никакой проблемы в том, чтобы перейти на другой микроконтроллер или другую IDE 👍

Итак, первый шаг заключается в настройке в CubeMx всей имеющейся периферии. Не буду подробно останавливаться на том, что не касается непосредственно CAN, все можно найти в нашем курсе по этой вот ссылке.

В итоге у нас оказываются задействованы следующие пины контроллера:

STM32CubeMx CAN pinout.

Здесь мы уже активировали модуль CAN:

STM32 CAN module.

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

Baudrate settings.

Давайте разберемся, что это за значения и за что они отвечают. Время передачи одного бита в CAN складывается из:

CAN timings.

Все длительности оцениваются через понятие кванта времени, для задания которого мы устанавливаем значение предделителя (в этом проекте он равен 8). Таким образом, мы получаем длительность 1 кванта:

T_{q}  = 222.2medspace нс

Первый сегмент на этой схеме – SYNC_SEG – используется для синхронизации всех узлов сети CAN. Ожидается, что фронт сигнала должен находиться внутри именно этого сегмента.

Второй сегмент — BS1 (Bit segment 1). Стандарт CAN включает в себя два сегмента — PROP_SEG и PHASE_SEG1. Оба этих сегмента в STM32 относятся к сегменту BS1. PROP_SEG нужен для компенсации физических задержек в сети, а PHASE_SEG1 используется для компенсации ошибки смещения фазы сигнала.

Сегмент BS1 определяет положение sample point (точки захвата). В этой точке модуль CAN анализирует уровень сигнала на шине, то есть определяет, принят рецессивный или доминантный бит.

И третий сегмент — BS2 (Bit segment 2). Он представляет из себя сегмент PHASE_SEG2 интерфейса CAN. Его назначение такое же как и у PHASE_SEG1.

Сегмент BS2 определяет положение transmit point (точки передачи), то есть того момента времени, когда модуль CAN выдает на линию определенный бит.

Длительности этих сегментов таковы:

  • SYNC_SEG: 1 квант времени
  • Bit segment 1 (BS1): 1 — 16 квантов
  • Bit segment 2 (BS2): 1 – 8 квантов

Устанавливая длительности различных сегментов, мы получаем время передачи одного бита в квантах. Зная длительность самого кванта, мы легко получаем время передачи бита в секундах. А уже из этого мы рассчитываем скорость передачи данных по шине. Только при настройке CAN нужно пройти в обратном направлении.

Пусть мы хотим задать скорость обмена равной 500 Кбит/с. Тогда время передачи одного бита:

T_{bit}  = frac{1medspace с}{500000medspace} = 2000medspace нс

Длительность одного кванта мы уже задали равной 222,2 нс. Таким образом, время 1-го бита в квантах:

T = frac{T_{bit}}{T_{q}} = 9

Эти 9 квантов нужно распределить между тремя сегментами. SYNC_SEG фиксирован (1 квант), значит остается 8 квантов на сегменты BS1 и BS2. Ставим в этом примере поровну – по 4 кванта и получаем нужную нам скорость обмена данными. И, наконец, можем двигаться дальше — включаем прерывания и генерируем код:

Настройка CAN для STM32.

В main() находим функцию инициализации CAN:

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();

Но на самом деле, на этом настройка не заканчивается. Дело в том, что в STM32 есть очень полезная функция фильтрации сообщений по ID. Как вы помните, ID в CAN относится не к устройству в сети, а к сообщению. То есть одно и то же устройство может рассылать сообщения с разными ID. А поскольку сеть является широковещательной, то приемник будет получать кучу сообщений, среди которых ему нужны только некоторые. И вот для этого и существует фильтрация сообщений. Благодаря аппаратной поддержке не нужно программно проверять ID всех принятых сообщений, можно всего лишь изначально настроить периферию на прием только нужных сообщений.

Настраивается этот механизм следующим образом:

CAN_FilterTypeDef canFilterConfig;
canFilterConfig.FilterBank = 0;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
canFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
canFilterConfig.FilterIdHigh = 0x0000;
canFilterConfig.FilterIdLow = 0x0000;
canFilterConfig.FilterMaskIdHigh = 0x0000;
canFilterConfig.FilterMaskIdLow = 0x0000;
canFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
canFilterConfig.FilterActivation = ENABLE;
canFilterConfig.SlaveStartFilterBank = 14;
HAL_CAN_ConfigFilter(&hcan, &canFilterConfig);

Собственно, за «пропускаемые» через фильтр ID отвечают эти поля структуры CAN_FilterTypeDef:

canFilterConfig.FilterIdHigh = 0x0000;
canFilterConfig.FilterIdLow = 0x0000;
canFilterConfig.FilterMaskIdHigh = 0x0000;
canFilterConfig.FilterMaskIdLow = 0x0000;
  • FilterIdHigh – старшая часть ID
  • FilterIdLow– младшая часть ID
  • FilterMaskIdHigh– старшая часть маски
  • FilterMaskIdLow– младшая часть маски

В данном случае все значения равны 0x0000, это означает, что абсолютно все сообщения будут проходить через фильтр.

Значения FilterIdHigh и FilterIdLow определяют идентификатор, с которым будет сравниваться ID принятого сообщения. А FilterMaskIdHigh и FilterMaskIdLow отвечают за битовую маску, которая, в свою очередь, определяет, какие биты идентификатора будут проверяться, а какие – нет. Единица в маске означает, что бит, который соответствует положению этой единицы, будет проверен. Сейчас на примере все станет окончательно понятно.

Итак, пусть мы хотим принимать только сообщения с ID из диапазона – 0x200 – 0x20F. Тогда настройка будет такой:

canFilterConfig.FilterIdHigh = 0x200 << 5;
canFilterConfig.FilterIdLow = 0x0000;
canFilterConfig.FilterMaskIdHigh = 0x7F0 << 5;
canFilterConfig.FilterMaskIdLow = 0x0000;

Обратите внимание, что для стандартного идентификатора значения  необходимо сместить влево  на 5 бит. Запишем в двоичном виде значения 0x200 – 0x20F, смещенные на 5 битов:

Фильтрация CAN сообщений.

Получается, что мы должны проверять 7 старших битов ID, одинаковые во всех идентификаторах. И, в итоге, получаем значение битов маски равным 0x7F0 << 5 (единицы соответствуют тем битам, которые должны соответствовать заданному в FilterIdHigh значению).

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

HAL_CAN_Start(&hcan);
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);

Теперь для приема сообщений CAN мы просто переопределяем соответствующую callback-функцию:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  CAN_RxHeaderTypeDef msgHeader;
  uint32_t msgId = 0;
  uint8_t msgData[8];
  
  HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &msgHeader, msgData);
    
  if (msgHeader.IDE == CAN_ID_EXT)
  {
    msgId = msgHeader.ExtId;
  }
  else
  {
    msgId = msgHeader.StdId;
  }
}

В самой функции мы вызываем HAL_CAN_GetRxMessage() для получения принятых данных и, например, проверяем тип идентификатора (расширенный или стандартный). Дальше уже можно использовать принятые данные по назначению. С приемом все понятно, давайте рассмотрим и процесс передачи.

В STM32F10x реализованы 3 так называемых mailbox’а, то есть по сути «почтовых ящика», в которые мы можем складывать наши сообщения. Далее микроконтроллер аппаратно выбирает, какое сообщение отправить в линию. Можно настроить механизм аналогичный FIFO, то есть первое помещенное в mailbox сообщение и отправлено будет первым. А можно настроить периферию на отправку сообщений в соответствии с приоритетом самих сообщений.

Для каждого из mailbox’ов есть соответствующий callback, который вызывается по окончанию передачи:

  • void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan)
  • void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan)
  • void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan)

Отправим тестовое сообщение:

if (HAL_CAN_GetTxMailboxesFreeLevel(&hcan) != 0)
{
  CAN_TxHeaderTypeDef msgHeader;
  uint8_t msgData[8];

  msgHeader.StdId = 0x200;
  msgHeader.DLC = 8;
  msgHeader.TransmitGlobalTime = DISABLE;
  msgHeader.RTR = CAN_RTR_DATA;
  msgHeader.IDE = CAN_ID_STD;
  
  uint32_t mailBoxNum = 0;
  
  for (uint8_t i = 0; i < 8; i++)
  {
    msgData[i] = i;
  }
  
  HAL_CAN_AddTxMessage(&hcan, &msgHeader, msgData, &mailBoxNum);
}

Первым делом вызываем HAL_CAN_GetTxMailboxesFreeLevel(&hcan). Функция возвращает количество свободных mailbox’ов. Если есть хоть один свободный mailbox, то начинаем формировать сообщение на передачу — устанавливаем параметры сообщения, идентификатор и, конечно же, непосредственно данные. Затем вызываем функцию HAL_CAN_AddTxMessage(), которая поместит наше новое сообщение в один из mailbox’ов и активирует соответствующий запрос на передачу.

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

Итак, в общем-то, на этом все — CAN настроили, прием и передачу осуществили ) Проект для статьи доступен по ссылке — MT CAN Example.

До скорых встреч и спасибо за внимание 🤝

8. CAN

8.1 Основные понятия

Полное название — Controller Area Network, что представляет собой полудуплексную асинхронную связь. Аргумента «главный-подчиненный» нет, каждое устройство может отправлять и получать.

8.1.1 Физический уровень

Две сигнальные линии, CAN_High и CAN_Low две дифференциальные сигнальные линии, обмениваются данными в дифференциальной форме

Два типа сетей:

Замкнутый контур: длина шины может составлять до 40 м, а максимальная скорость составляет 1 Мбит / с.

circ

На каждом конце шины есть резистор 120 Ом.

circ

Контроллер CAN является контроллером каждого устройства, подключенного к шине, и обычно должен быть оснащен трансивером CAN (например, трансивер CAN на кодовом диске нашей команды использует TJA1050) для преобразования потока двоичного кода контроллера CAN в Дифференциальный уровень шины CAN, передача данных по двум кабелям шины с дифференциальным напряжением

Открытый цикл: максимальное расстояние передачи составляет 1 км, максимальная скорость — 125 кбит / с.

circ

Укажите последовательно резистор 2,2 кОм для каждого провода.

Дифференциальный сигнал протокола CAN

circ

Доминирующий уровень соответствует «0», а рецессивный уровень соответствует «1». Рецессивный уровень (1) оба линейных напряжения составляют 2,5 В, то есть разность напряжений равна 0; доминирующий уровень (0) CAN_High и CAN_Low составляют 3,5 В и 1,5 В соответственно, а разница напряжений составляет 2 В.

circ

На шине, пока один узел выводит доминирующий уровень, шина находится на доминирующем уровне; только когда все узлы находятся на рецессивном уровне, шина находится на рецессивном уровне

circ

Поскольку CAN является полудуплексным, отправка и получение выполняются отдельно, и это связь по шине, поэтому только один узел может отправлять одновременно, а другие узлы могут только получать в это время.

8.1.2 Уровень протокола

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

Значение: для достижения правильной выборки на уровне шины, чтобы обеспечить нормальную связь. Самая маленькая единица — Tq (Time Quantum), полный бит состоит из 8 ~ 25 Tq.

Состав: раздел SS, раздел PTS, раздел PBS1, раздел PBS2

Название раздела значение эффект
SS(1Tq) Синхронизировать сегмент Синхронизируйте узлы шины
PTS(1~8Tq) Период размножения Компенсация физической задержки, которая в два раза превышает сумму времени распространения и задержки трансивера.
PBS1(1~8Tq) Фазовый буфер 1 Компенсация погрешности трансформаторного каскада
PBS2(2~8Tq) Фазовый буфер 2 Компенсация ошибки фазы фронта
SJW(1~4Tq) Ширина компенсации ресинхронизации Компенсация отклонения тактовой частоты, задержки передачи и т. Д.

Например

Расчет скорости передачи данных: линия синхронизации, используемая CAN, — это периферийные часы APB1 (при условии APC), что обычно составляет четверть частоты SYSCLK. И связь CAN также должна предварительно масштабировать это (при условии, что это Prescaler), тогда Tq — это Prescaler / APC (unit s). И один бит данных занимает (SS + PTS + PBS1 + PBS2 + SJW) Tq. Тогда количество битов, которые могут быть переданы за одну секунду, равно

1

T

q

Один

А

Немного

Получить

T

q

число

frac {1} {Tq * Tq число на цифру}

Например: в дереве тактовых импульсов частота периферийных часов APB1 составляет 45 МГц, а предделитель равен 5, тогда Tq — это

4

45

M

H

z

=

111.1111

(

n

s

)

frac{4}{45MHz}=111.1111dots(ns)

, На рисунке выше 19 Tqs, тогда скорость передачи равна

1

19

111.11

1

0

9

473689

(

b

p

s

)

frac{1}{19*111.11*10^{-9}}approx473689(bps)

Сообщение

Тип кадра:

Виды использовать
Фрейм данных Отправляющий блок для получения информационного содержания блока
Рама дистанционного управления Получите блок отправить данные запроса блока
Кадр ошибки Уведомлять другие подразделения об обнаруженных ошибках
Рамка перегрузки Уведомление не готово к приему
Интервальный кадр Отделите фрейм данных или фрейм перед фреймом дистанционного управления

Структура кадра данных:

Начинается с доминирующего бита (0) и заканчивается 7 последовательными невидимыми битами (1). Посередине расположены секция арбитража, секция управления, секция данных, секция CRC и секция ACK последовательно, всего 7 секций.

Начало кадра (SOF): доминирующий уровень. Используется для уведомления каждого узла о передаче данных

Раздел арбитража: используется для указания приоритета. Разница между стандартным форматом и расширенным форматом здесь, идентификатор стандартного формата составляет 11 бит, а расширенный формат — 11 + 18 = 29 бит. RTR (бит запроса удаленной передачи) использует явный рецессивный уровень, чтобы отличать кадры данных от кадров удаленного управления.

IDR (Identifier Extension Bit), доминантная — стандартная форма, рецессивная — расширенная.

SSR, стандартный формат RTR, является рецессивным битом.

Идентификатор определяет приоритет кадра данных. Когда два узла конкурируют за шину одновременно, узел с рецессивным уровнем сначала теряет свое владение и переходит в состояние приема.

Сегмент управления: r1 и r0 являются зарезервированными битами и по умолчанию являются доминирующими. DLC, длина массива данных, 0 ~ 8

Сегмент данных: 08 байт (064 бит)

Сегмент CRC: всего 16 бит. 15-битный контрольный код CRC, 1-битный разделитель, рецессивный

Сегмент ACK: всего 2 бита. Один бит — это слот ACK, отправитель отправляет рецессивный, а получатель отправляет доминирующий, чтобы указать ответ; один бит является разделителем конца кадра

Конец кадра (ROF): 7 невидимых бит

8.1.3 Фильтр

Цель: отфильтровать неинтересные сообщения, то есть сообщения, не имеющие отношения к этому узлу

Два режима: режим списка и режим маски

Количество фильтров: необязательно 0 при использовании CAN№ 13 фильтр; использовать два CAN да, опционально 0№ 37 фильтр

Режим

Режим списка: составьте таблицу идентификаторов интересующих сообщений. Когда полученный идентификатор сообщения совпадает, оно будет получено, в противном случае оно не будет получено

Преимущества, точные, могут полностью отфильтровать нежелательные сообщения

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

В режиме маски пакеты с частичными идентификаторами получают через операцию И.

Преимущества, круг интересов может быть больше

Недостатки, возможно, не удастся полностью отфильтровать незаинтересованные сообщения, точность зависит от кода маскировки.

Битовая ширина

Фильтр доступен в 32-битном и 16-битном вариантах. Среди них 16 бит могут фильтровать только стандартные кадры, но не расширенные кадры.

8.2 STM32 CAN

STM32 имеет два набора контроллеров CAN, CAN1 — это главное устройство, отвечающее за управление bxCAN (базовая расширенная CAN, то есть CAN) и 512 байтов SRAM. CAN2 является подчиненным контроллером и не может напрямую обращаться к SRAM. Периферийные часы CAN1 должны быть включены для использования CAN2

В STM32, когда фильтр приема CAN использует 32 бита, маска и проверочный код разделяются на два регистра, каждый по 16 бит, представляющих старшие 16 бит и младшие 16 бит.

8.3 Шаги настройки CubeMX

  1. Список слева>Connectivity> Нажмите CAN1 / CAN2 ~> Проверка режима Master Mode / Slave Mode

  2. Параметры конфигурации имеют следующие значения:

    параметр имея в виду
    Prescaler Предделитель, то есть периферийные часы APB1, упомянутые в битовой синхронизации, продолжают делиться один раз
    Time Quantum Минимальная единица времени Tq, рассчитывается автоматически, вводить не нужно
    Time Quanta in Bit Segment 1 Длина сегмента PBS1
    Time Quanta in Bit Segment 2 Длина секции PBS2
    ReSynchronization Jump Width Ширина скачка ресинхронизации, то есть SJW, упомянутая в битовой синхронизации
    Time Triggered Communication Mode Включить ли триггер времени
    Automatic Bus-Off Management Следует ли включать автоматическое автономное управление
    Automatic Wake-Up Mode Включать ли автоматическое пробуждение
    Qutomatic Retransmission Включать ли автоматическую повторную передачу
    Receive Fifo Locked Mode Включить ли блокировку FIFO
    Transmit Fifo Priority Метод суждения для настройки приоритета сообщения
    Oprating Mode Режим работы

    Эти параметры также можно изменить в can.c

  3. Настройки прерывания (NVIC), установленные по мере необходимости, обычно проверяют прерывание CAN1 RX0

8.4 Программирование

Все определения функций и структуры библиотеки HAL о CAN находятся в stm32f4xx_HAL_Driver.c и stm32f4xx_HAL_Driver.h в папке Drivers / STM32F4xx_HAL_Driver соответственно

Вот несколько основных и часто используемых

8.4.1 Базовая структура CAN

Структура определения отправки сообщения (CAN_TxHeaderTypeDef)

typedef struct
{
  uint32_t StdId;    / *! Стандартный ID. Значение параметра может быть только от 0 до 0x7FF (11 бит 1 в двоичном формате) * /

  uint32_t ExtId;    / *! Идентификатор расширения. Значение параметра может быть только от 0 до 0x1FFFFFFF (29 бит 1 в двоичном формате) * /

  uint32_t IDE;      / *! IDE. При программировании библиотеки HAL укажите CAN_ID_STD для стандартных кадров и CAN_ID_EXT для расширенных кадров * /

  uint32_t RTR;      / *! RTR. При программировании библиотеки HAL заполните CAN_RTR_DATA во фрейме данных и заполните CAN_RTR_REMOTE во фрейме дистанционного управления * /

  uint32_t DLC;      / *! DLC. Длина данных, значение параметра может быть только от 0 до 8 * /

  FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
                          of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
                          @note: Time Triggered Communication Mode must be enabled.
                          @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
                          This parameter can be set to ENABLE or DISABLE. */

} CAN_TxHeaderTypeDef;

Структура определения сообщения приема(CAN_RxHeaderTypeDef)

typedef struct
{
  uint32_t StdId;   

  uint32_t ExtId;    

  uint32_t IDE;      

  uint32_t RTR;      

  uint32_t DLC;      

  uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on start of frame reception.
                          @note: Time Triggered Communication Mode must be enabled.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFFFF. */

  uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance filter element.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF. */

} CAN_RxHeaderTypeDef;

Структура определения типа фильтра приема (CAN_FilterTypeDef)

typedef struct
{
  uint32_t FilterIdHigh;          / *! Старшие 16 цифр идентификатора кода проверки фильтра могут заполнять только значение от 0 до 0xFFFF * /

  uint32_t FilterIdLow;           / *! Младшие 16 бит идентификатора фильтра, вы можете ввести только значение от 0 до 0xFFFF * /

  uint32_t FilterMaskIdHigh;      / *! Старшие 16 бит идентификатора маски фильтра могут заполнять только значение от 0 до 0xFFFF * /

  uint32_t FilterMaskIdLow;       / *! Младшие 16 бит идентификатора маски фильтра могут заполнять только значение от 0 до 0xFFFF * /

  uint32_t FilterFIF(x)Assignment;  / *! В какой FIFOx поместить переданное сообщение и заполнить FIFO (x) * /

  uint32_t FilterBank;            / *! Использовать номер фильтра. Если вы используете одну CAN, вы можете выбрать 0 ~ 13; если вы используете две CAN, вы можете выбрать 0 ~ 27 * /

  uint32_t FilterMode;            / *! Выбор режима фильтрации. Заполните CAN_FILTERMODE_IDMASK для режима маски и заполните режим списка
                                                                           Заполните CAN_FILTERMODE_IDLIST * /

  uint32_t FilterScale;           / *! Разрядность фильтра, 32 бита CAN_FILTERSCALE_32BIT,
                                                                                               16 бит - CAN_FILTERSCALE_16BIT * /

  uint32_t FilterActivation;      / *! Включить ли фильтр, ОТКЛЮЧИТЬ или ВКЛЮЧИТЬ * /

  uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
                                       For single CAN instances, this parameter is meaningless.
                                       For dual CAN instances, all filter banks with lower index are assigned to master
                                       CAN instance, whereas all filter banks with greater index are assigned to slave
                                       CAN instance.
                                       This parameter must be a number between Min_Data = 0 and Max_Data = 27. */

} CAN_FilterTypeDef;

Примечание. Четыре члена FilterIdHigh, FilterIdLow, FilterMaskIdLow и FilterMaskIdLow не так просты, как их имена.

Их функция зависит от используемого режима фильтрации. Если это режим списка, неважно, FilterId или FilterMaskId, это столбец

Члены таблицы.

Вышеупомянутые четыре члена — все 16 бит, обязательно обратите внимание на операцию сдвига, упомянутую ниже.

В 32-битном фильтре группа High и Low проверяет один и тот же CAN ID; 16-битный фильтр, вы можете независимо тестировать ID

Регистры фильтра следующие: (При использовании библиотеки HAL не нужно копаться в конкретных регистрах, просто обратите внимание на содержимое каждого бита сопоставления)

32-битный режим списка

16-битный режим списка


32-битный режим маски
Режим 16-битной маски

Стандартный кадр представлен 16-битным фильтром: FilterIdHigh, FilterIdLow, FilterMaskIdLow, FilterMaskIdLow может представлять член списка. Поскольку идентификатор стандартного кадра составляет 11 бит, необходимо сдвинуть идентификатор на 5 бит влево.

Стандартный кадр представлен 32-битным фильтром: FilterIdHigh и FilterIdLow вместе представляют идентификатор, а FilterMaskIdLow и FilterMaskIdLow вместе представляют идентификатор. Поскольку стандартный идентификатор кадра составляет 11 бит, его идентификатор необходимо сдвинуть влево на 5 бит и сохранить в High, когда он отображается, а LOW = 0 | CAN_ID_STD (что означает, что позиция IDE равна 0)

Расширенный кадр представлен 32-битным фильтром: идентификатор расширенного кадра составляет 29 бит, поэтому расширенный идентификатор кадра сначала сдвигается влево на 3 бита, и 32 бита выравниваются с высоким битом, а затем сдвигаются на 16 бит вправо, а младшие 16 бит берутся и сохраняются в высоком уровне Сдвиньте расширенный идентификатор кадра влево на 3 бита, чтобы выровнять его с 32 битами, а затем возьмите младшие 16 бит и сохраните их в низком. Конкретная операция выглядит следующим образом

CAN_FilterTypeDef sFilterConfig                                 // Определение переменной структуры настройки фильтра
uint32_t StdId =0x321;				                            // Стандартный CAN ID
uint32_t ExtId =0x1800f001;			                            // Расширенный CAN ID

sFilterConfig.FilterIdHigh = StdId<<5;			                // Стандартный идентификатор помещается в FilterIdHigh
sFilterConfig.FilterIdLow = 0|CAN_ID_STD;			            // Стандартный идентификатор, поэтому установите бит IDE в 0

sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;       // Старшие 16 бит расширенного идентификатора кадра помещаются в FilterMaskIdHigh
sFilterConfig.FilterMaskIdLow = (ExtId<<3)&0xffff|CAN_ID_EXT;	// Старшие 16 бит расширенного идентификатора кадра помещаются в FilterMaskIdLow, а бит IDE устанавливается в 1

Что касается проверочного кода и маски: предположим, что есть список наблюдения, полный интересных сообщений. Код подтверждения может быть идентификатором любого члена в списке наблюдения (после вышеупомянутой обработки), а маска является результатом XOR всех заинтересованных членов.

Таким образом, существует две разрядности, два режима и в общей сложности четыре режима фильтрации. Характеристики суммируются следующим образом:

Режим Характеристики
16-битный список Может содержать четыре члена списка
32-битный список Может содержать два члена списка
16-битная маска Можно проверить две пары кода подтверждения и маски
32-битная маска Можно проверить пару проверочного кода и маски

8.4.2 Основные функции CAN

Функции управления следующие

функция Характеристики
HAL_CAN_Start Включить связь CAN
HAL_CAN_Stop Закройте связь CAN
HAL_CAN_RequestSleep Попробуйте войти в спящий режим
HAL_CAN_WakeUp Выход из спящего режима
HAL_CAN_IsSleepActive Проверьте, успешно ли вы перешли в спящий режим
HAL_CAN_AddTxMessage Добавьте сообщение в почтовый ящик Tx и активируйте соответствующий запрос на передачу
HAL_CAN_AbortTxRequest Запросить передачу прерывания
HAL_CAN_GetTxMailboxesFreeLevel Return Tx mailboxes free level
HAL_CAN_IsTxMessagePending Проверить, есть ли ожидающий запрос передачи на указанный почтовый ящик Tx
HAL_CAN_GetRxMessage Получите CAN-кадр из Rx FIFO
HAL_CAN_GetRxFifoFillLevel Return Rx FIFO fill level
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)**

Функция: включить CAN, обычно в начале
Параметры: указатель дескриптора CAN, & hcan1 или & hcan2
Возвращаемое значение: возвращаемое значение: статус HAL

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)

Функция: настройка фильтра CAN
Параметр: первый, указатель дескриптора CAN, & hcan1 или & hcan2
Второй, указатель на структуру конфигурации CAN.
Возвращаемое значение: возвращаемое значение: статус HAL

HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs)

Функция: разрешить прерывание
Параметр: первый, указатель дескриптора CAN, & hcan1 или & hcan2
Второй, прерывание которого разрешено, в stm32f4xx_HAL_Driver.h, ищите прерывания приема, чтобы найти каждое определение макроса
Возвращаемое значение: возвращаемое значение: статус HAL

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)(Согласно использованию0Может быть заменен на1

Функция: функция обратного вызова приема, работа после обратного вызова CAN. Обычно получают данные здесь
Параметр: первый, указатель на дескриптор CAN
Возвращаемое значение: void

HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)**

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

Параметры: первый, указатель CAN-дескриптора, & hcan1 или & hcan2
Второй, указатель на структуру определения отправленного сообщения.
Третье, содержимое массива фрейма данных, длина не может превышать заданную длину
Четвертый, почтовый ящик Tx, может заполнять (uint32_t *) CAN_TX_MAILBOX0, CAN_TX_MAILBOX1, CAN_TX_MAILBOX3
Возвращаемое значение: статус HAL

HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])

Функция: получение кадра CAN от Rx FIFO
Параметры: первый, указатель дескриптора CAN, & hcan1 или & hcan2
Второй, Rx FIFO, можно заполнить CAN_RX_FIFO0, CAN_RX_FIFO1
Третий — указатель на структуру определения полученного сообщения.
В-четвертых, принять массив данных
Возвращаемое значение: статус HAL

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)

Функция: Установить фильтр приема
Параметр: первый, указатель дескриптора CAN, & hcan1 или & hcan2
Второй, указатель на структуру определения типа фильтра.
Возвращаемое значение: статус HAL

8.4.3 Пример шагов программирования CAN

  1. Определите переменную структуры определения типа принимающего фильтра (CAN_FilterTypeDef)

  2. Настроить фильтр приема CAN HAL_CAN_ConfigFilter

  3. Включите CAN, HAL_CAN_Start

  4. Отправить, HAL_CAN_AddTxMessage

  5. Для получения нужно сначала включить прерывание HAL_CAN_ActivateNotification, а второй параметр установить на CAN_IT_RX_FIFO0_MSG_PENDING

    Функция обратного вызова прерывания HAL_CAN_RxFifo0MsgPendingCallback, которая определяет структурную переменную структуры определения полученного сообщения (CAN_RxHeaderTypeDef). Прием с функцией приема HAL_CAN_GetRxMessage

Базовое расширенное периферийное устройство CAN (Basic Extended CAN, которое сокращенно называется bxCAN), позволяет подключить MCU STM32 с сети CAN. Поддерживаются CAN протоколы версий 2.0A и 2.0B. Контролер CAN был разработан для эффективного обслуживания большого количества входящих сообщений с минимальной нагрузкой на вычислительное ядро CPU. Также он удовлетворяет требованиям приоритета для передачи сообщений.

Примечание: информация в этой статье (перевод раздела «32 Controller area network (bxCAN)» даташита [1]) относится ко всем представителям MCU семейства STM32F4xx, если специально не указано что-то иное.

В критически важных для безопасности приложениях контроллер CAN предоставляет все аппаратные функции для поддержки опции обмена CAN Time Triggered Communication.

Основные функции и возможности bxCAN:

• Имеется два интерфейса CAN: CAN1 и CAN2.
• Поддерживается протокол CAN версий 2.0A, B Active.
• Скорости до 1 мегабит/сек.
• Поддерживается опция Time Triggered Communication.

Передача:

• 3 передающих mailbox.
• Конфигурируемый приоритет передачи.
• Метка времени (Time Stamp) на передаче SOF.

Прием:

• 2 принимающих FIFO с тремя уровнями.
• Масштабируемые банки фильтра: 28 банков фильтра, используемые совместно CAN1 и CAN2.
• Функция идентификатора списка.
• Конфигурируемый порог переполнения FIFO (FIFO overrun).
• Метка времени (Time Stamp) на приеме SOF.

Опция коммуникации Time-triggered:

• Запрет режима автоматической ретрансмиссии.
• 16-разрядный свободно считающий таймер.
• Метка времени (Time Stamp) в последних двух байтах данных.

Управление:

• Маскируемые прерывания.
• Эффективное для программы отображение mailbox на уникальный адрес.

Одновременная работа двух CAN (Dual CAN):

• CAN1: Master bxCAN для управления коммуникацией между Slave bxCAN и 512 байтами памяти SRAM.
• CAN2: Slave bxCAN, без прямого доступа к памяти SRAM.
• Два bxCAN используют общую память 512 байт SRAM (см. рис. 335).

bxCAN Dual CAN block diagram fig335

Рис. 335. Блок-схема Dual CAN.

Примечание: начальный банк фильтров CAN2 номер n конфигурируется записью CAN2SB[5:0] бит в регистре CAN_FMR.

[Общее описание bxCAN]

В современных приложениях CAN количество узлов сети увеличивается, и часто сети соединяются друг с другом через шлюзы (gateway). Обычно количество сообщений в системе (и таким образом обрабатываемых каждым узлом) значительно увеличивается. В дополнение к сообщениям приложения были введены сообщения управления сетью и диагностики (Network Management and Diagnostic messages).

• Для обработки каждого типа сообщения требуется расширенный механизм фильтрации.

Кроме того, задачи приложения требуют большего времени CPU, поэтому должны быть уменьшены ограничения по реальному времени обработки, вызванные приемом сообщения.

• Схема FIFO приема позволяет переключить CPU на задачи приложения на долгое время без потери принимаемых сообщений.

Стандартный высокоуровневый протокол HLP (аббревиатура от Higher Layer Protocol), основанный на стандартных драйверах CAN, требует эффективного интерфейса с контроллером CAN.

bxCAN CAN network topology fig334

Рис. 334. Топология сети CAN.

Активное ядро CAN 2.0B. Модуль bxCAN полностью автономно обрабатывает передачу и прием сообщений CAN. Стандартные идентификаторы (11 бит) и расширенные идентификаторы (29 бит) полностью поддерживаются аппаратурой контроллера.

Регистры управления, статуса и конфигурации. Приложение использует эти регистры для следующих целей:

• Конфигурирования параметров CAN, например скорости передачи/приема (baud rate).
• Запрос передач.
• Обработка приема.
• Управление прерываниями.
• Получение информации диагностики.

Передающие ящики (Tx mailboxes). Предоставлены 3 передающих mailbox, чтобы настраивать отправку сообщений. Планировщик передачи (transmission Scheduler) принимает решение, какой mailbox должен быть передан первым.

Фильтры приема (Acceptance filters). bxCAN предоставляет 28 масштабируемых / конфигурируемых банков фильтров по идентификатору, чтобы выделять из принимаемых данных нужные сообщения и отбрасывать другие.

FIFO приема. Для сохранения поступающих сообщений используются 2 приемных FIFO. В каждом FIFO можно сохранить 3 полных сообщения. FIFO полностью обслуживаются аппаратурой контроллера CAN.

[Рабочие режимы bxCAN]

У bxCAN есть 3 основных рабочих режима: initialization (инициализация), normal (активная работа) и Sleep (сон, приостановка). После аппаратного сброса bxCAN находится в режиме Sleep, чтобы снизить потребление энергии, и на CANTX активен внутренний pull-up (верхний подтягивающий резистор). Программа запрашивает bxCAN на вход в режим initialization или Sleep установкой бит INRQ или SLEEP в регистре CAN_MCR. Как только произошел вход в режим, bxCAN подтверждает это установкой бит INAK или SLAK в регистре CAN_MSR, и внутренний pull-up запрещается. Когда ни один из бит INAK и SLAK не установлен, bxCAN находится в режиме normal. Перед входом в режим normal bxCAN всегда должен быть синхронизирован с шиной CAN. Для синхронизации bxCAN ждет, пока шина CAN не освободится (перейдет в состояние idle), это означает, что отслеживается появление 11 следующих друг за другом рецессивных бита на сигнале CANRX.

Режим инициализации. Программная инициализация может быть осуществлена, когда железо CAN находится в режиме инициализации (Initialization mode). Чтобы войти в этот режим, программа устанавливает бит INRQ в регистре CAN_MCR и ждет, пока железо подтвердит этот запрос установкой бита INAK в регистре статуса CAN_MSR.

Чтобы покинуть режим инициализации, программа очищает бит INQR. bxCAN покинет режим инициализации, когда бит INAK очистится аппаратурой.

Во время режима инициализации останавливаются все входящие и исходящие транзакции сообщений CAN, и статус шины CAN на выходе CANTX сохраняется рецессивным (лог. 1).

Вход в режим инициализации не меняет ни один регистр конфигурации.

Чтобы инициализировать контроллер CAN, программа должна установить длительность бита (Bit Timing, регистр CAN_BTR) и опции CAN (регистр управления CAN_MCR).

Чтобы инициализировать регистры, связанные с банками фильтров CAN (mode, scale, FIFO assignment, activation и значения фильтраand filter values), программа должна установить бит FINIT (в регистре CAN_FMR). Инициализация фильтра также может быть осуществлена вне режима инициализации.

Примечание: когда FINIT=1, прием CAN деактивирован. Значения фильтра также можно модифицировать сбросом соответствующих бит активации (в регистре CAN_FA1R). Если банк фильтра не используется, то рекомендуется оставить его в неактивном режиме (т. е. оставить его соответствующий бит FACTx очищенным).

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

Запрос входа в Normal mode выдается очисткой бита INRQ в регистре управления CAN_MCR. Блок bxCAN входит в режим Normal и готов принять участие в активности на шине, когда он синхронизирован с передачей данных по шине CAN. Это осуществляется ожиданием появления на шине 11 следующих друг за другом рецессивных бит (состояние ожидания Bus Idle). Переключение в Normal mode подтверждается аппаратурой, когда она сбрасывает бит INAK в регистре статуса CAN_MSR.

Инициализация значений фильтра не зависит от режима инициализации, однако должна осуществляться, когда инициализируемый фильтр не активен (его соответствующий бит FACTx сброшен). Параметры фильтра scale и mode должны конфигурироваться перед входом в режим Normal.

Режим Sleep (малое потребление мощности). Чтобы уменьшить энергопотребление, у bxCAN есть режим пониженного потребления мощности (low-power mode), который называется режим сна (Sleep mode). В этот режим осуществляется вход по запросу программы установкой бита SLEEP в регистре CAN_MCR. В этом режиме тактирование bxCAN останавливается, однако программа все еще имеет доступ к ящикам (mailboxes) bxCAN.

Если программа запрашивает вход в режим инициализации установкой бита INRQ, когда bxCAN находится в Sleep mode, она также должна очистить бит SLEEP.

Блок bxCAN может быть разбужен (выведен из Sleep mode) либо программно путем очистки бита SLEEP, или когда была детектирована активность шины CAN.

Когда была определена активность на шине CAN, аппаратура автоматически выполняет последовательность пробуждения очисткой бита SLEEP, если установлен бит AWUM в регистре CAN_MCR. Если бит AWUM очищен, то программа должна очистить бит SLEEP, когда произошло прерывание пробуждения (wakeup interrupt), чтобы bxCAN вышел из Sleep mode.

Примечание: если разрешено прерывание пробуждения (wakeup interrupt, установлен бит WKUIE в регистре CAN_IER), то будет генерироваться прерывание пробуждения, когда была определена активность шины CAN, даже если bxCAN автоматически выполняет последовательность пробуждения.

После того, как бит SLEEP был очищен, произойдет выход из Sleep mode, когда bxCAN засинхронизировался с шиной CAN, см. рис. 336. Из режима Sleep mode произойдет выход, когда аппаратура очистила бит SLAK.

bxCAN operating modes fig336

Рис. 336. Режимы bxCAN.

Примечания:

(1) ACK = состояние ожидания (wait state), во время которого аппаратура подтверждает запрос установкой бит INAK или SLAK в регистре CAN_MSR.
(2) SYNC = состояние, во время которого bxCAN ожидает состояния ожидания шины CAN (idle state, когда прошло 11 следующих друг за другом рецессивных бита на CANRX).

[Режим тестирования]

Режим тестирования может быть выбран битами SILM и LBKM в регистре CAN_BTR. Эти биты должны быть сконфигурированы, когда bxCAN находится в Initialization mode. Как только был выбран режим тестирования, для входа в режим Normal должен быть сброшен бит INRQ в регистре CAN_MCR.

Silent mode. Блок bxCAN может быть переведен в «тихий режим» (Silent mode) установкой бита SILM в регистре CAN_BTR.

В тихом режиме bxCAN может принимать правильные фреймы данных и правильные фреймы remote, однако bxCAN передает только рецессивные биты на шине CAN, и не может начать передачу. Если bxCAN должен отправить доминантный бит (бит ACK, флаг overload, флаг active error), то бит перемашрутизируется внутри таким образом, что ядро CAN мониторит этот доминантный бит, хотя шина CAN может оставаться в рецессивном состоянии. Silent mode может использоваться для анализа трафика на шине CAN без влияния на шину передачей доминантных бит (доминантные биты Acknowledge, фреймы ошибки Error Frame физически не передаются).

bxCAN in silent mode fig337

Рис. 337. Блок bxCAN в Silent Mode.

Loop back mode. Блок bxCAN может быть установлен в режим зацикливания (Loop Back Mode) установкой бита LBKM в регистре CAN_BTR. В Loop Back Mode блок bxCAN обрабатывает свои собственные передаваемые сообщения как принимаемые, и сохраняет их (если они прошли фильтрацию, acceptance filtering) в ящиках приема (Receive mailbox).

bxCAN in loop back mode fig338

Рис. 338. Блок bxCAN в режиме зацикливания.

Этот режим предоставлен для функций самотестирования. Чтобы быть независимым от внешних событий, ядро CAN игнорирует ошибки подтверждения (acknowledge errors, отсутствие доминантного бита, оцифрованного в слоте подтверждения данных фрейма data / remote), в режиме Loop Back. В этом режиме bxCAN соединяет выход Tx со входом Rx внутри чипа. Актуальное значение входа на выводе CANRX игнорируется блоком bxCAN. Передаваемые сообщения могут мониториться на выводе CANTX.

Комбинация режимов Loop back и silent. Можно также скомбинировать режимы Loop Back и Silent установкой бит LBKM и SILM в регистре CAN_BTR. Это может использоваться для «горячего самотестирования», т. е. bxCAN может быть проверен в режиме Loop Back, но без влияния на работающую систему CAN, подключенную к выводам CANTX и CANRX. В этом режиме вывод CANRX отключен от bxCAN, и вывод CANTX удерживается в рецессивном состоянии.

bxCAN in combined mode fig339

Рис. 339. Блок bxCAN в комбинированном режиме.

[Debug mode]

Когда MCU вошел в отладочный режим debug mode (приостановлено ядро Cortex®-M4 с FPU), блок bxCAN продолжит нормально работать или останавливается, в зависимости от:

• Бита DBG_CAN1_STOP для CAN1 или бита DBG_CAN2_STOP для CAN2 в модуле DBG. Для получения подробностей см. секцию «38.16.2 Debug support for timers, watchdog, bxCAN and I2C» даташита [1].
• Бита DBF в регистре CAN_MCR. Для дополнительной информации см. секцию 32.9.2 даташита [1].

[Функциональное описание bxCAN]

Обработка передачи. Чтобы передать сообщение, приложение должно выбрать пустой transmit mailbox, установить идентификатор, код длины данных (data length code, DLC) и передаваемые данные перед тем, как запросить передачу установкой соответствующего бита TXRQ в регистре CAN_TIxR. Как только mailbox покинул состояние опустошенности (empty state), программа больше не может получить доступ на запись в его регистры. Сразу после установки бита TXRQ mailbox входит в состояние ожидания отправки (enters pending), и ждет, когда он станет самым приоритетным для передачи, см. врезку «Приоритет передачи». Как только mailbox получил самый высокий приоритет, он будет запланирован на передачу. Передача сообщения запланированного mailbox начнется (произойдет вход в состояние передачи), когда шина CAN окажется в состоянии ожидания (idle). Как только mailbox был успешно передан, он снова станет пустым (empty). Аппаратура покажет успешную передач установкой бит RQCP и TXOK в регистре CAN_TSR.

Если передача была неудачной, то это состояние будет показано битом ALST в регистре CAN_TSR, когда был проигрыш арбитража (Arbitration Lost), и/или битом TERR, когда была детектирована ошибка передачи.

Приоритет передачи устанавливается по идентификатору и по порядку запроса передачи (transmit request order).

По идентификатору. Когда больше одного transmit mailbox ожидают передачи, порядок передачи сообщения определяется по идентификатору, сохраненному в mailbox. Сообщение с самым малым значением идентификатора имеет самый высокий приоритет в соответствии со схемой арбитража протокола CAN. Если же значения идентификатора одинаковые, то сначала планируется передача из mailbox с самым малым номером.

По порядку запроса передачи. Передающие mailbox можно сконфигурировать как transmit FIFO установкой бита TXFP в регистре управления CAN_MCR. В этом режиме приоритет для порядка передачи определяется по порядку поступления запросов не передачу (тот ящик, для которого запрос поступил раньше, будет передан первым). Этот режим очень полезен для сегментированных передач.

Обрыв передачи. Запрос на передачу может быть оборван (abort) пользователем путем установки бита ABRQ в регистре CAN_TSR. Когда mailbox находится в состоянии pending или scheduled обрыв произойдет немедленно. Когда запрос на abort поступил в состоянии передачи mailbox, то состояние передачи может иметь одно из 2 результатов. Если была успешная передача, то mailbox станет пустым с установкой бита TXOK в регистре CAN_TSR. Если передача была неудачной, то mailbox получит состояние запланированности на передачу (scheduled), передача оборвется и ящик станет пустым с очищенным TXOK. Во всех случаях ящик становится пустым, как минимум в конце текущей передачи.

Режим не автоматической повторной передачи. Этот режим был реализован, чтобы удовлетворить требованиям опции Time Triggered Communication стандарта CAN. Чтобы сконфигурировать аппаратуру в этот режим, должен быть установлен бит NART в регистре CAN_MCR.

В этом режиме каждая передача начинается только однократно. Если первая попытка потерпела неудачу из-за потери арбитража или из-за ошибки, аппаратура не будет автоматически перезапускать передачу сообщения.

По окончании первой попытки передачи, аппаратура считает запрос завершенным, и установит бит RQCP в регистре CAN_TSR. Результат передачи показывается в регистре CAN_TSR битами TXOK, ALST и TERR.

bxCAN Transmit mailbox states fig340

Рис. 340. Состояния передающего mailbox.

Режим Time Triggered Communication. В этом режиме активируется внутренний счетчик аппаратуры CAN и используется для генерации значения метки времени (Time Stamp), сохраняемой в регистрах CAN_RDTxR/CAN_TDTxR (соответственно для Rx и Tx mailbox). Внутренний счетчик инкрементируется на каждом битовом интервале CAN, см. далее секцию «Интервалы бит (bit timing)». Внутренний счетчик захватывается в точке оцифровки (sample point) бита начала фрейма (Start Of Frame, SOF) и для приема, и для передачи.

[Обработка приема]

Для приема сообщений CAN предоставляются три mailbox, организованных как FIFO. Чтобы уменьшить нагрузку на CPU, упростить программу и гарантировать целостность данных, FIFO полностью обслуживается аппаратурой. Приложение обращается к сохраненным в FIFO сообщениям через выходной mailbox FIFO.

Корректно принятое сообщение. Принятое сообщение считается корректным (valid), когда оно было правильно принято в соответствии с протоколом CAN (не было ошибки до последнего бита, но с одним битом в поле EOF), и при этом успешно прошло фильтрацию по идентификатору (см. далее секцию «Фильтрация по идентификатору»).

bxCAN Receive FIFO states fig341

Рис. 341. Состояния приемного FIFO.

Обслуживание FIFO. Начиная с состояния «пусто» (empty) FIFO, первое корректно принятое сообщение сохраняется в FIFO, который переходит в состояние pending_1 (ожидает обработки одно принятое сообщение). Аппаратура сигнализирует об этом событии установкой бит FMP[1:0] в регистре CAN_RFR в значение 01b. Сообщение становится доступным в выходном mailbox FIFO. Программа считывает текущий mailbox и освобождает его установкой бита RFOM в регистре CAN_RFR. После этого FIFO снова становится пустым. Если в этот момент было принято новое корректное сообщение, то FIFO остается в состоянии pending_1, и новое сообщение доступно в выходном mailbox FIFO.

Если программа не освободила mailbox, то следующее корректно принятое сообщение будет сохранено в FIFO, который перейдет в состояние pending_2 (FMP[1:0] = 10b). Процесс сохранения сообщений в FIFO продолжится вплоть до перехода FIFO в состояние pending_3 (FMP[1:0] = 11b). В этой точке программа должна освободить выходной mailbox FIFO установкой бита RFOM, чтобы можно было освободить mailbox для сохранения нового корректного сообщения. Иначе следующее корректное сообщение будет потеряно. См. также раздел «Хранилище сообщений».

Overrun. Как только FIFO перешел в состояние pending_3 (т. е. все mailbox заполнены), следующее поступившее сообщение приведет к переполнению приема (overrun), и сообщение будет потеряно. Аппаратура сигнализирует о состоянии overrun установкой бита FOVR в регистре CAN_RFR. Какое сообщение потеряно, зависит от конфигурации FIFO:

• Если функция блокировки FIFO (FIFO lock) запрещена (очищен бит RFLM в регистре CAN_MCR), то последнее сохраненное сообщение в FIFO будет перезаписано новым поступившим сообщением. В этом случае последние поступившие (самые свежие) сообщения будут всегда доступны для приложения.
• Если функция блокировки FIFO разрешена (установлен бит RFLM в регистре CAN_MCR), то самое свежее поступившее сообщение будет отброшено, и для программы будут всегда доступны 3 самые старые не обработанные сообщения FIFO.

Прерывания приема. Как только сообщение было сохранено в FIFO, обновятся биты FMP[1:0] и генерируется запрос прерывания, если установлен бит FMPIE в регистре разрешения прерываний CAN_IER.

Когда FIFO становится заполненным (т. е. сохранено третье сообщение), установится бит FULL в регистре CAN_RFR, и будет сгенерировано прерывание, если установлен бит FFIE в регистре разрешения прерываний CAN_IER.

При переполнении приема (overrun condition) установится бит FOVR, и будет сгенерировано прерывание, если установлен бит FOVIE в регистре разрешения прерываний CAN_IER.

[Фильтрация по идентификатору]

В протоколе CAN идентификатор сообщения не связан с адресом узла, но связан с содержимым сообщения. Следовательно, передатчик передает свое сообщение всем приемникам. Во время приема сообщения принимающий узел решает — в зависимости от значения идентификатора — нуждается программа в этом сообщении, или нет. Если сообщение нужное, то оно копируется в SRAM. Если нет, то сообщение будет отброшено без какого-либо вмешательства со стороны программы.

Чтобы удовлетворить этому требованию, контроллер bxCAN предоставляет для приложения 28 конфигурируемых и масштабируемых банков фильтра (27 .. 0). Эта аппаратная фильтрация сохраняет процессорное время CPU, которое иначе тратилось бы, если фильтрация была реализована программно. Каждый банк фильтра x состоит из двух 32-битных регистра CAN_FxR0 и CAN_FxR1.

Масштабируемая ширина (scale). Чтобы оптимизировать и адаптировать фильтрацию к требованиям приложения, каждый банк фильтра может масштабироваться независимо. В зависимости от масштаба фильтра банк фильтра предоставляет (см. рис. 342):

• Один 32-битный фильтр для бит STDID[10:0], EXTID[17:0], IDE и RTR.
• Два 16-битных фильтра для бит STDID[10:0], RTR, IDE и EXTID[17:15].

Кроме того, фильтры могут быть сконфигурированы в режиме маски (mask mode) или в режиме списка идентификаторов (identifier list mode).

Mask mode. В режиме маски регистры идентификатора связаны с регистрами маски, указывающими, какие биты в идентификаторе должны совпадать (must match), а какие могут быть любыми (don’t care).

Identifier list mode. В режиме списка идентификаторов регистры маски используются как регистры идентификатора. Таким образом, вместо определения идентификатора и маски, указываются 2 идентификатора, удваивая количество одиночных идентификаторов. Все биты приходящего идентификатора должны совпадать с битами, указанными в регистрах фильтра.

Конфигурация scale и mode банка фильтра. Банки фильтра конфигурируются соответствующим регистром CAN_FMR. Для конфигурирования банка фильтра он должен быть деактивирован очисткой бита FACT в регистре CAN_FAR. Параметр scale фильтра конфигурируется соответствующим битом FSCx регистра CAN_FS1R, см. рис. 342. Режим маски или режим списка идентификаторов для соответствующих регистров Mask/Identifier конфигурируется битами FBMx в регистре CAN_FMR.

Для фильтрации группы идентификаторов сконфигурируйте регистры Mask/Identifier в режиме маски.

Для выбора одиночных идентификаторов сконфигурируйте регистры Mask/Identifier в режиме списка идентификаторов.

Фильтры, не используемые приложением, должны быть оставлены деактивированными.

Каждый фильтр в банке фильтра пронумерован (номер называется Filter Number) от 0 до максимума, в зависимости от mode и scale каждого банка фильтра.

Конфигурация фильтра показана на рис. 342.

bxCAN filter bank scale configuration fig342

Рис. 342. Конфигурация масштабирования (scale) банков фильтра — организация регистров.

Примечания:

x = номеру банка фильтра.
ID = идентификатору.
(1) Эти биты находятся в регистре CAN_FS1R.
(2) Эти биты находятся в регистре CAN_FM1R.

Индекс совпадения фильтра. Как только сообщение было принято в FIFO, оно становится доступным для приложения. Обычно данные приложения копируются в ячейки SRAM. Чтобы копировать данные в правильное место, приложение должно идентифицировать данные по идентификатору. Чтобы упросить доступ к ячейкам SRAM принятых сообщений, контроллер CAN предоставляет индекс совпадения фильтра (Filter Match Index).

Этот индекс сохраняется в mailbox вместе с сообщением, в соответствии с правилами приоритета фильтра. Таким образом, каждое принятое сообщение связывает с индексом совпадения фильтра.

Индекс Filter Match может быть задействован двумя способами:

• Сравнение индекса Filter Match со списком ожидаемых значений.
• Использование индекса Filter Match как индекса в массиве для доступа к месту нахождения данных.

Для не маскируемых фильтров программа больше не должна сравнивать идентификатор.

Если фильтр маскирован, то программа ограничивает сравнение только маскированными битами.

Значение индекса номера фильтра не учитывает состояние активации банков фильтра. Дополнительно используются две независимые схемы нумерации, по одной для каждого FIFO. Пример см. на рис. 343.

bxCAN example filter numbering fig343

Рис. 343. Пример нумерации фильтров. ID означает идентификатор.

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

• 32-битный фильтр имеет приоритет над 16-битным фильтром.
• Для фильтров с одинаковым scale, приоритет предоставляется режиму списка идентификаторов (Identifier List mode) над режимом маски идентификаторов (Identifier Mask mode).
• Для фильтров с одинаковым scale и mode, приоритет дается по номеру фильтра (чем меньше номер, тем выше приоритет).

bxCAN filtering mechanism example fig344

Рис. 344. Пример механизма фильтрации. Три банка фильтра сконфигурированы в 32-битном Unidentified List mode, остальные в 32-битном Identifier Mask mode.

На рис. 344 выше показан пример принципа фильтрации bxCAN. На приеме сообщения идентификатор сначала сравнивается с фильтрами, сконфигурированными в identifier list mode. Если было совпадение, то сообщение сохранятся в связанном FIFO и индекс совпавшего фильтра сохраняется в Filter Match Index (FMI). Как показано в примере, идентификатор совпал с Identifier #2, так что в FIFO будет сохранено содержимое сообщения и FMI 2.

Если не было совпадения, пришедший идентификатор сравнивается с фильтрами, сконфигурированными в mask mode.

Если идентификатор не совпал ни с одним из идентификаторов, сконфигурированным в фильтрах, то сообщение отбрасывается аппаратно, никак не влияя на программу.

[Хранилище сообщений]

Интерфейс между программой и аппаратурой для сообщений CAN реализован через ящики (mailboxes). Mailbox содержит всю информацию, относящуюся к сообщению: идентификатор, данные, управление, статус и метку времени.

Transmit mailbox. Программа настраивает сообщение для передачи в пустом передающем mailbox. Статус передачи показывается аппаратурой в регистре CAN_TSR.

Таблица 182. Отображение ящиков передачи (TX mailbox) передачи.

Смещение для базового адреса TX mailbox (в байтах) Имя регистра
0 CAN_TIxR
4 CAN_TDTxR
8 CAN_TDLxR
12 CAN_TDHxR

Receive mailbox. Когда было принято сообщение, оно становится доступным в выходном mailbox FIFO. Когда программа обработала сообщение (т. е. прочитала его), она должна освободить выходной mailbox FIFO с помощью бита RFOM в регистре CAN_RFR, чтобы стало доступным для чтения следующее приходящее сообщение. Индекс совпавшего фильтра сохраняется в поле MFMI регистра CAN_RDTxR. 16-битное значение метки времени (time stamp) сохраняется в поле TIME[15:0] регистра CAN_RDTxR.

Таблица 183. Отображение ящиков (RX mailbox) приема.

Смещение для базового адреса RX mailbox (в байтах) Имя регистра
0 CAN_RIxR
4 CAN_RDTxR
8 CAN_RDLxR
12 CAN_RDHxR

[Обработка ошибок]

Обработка ошибок (error management), как это описано в протоколе CAN, осуществляется полностью аппаратно, с использованием счетчика ошибок передачи Transmit Error Counter (значение TEC в регистре CAN_ESR) и счетчика ошибок приема Receive Error Counter (значение REC в регистре CAN_ESR), которые инкрементируются по мере появления событий ошибки. Более подробно обслуживание TEC и REC описано в стандарте CAN.

Оба счетчика TEC и REC могут быть прочитаны программой, чтобы определить стабильность сети CAN. Кроме того, аппаратура CAN предоставляет подробную информацию о текущем статусе ошибки в регистре CAN_ESR. Через регистр CAN_IER (бит ERRIE и т. п.), программа может очень гибко сконфигурировать прерывание при детектировании ошибки.

bxCAN error state diagram fig345

Рис. 345. Диаграмма состояний ошибки CAN.

Восстановление из Bus-Off. Состояние Bus-Off (отключение от шины) достигается, когда TEC становится больше 255, это состояние индицируется битом BOFF регистра CAN_ESR. В состоянии Bus-Off блок bxCAN больше не может передавать и принимать сообщения.

В зависимости от бита ABOM в регистре CAN_MCR, блок bxCAN будет восстанавливаться из Bus-Off (переходить в состояние error active) либо автоматически, либо по запросу программы. Однако в обоих случаях bxCAN будет ждать как минимум последовательности восстановления (recovery sequence), описанную в стандарте CAN (128 случаев появления 11 следующих друг за другом рецессивных бит, обнаруженных на CANRX).

Если установлен ABOM, то bxCAN автоматически начнет последовательность восстановления после того, как произошел вход в состояние Bus-Off. Если ABOM очищен, то программа должна инициировать последовательность восстановления путем запроса к bxCAN на вход в режим инициализации и на выход из него.

Примечание: в режиме инициализации bxCAN не мониторит сигнал CANRX, поэтому не может завершить последовательность восстановления. Для восстановления bxCAN должен быть в normal mode.

[Интервалы бит (bit timing)]

Логика тайминга бита мониторит последовательную линию шины и выполняет оцифровку сигнала с подстройкой точки выборки. Это делается синхронизацией по перепаду начального бита, и повторной синхронизацией на последующих перепадах.

Эта операция может быть объяснена простым разделением номинального времени бита на 3 сегмента следующим образом:

• Сегмент синхронизации (SYNC_SEG): во время этого интервала времени ожидается изменение бит. Величина этого сегмента фиксируется на одном кванте времени (time quantum): 1 x tq.
• Сегмент бита 1 (Bit segment 1, BS1): определяет положение точки выборки уровня сигнала (sample point). Стандарт включает сюда интервалы PROP_SEG (сегмент распространения) и PHASE_SEG1 (сегмент фазы 1). Длительности этих интервалов программируются между 1 и 16 time quanta, однако они могут быть автоматически увеличены для компенсации положительного дрейфа фазы из-за разницы частот тактов различных узлов в сети.
• Сегмент бита 2 (Bit segment 2, BS2): определяет положение точки передачи (transmit point). Представлен в стандарте CAN интервалом PHASE_SEG2 (сегмент фазы 2). Его длительность программируется в диапазоне от 1 до 8 time quanta, однако этот интервал может быть автоматически сокращен для компенсации отрицательных смещений фазы.

Параметр ширины скачка ресинхронизации (resynchronization Jump Width, SJW) определяет верхнюю границу величины удлинения или укорочения сегментов бита. Программируется в диапазоне от 1 до 4 time quanta.

Достоверный перепад детектируется как первый переход в интервале бита от доминантного к рецессивному уровню шины при условии, что контролер сам не передает рецессивный бит.

Если достоверный перепад был детектирован в BS1 вместо SYNC_SEG, BS1 расширяется на интервал SJW, чтобы точка выборки была задержана. Соответственно, если достоверный перепад был определен в интервале BS2 вместо SYNC_SEG, интервал BS2 укорачивается на SJW, чтобы точка передачи оказалась раньше.

В качестве защиты от ошибок программирования конфигурация Bit Timing Register (CAN_BTR) возможна только когда устройство находится в режиме Standby.

Примечание: подробное описание тайминга бит CAN и механизма ресинхронизации см. в стандарте ISO 11898.

bxCAN Bit Timing fig346

Рис. 346. Интервалы бит.

                  1
BaudRate = —————-
            NominalBitTime

NominalBitTime = 1 x tq + tBS1 + tBS2

Здесь:

tBS1 = tq x (TS1[3:0] + 1),
tBS2 = tq x (TS2[2:0] + 1),
tq = (BRP[9:0] + 1) x tPCLK

tq обозначает Time quantum.

tPCLK = период тактов APB, BRP[9:0], TS1[3:0] и TS2[2:0] определены в регистре CAN_BTR.

bxCAN CAN frames fig347

Рис. 347. Фреймы CAN.

Примечания:

0 ≤ N ≤ 8
SOF = Start Of Frame (начало фрейма).
ID = Identifier (идентификатор).
RTR = Remote Transmission Request (запрос на передачу от удаленного сетевого узла).
IDE = Identifier Extension Bit (бит расширения идентификатора).
r0 = Reserved Bit (зарезервированный бит).
DLC = Data Length Code (код длины данных).
CRC = Cyclic Redundancy Code (контрольная сумма).
Error flag: флаг ошибки, 6 доминантных бит, если на узле активная ошибка, иначе 6 рецессивных бит.
Suspend transmission: приостановка передачи, применимо только к узлам с пассивной ошибкой.
EOF = End of Frame (конец фрейма).
ACK = Acknowledge bit (бит подтверждения).
Ctrl = Control (управление).

[Прерывания bxCAN]

Для bxCAN выделено 4 вектора прерывания. Каждый источник прерывания может быть независимо разрешен или запрещен программированием регистра разрешения прерываний CAN (CAN Interrupt Enable Register, CAN_IER).

bxCAN event flags and interrupt generation fig348

Рис. 348. Флаги событий и генерация прерываний.

• Прерывание передачи (transmit interrupt) может генерироваться от следующих событий:
   – Transmit mailbox 0 стал пустым, установился бит RQCP0 в регистре CAN_TSR.
   – Transmit mailbox 1 стал пустым, установился бит RQCP1 в регистре CAN_TSR.
   – Transmit mailbox 2 стал пустым, установился бит RQCP2 в регистре CAN_TSR.
• Прерывание FIFO0 может генерироваться от следующих событий:
   – Прием нового сообщения, биты FMP0 в регистре CAN_RF0R не равны 00b.
   – Состояние заполненности FIFO0, установлен бит FULL0 в регистре CAN_RF0R.
   – Состояние переполнения FIFO0 (overrun), установлен бит FOVR0 в регистре CAN_RF0R.
• Прерывание FIFO 1 может генерироваться от следующих событий:
   – Прием нового сообщения, биты FMP1 в регистре CAN_RF1R не равны 00b.
   – Состояние заполненности FIFO1, установлен бит FULL1 в регистре CAN_RF1R.
   – Состояние переполнения FIFO1 (overrun), установлен бит FOVR1 в регистре CAN_RF1R.
• Прерывание ошибки и изменения статуса может быть сгенерировано следующими событиями:
   – Произошла ошибка (Error condition), подробную информацию о характере ошибки можно получить в регистре статуса ошибки (CAN Error Status register, CAN_ESR).
   – Пробуждение (Wakeup condition), на сигнале приема CAN Rx обнаружено начало фрейма (SOF).
   – Вход в режим сна (Sleep mode).

[Регистры CAN]

К регистрам периферийного устройства CAN нужно обращаться как к словам (32-битный доступ). Смещение адреса указано относительно базового адреса CAN1_BASE или CAN2_BASE (можно узнать в файле stm32f407xx.h). Для адресного пространства CAN1 зарезервированы адреса 0x40006400 .. 0x400067FF (базовый адрес 0x40006400). Для адресного пространства CAN2 зарезервированы адреса 0x40006800 .. 0x40006BFF (базовый адрес 0x40006800). Регистры со смещениями от 0x200 до 0x31C имеются только у CAN1.

bxCAN register map and reset values tbl184

В описании функций регистров используются следующие сокращения:

read/write (rw) Программа может читать и записывать эти биты.

read-only (r) Программа может только читать эти биты.

write-only (w) Программа может только записывать в этот бит. Чтение бита вернет значение сброса.

read/clear (rc_w1) Программа может прочитать бит, а также сбросить его путем записью 1. Запись 0 не дает никакого эффекта.

read/clear (rc_w0) Программа может прочитать бит, а также сбросить его путем записью 0. Запись 1 не дает никакого эффекта.

read/clear by read (rc_r) Программа может прочитать этот бит. Чтение этого бита автоматически сбросит его в 0. Запись 0 в бит не дает никакого эффекта.

read/set (rs) Программа может прочитать, а также установить этот бит. Запись 0 в бит не дает никакого эффекта.

read-only write trigger (rt_w) Программа может прочитать этот бит. Запись 0 или 1 вызовет появление события (триггер), но не окажет никакого влияния на значение бита.

toggle (t) Программа может только переключить этот бит записью 1. Запись 0 не дает никакого эффекта.

Reserved (Res.) Зарезервированный бит, его значение должно сохраняться на значении сброса.

Защита доступа к регистрам. Ошибочный доступ к определенным конфигурационным регистрам может привести к тому, что аппаратура временно нарушит работу всей сети CAN. Таким образом, регистр CAN_BTR может быть модифицирован программой только когда аппаратура CAN находится в режиме инициализации (initialization mode).

Хотя передача некорректных данных не приведет к проблемам на сетевом уровне CAN, это может сильно помешать работе приложения. Передающий mailbox может быть изменен программой только когда mailbox в состоянии empty, см. рис. 340.

Значения фильтра могут быть изменены либо деактивацией банков фильтра, либо установкой бита FINIT. Кроме того, модификация конфигурации фильтра (scale, mode и назначение FIFO) в регистрах CAN_FMxR, CAN_FSxR и CAN_FFAR может быть только когда установлен режим инициализации фильтра (filter initialization mode, FINIT=1) в регистре CAN_FMR.

[Регистры управления и состояния]

Смещение адреса: 0x00
Значение после сброса: 0x00010002

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано DBF
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
RESET
rs
зарезервировано TTCM
rw
ABOM
rw
AWUM
rw
NART
rw
RFLM
rw
TXFP
rw
SLEEP
rw
INRQ
rw

Биты 31:17 зарезервированы, и должны находиться в состоянии сброса (все нули).

DBF (бит 16): DeBug Freeze, остановка CAN во время отладки.

0: во время отладки CAN работает.
1: прием/передача CAN во время отладки замораживается. Стеки Reception FIFO все еще могут нормально управляться и к ним может быть осуществлен доступ.

RESET (бит 15): главный программный сброс (bxCAN software master reset).

0: нормальное функционирование.
1: принудительный сброс bxCAN, после сброса активируется Sleep mode (биты FMP и регистр CAN_MCR инициализируются своими значениями после сброса). Этот бит автоматически сбросится в 0.

Биты 14:8 зарезервированы, и должны находиться в состоянии сброса (все нули).

TTCM (бит 7): Time Triggered Communication Mode, режим обмена, срабатывающий по времени.

0: режим Time Triggered Communication запрещен.
1: режим Time Triggered Communication разрешен.

ABOM (бит 6): Automatic Bus-Off Management, автоматическое управление состоянием отключения от шины. Этот бит управляет поведением аппаратуры CAN для выхода из состояния Bus-Off.

0: выход из Bus-Off осуществляется по запросу программы, как только произойдет 128 случаев появления 11 рецессивных бит, и программа сначала должна установить и очистить бит INRQ регистра CAN_MCR.
1: состояние Bus-Off будет оставлено автоматически под управлением аппаратуры, как только будет обнаружено 128 случаев появления 11 рецессивных бит.

AWUM (бит 5): Automatic WakeUp Mode, режим автоматического пробуждения. Этот бит управляет поведением аппаратуры CAN на приеме сообщения во время Sleep mode.

0: из режима сна произойдет выход по запросу программы путем очистки бита SLEEP регистра CAN_MCR.
1: из режима сна выход будет произведен автоматически, под управлением аппаратуры, когда будет детектировано сообщение CAN. Бит SLEEP регистра CAN_MCR и бит SLAK регистра CAN_MSR очистятся аппаратно.

NART (бит 4): No Automatic ReTransmission, без автоматической повторной передачи.

0: аппаратура CAN будет автоматически запускать повтор передачи, пока сообщение не будет успешно передано в соответствии со стандартом CAN.
1: сообщение будет отправлено только однократно, независимо от результата передачи (успешно или нет из-за ошибки или потери арбитража).

RFLM (бит 3): Receive FIFO Locked Mode, режим блокировки приемного FIFO.

0: Receive FIFO не блокируется при переполнении (overrun). Как только приемный FIFO заполнится, следующее поступившее сообщение перезапишет предыдущее.
1: Receive FIFO блокируется на перезапись при переполнении. Как только приемный FIFO заполнится, следующее пришедшее сообщение будет отброшено и соответственно потеряно.

TXFP (бит 2): Transmit FIFO Priority, приоритет FIFO передачи. Этот бит управляет порядком передачи сообщений, когда одновременно ожидают передачи несколько mailbox.

0: приоритет на передачу берется по идентификатору сообщения (чем меньше идентификатор, тем приоритет выше).
1: приоритет на передачу берется по порядку запроса (хронологически: чем раньше mailbox был поставлен на ожидание передачи, тем раньше произойдет его передача).

SLEEP (бит 1): запрос на вход режим сна (Sleep Mode). Этот бит устанавливается программой, чтобы запросить у аппаратуры CAN её вход в Sleep Mode. В режим сна произойдет вход, как только будет завершена текущая активность CAN (передача или прием фрейма CAN). Этот бит очищается программой для выхода из режима сна. Этот бит очищается аппаратно, когда установлен бит AWUM и детектирован бит SOF в сигнале CAN Rx. Этот бит установится после сброса -аппаратура CAN изначально находится в Sleep mode.

INRQ (бит 0): INitialization ReQuest. Программа очищает этот бит для переключения в нормальный рабочий режим. Как только будет обнаружено 11 следующих друг за другом рецессивных бит на сигнале RX, аппаратура CAN синхронизирована и готова к передаче и приема. Аппаратура сигнализирует об этом событии очисткой бита INAK в регистре CAN_MSR.

Программа установит этот бит для запроса аппаратуре CAN войти в режим инициализации (initialization mode). Как только программа установит бит INRQ, аппаратура CAN подождет завершения текущей активности CAN (передача или прием) перед входом в initialization mode. Аппаратура сигнализирует об этом событии установкой бита INAK в регистре CAN_MSR.

Смещение адреса: 0x04
Значение после сброса: 0x00000C02

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано RX
r
SAMP
r
RXM
r
TXM
r
зарезервировано SLAKI
rc_w1
WKUI
rc_w1
ERRI
rc_w1
SLAK
r
INAK
r

Биты 31:12 зарезервированы, и должны находиться в состоянии сброса (все нули).

RX (бит 11): Сигнал приема CAN Rx. Мониторится актуальное значение вывода CAN_RX (как на обычной ножке GPIO).

SAMP (бит 10): последняя точка выборки (SAMple Point). Значение RX на последней точке выборки (текущее значение бита).

RXM (бит 9): Receive mode, режим приема. Аппаратура CAN сейчас работает как приемник.

TXM (бит 8): Transmit mode, режим передачи. Аппаратура CAN сейчас работает как передатчик.

Биты 7:5 зарезервированы, и должны находиться в состоянии сброса (все нули).

SLAKI (бит 4): SLeep AcKnowledge Interrupt, подтверждение прерывания входа в режим сна. Когда SLKIE=1, этот бит установится аппаратно для сигнализации, что bxCAN вошел в Sleep Mode. Когда бит SLAKI установлен, этот бит генерирует прерывание изменения состояния (status change interrupt), если установлен бит SLKIE в регистре CAN_IER. Этот бит очищается программно или аппаратно, когда очищен бит SLAK.

Примечание: когда SLKIE=0, опрос SLAKI невозможен. В этом случае можно опрашивать бит SLAK.

WKUI (бит 3): WaKeUP Interrupt, прерывание пробуждения. Этот бит установится аппаратно для сигнализации, когда был определен бит начала фрейма SOF и аппаратура CAN находилась в Sleep mode. Установка этого бита генерирует прерывание изменения статуса, если установлен бит WKUIE в регистре CAN_IER. Этот бит очищается программой.

ERRI (бит 2): ERRor Interrupt, прерывание ошибки. Этот бит установится аппаратно, когда был установлен CAN_ESR на детектирование ошибки, и разрешено соответствующее прерывание CAN_IER. Установка этого бита генерирует прерывание изменения статуса, если установлен бит ERRIE в регистре CAN_IER.

Бит ERRI очищается программой.

SLAK (бит 1): SLeep AcKnowledge, подтверждение входа в режим сна. Этот бит установится аппаратно, показывая тем самым программе, что аппаратура CAN находится теперь в Sleep mode. Этот бит подтверждает запрос на Sleep mode от программы (установка бита SLEEP в регистре CAN_MCR).

Бит SLAK очистится аппаратно, когда аппаратура CAN выйдет из Sleep mode (чтобы засинхронизироваться на шине CAN). Для синхронизации аппаратура отслеживает 11 следующих друг за другом рецессивных бита на сигнале CAN RX.

Примечание: процесс выхода из Sleep срабатывает, когда очищается бит SLEEP в регистре CAN_MCR. См. описание бита AWUM регистра CAN_MCR для получения подробной информации по очистке бита SLEEP.

INAK (бит 0): INitialization AcKnowledge, подтверждение режима инициализации. Этот бит установится аппаратно, показывая тем самым программе, что аппаратура CAN находится теперь в initialization mode. Этот бит подтверждает запрос на инициализацию от программы (установка бита INRQ в регистре CAN_MCR).

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

Смещение адреса: 0x08
Значение после сброса: 0x1С000000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
LOW2
r
LOW1
r
LOW0
r
TME2
r
TME1
r
TME0
r
CODE[1:0]
r
ABRQ2
rs
зарезервировано TERR2
rc_w1
ALST2
rc_w1
TXOK2
rc_w1
RQCP2
rc_w1
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
ABRQ1
rs
зарезервировано TERR1
rc_w1
ALST1
rc_w1
TXOK1
rc_w1
RQCP1
rc_w1
ABRQ0
rs
зарезервировано TERR0
rc_w1
ALST0
rc_w1
TXOK0
rc_w1
RQCP0
rc_w1

LOW2 (бит 31): LOWest priority flag for mailbox 2, самый низкий приоритет для ящика 2. Этот бит установится аппаратурой, когда больше одного mailbox ожидает передачи, и у mailbox 2 был самый низкий приоритет.

LOW1 (бит 30): LOWest priority flag for mailbox 1, самый низкий приоритет для ящика 1. Этот бит установится аппаратурой, когда больше одного mailbox ожидает передачи, и у mailbox 1 был самый низкий приоритет.

LOW0 (бит 29): LOWest priority flag for mailbox 0, самый низкий приоритет для ящика 0. Этот бит установится аппаратурой, когда больше одного mailbox ожидает передачи, и у mailbox 0 был самый низкий приоритет.

Примечание: биты LOW[2:0] установятся в 0, когда только один mailbox находится в ожидании (pending) передачи.

TME2 (бит 28): Transmit Mailbox 2 Empty, передающий ящик 2 пуст. Этот бит установится аппаратурой, когда нет ожидающего запроса на передачу для mailbox 2.

TME1 (бит 27): Transmit Mailbox 1 Empty, передающий ящик 1 пуст. Этот бит установится аппаратурой, когда нет ожидающего запроса на передачу для mailbox 1.

TME0 (бит 26): Transmit Mailbox 0 Empty, передающий ящик 0 пуст. Этот бит установится аппаратурой, когда нет ожидающего запроса на передачу для mailbox 0.

CODE[1:0] (биты 25:24): Mailbox code, код ящика. В случае, когда как минимум один передающий mailbox свободен, значение кода равно номеру следующего свободного ящика передачи.

В случае, когда все передающие ящики заняты ожиданием передачи, значение кода равно номеру передающего mailbox с самым низким приоритетом.

ABRQ2 (бит 23): ABort ReQuest for mailbox 2, запрос на обрыв передачи ящика 2. Устанавливается программой, чтобы оборвать запрос передачи для соответствующего mailbox. Очищается аппаратно, когда mailbox становится пустым.

Установка этого бита не дает никакого эффекта, когда mailbox не ожидает передачи своего сообщения.

Биты 22:20 зарезервированы, и должны находиться в состоянии сброса (все нули).

TERR2 (бит 19): Transmission ERRor of mailbox 2, ошибка передачи ящика 2. Этот бит установится, когда предыдущая передача потерпела неудачу из-за ошибки.

ALST2 (бит 18): Arbitration lost for mailbox 2, потеря арбитража на ящике 2. Этот бит установится, когда предыдущая передача потерпела неудачу из-за потери арбитража.

TXOK2 (бит 17): Transmission OK of mailbox 2, успешная передача на ящике 2. Аппаратура обновляет этот бит при каждой попытке передачи.

0: предыдущая передача потерпела неудачу.
1: предыдущая передача закончилась успешно.

Этот бит установится аппаратно, когда запрос на передачу ящика 2 был успешно выполнен. См. рис. 340.

RQCP2 (бит 16): Request completed mailbox 2, завершен запрос ящика 2. Установится аппаратурой, когда был выполнен последний запрос (transmit или abort).

Очищается программой путем записи лог. 1, или аппаратурой при запросе на передачу (установка бита TXRQ2 в регистре CAN_TMID2R).
Очистка этого бита очистит все биты статуса (TXOK2, ALST2 и TERR2) для Mailbox 2.

ABRQ1 (бит 15): ABort ReQuest for mailbox 1, запрос на обрыв передачи ящика 1. Устанавливается программой, чтобы оборвать запрос передачи для соответствующего mailbox. Очищается аппаратно, когда mailbox становится пустым.

Установка этого бита не дает никакого эффекта, когда mailbox не ожидает передачи своего сообщения.

Биты 14:12 зарезервированы, и должны находиться в состоянии сброса (все нули).

TERR1 (бит 11): Transmission ERRor of mailbox 1, ошибка передачи ящика 1. Этот бит установится, когда предыдущая передача потерпела неудачу из-за ошибки.

ALST1 (бит 10): Arbitration lost for mailbox 1, потеря арбитража на ящике 1. Этот бит установится, когда предыдущая передача потерпела неудачу из-за потери арбитража.

TXOK1 (бит 9): Transmission OK of mailbox 1, успешная передача на ящике 1. Аппаратура обновляет этот бит при каждой попытке передачи.

0: предыдущая передача потерпела неудачу.
1: предыдущая передача закончилась успешно.

Этот бит установится аппаратно, когда запрос на передачу ящика 1 был успешно выполнен. См. рис. 340.

RQCP1 (бит 8): Request completed mailbox 1, завершен запрос ящика 1. Установится аппаратурой, когда был выполнен последний запрос (transmit или abort).

Очищается программой путем записи лог. 1, или аппаратурой при запросе на передачу (установка бита TXRQ1 в регистре CAN_TMID1R).

Очистка этого бита очистит все биты статуса (TXOK1, ALST1 и TERR1) для Mailbox 1.

ABRQ0 (бит 7): ABort ReQuest for mailbox 0, запрос на обрыв передачи ящика 0. Устанавливается программой, чтобы оборвать запрос передачи для соответствующего mailbox. Очищается аппаратно, когда mailbox становится пустым.

Установка этого бита не дает никакого эффекта, когда mailbox не ожидает передачи своего сообщения.

Биты 6:4 зарезервированы, и должны находиться в состоянии сброса (все нули).

TERR0 (бит 3): Transmission ERRor of mailbox 0, ошибка передачи ящика 0. Этот бит установится, когда предыдущая передача потерпела неудачу из-за ошибки.

ALST0 (бит 2): Arbitration lost for mailbox 0, потеря арбитража на ящике 0. Этот бит установится, когда предыдущая передача потерпела неудачу из-за потери арбитража.

TXOK0 (бит 1): Transmission OK of mailbox 0, успешная передача на ящике 0. Аппаратура обновляет этот бит при каждой попытке передачи.

0: предыдущая передача потерпела неудачу.
1: предыдущая передача закончилась успешно.

Этот бит установится аппаратно, когда запрос на передачу ящика 0 был успешно выполнен. См. рис. 340.

RQCP0 (бит 0): Request completed mailbox 0, завершен запрос ящика 0. Установится аппаратурой, когда был выполнен последний запрос (transmit или abort).

Очищается программой путем записи лог. 1, или аппаратурой при запросе на передачу (установка бита TXRQ0 в регистре CAN_TMID0R).
Очистка этого бита очистит все биты статуса (TXOK0, ALST0 и TERR0) для Mailbox 0.

Смещение адреса: 0x0C
Значение после сброса: 0x00000000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано RFOM0
rs
FOVR0
rc_w1
FULL0
rc_w1
зарез. FMP0[1:0]
r

Биты 31:6 зарезервированы, и должны находиться в состоянии сброса (все нули).

RFOM0 (бит 5): Release FIFO 0 output mailbox, освободился выходной ящик стека FIFO0. Устанавливается программой, чтобы освободить выходной mailbox FIFO. Выходной mailbox может быть освобожден только когда как минимум одно сообщение FIFO ожидает (pending) обработки. Установка этого бита не дает никакого эффекта, когда FIFO пуст. Если как минимум 2 сообщения FIFO ожидают обработки, программа должна освободить выходной mailbox, чтобы получить доступ к следующему сообщению.

Очищается аппаратно, когда выходной mailbox был освобожден.

FOVR0 (бит 4): FIFO 0 OVerRun, переполнение FIFO0 приема. Этот бит устанавливается аппаратно, когда новое сообщение было принято и прошло фильтр, и FIFO0 при этом был заполнен.

Этот бит очищается программно.

FULL0 (бит 3): FIFO 0 full, FIFO0 приема заполнен. Установится аппаратно, когда в FIFO0 сохранено 3 сообщения.

Этот бит очищается программно.

Бит 2 зарезервирован, и должен оставаться в состоянии сброса (0).

FMP0[1:0] (биты 1:0): FIFO 0 Message Pending. Эти биты показывают, сколько сообщений ожидают обработки в FIFO приема. FMP увеличивается каждый раз, когда аппаратура сохраняет новое сообщение в FIFO. FMP уменьшается каждый раз, когда программа освобождает выходной mailbox установкой бита RFOM0.

Смещение адреса: 0x10
Значение после сброса: 0x00000000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано RFOM1
rs
FOVR1
rc_w1
FULL1
rc_w1
зарез. FMP1[1:0]
r

Биты 31:6 зарезервированы, и должны находиться в состоянии сброса (все нули).

RFOM1 (бит 5): Release FIFO 1 output mailbox, освободился выходной ящик стека FIFO1. Устанавливается программой, чтобы освободить выходной mailbox FIFO. Выходной mailbox может быть освобожден только когда как минимум одно сообщение FIFO ожидает (pending) обработки. Установка этого бита не дает никакого эффекта, когда FIFO пуст. Если как минимум 2 сообщения FIFO ожидают обработки, программа должна освободить выходной mailbox, чтобы получить доступ к следующему сообщению.

Очищается аппаратно, когда выходной mailbox был освобожден.

FOVR1 (бит 4): FIFO 1 OVerRun, переполнение FIFO1 приема. Этот бит устанавливается аппаратно, когда новое сообщение было принято и прошло фильтр, и FIFO1 при этом был заполнен.

Этот бит очищается программно.

FULL1 (бит 3): FIFO 1 full, FIFO1 приема заполнен. Установится аппаратно, когда в FIFO1 сохранено 3 сообщения.

Этот бит очищается программно.

Бит 2 зарезервирован, и должен оставаться в состоянии сброса (0).

FMP1[1:0] (биты 1:0): FIFO 1 Message Pending. Эти биты показывают, сколько сообщений ожидают обработки в FIFO приема. FMP увеличивается каждый раз, когда аппаратура сохраняет новое сообщение в FIFO. FMP уменьшается каждый раз, когда программа освобождает выходной mailbox установкой бита RFOM1.

Смещение адреса: 0x14
Значение после сброса: 0x00000000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано SLKIE
rw
WKUIE
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
ERRIE
rw
зарезервировано LECIE
rw
BOFIE
rw
EPVIE
rw
EWGIE
rw
зарез. FOVIE1
rw
FFIE1
rw
FMPIE1
rw
FOVIE0
rw
FFIE0
rw
FMPIE0
rw
TMEIE
rw

Биты 31:18 зарезервированы, и должны находиться в состоянии сброса (все нули).

SLKIE (бит 17): Sleep interrupt enable, разрешение прерывания при входе bxCAN в режим сна.

0: нет прерывания, когда установится бит SLAKI.
1: произойдет прерывание, когда установится бит SLAKI.

WKUIE (бит 16): WaKeUp Interrupt Enable, разрешение прерывания пробуждения.

0: нет прерывания, когда установится бит WKUI.
1: произойдет прерывание, когда установится бит WKUI.

ERRIE (бит 15): ERRor Interrupt Enable, разрешение прерывания ошибки.

0: не будет сгенерировано прерывание, когда событие ошибки ожидает обработки в регистре CAN_ESR.
1: будет сгенерировано прерывание, когда событие ошибки ожидает обработки в регистре CAN_ESR.

Биты 14:12 зарезервированы, и должны находиться в состоянии сброса (все нули).

LECIE (бит 11): Last Error Code Interrupt Enable, разрешение прерывания от последнего кода ошибки.

0: бит ERRI не будет установлен, когда в LEC[2:0] аппаратура установит код детектированной ошибки.
1: бит ERRI будет установлен, когда в LEC[2:0] аппаратура установит код детектированной ошибки.

BOFIE (бит 10): Bus-OFf Interrupt Enable, разрешение прерывания, когда появляется состояние отключения от шины.

0: бит ERRI не установится, когда установился BOFF.
1: бит ERRI установится, когда установился BOFF.

EPVIE (бит 9): Error PassiVe Interrupt Enable, разрешение прерывания, когда появляется состояние пассивной ошибки.

0: бит ERRI не установится, когда установился бит EPVF.
1: бит ERRI установится, когда установился бит EPVF.

EWGIE (бит 8): Error warning interrupt enable, разрешение прерывания предупреждения ошибки.

0: бит ERRI не установится, когда установился бит EWGF.
1: бит ERRI установится, когда установился бит EWGF.

Бит 7 зарезервирован, и должен оставаться в состоянии сброса (0).

FOVIE1 (бит 6): FIFO1 OVerrun Interrupt Enable, разрешение прерывания при переполнении FIFO1.

0: нет прерывания, когда установлен FOVR1.
1: сгенерируется прерывание, когда установлен FOVR1.

FFIE1 (бит 5): FIFO1 Full Interrupt Enable, разрешение прерывания при заполнении стека приема FIFO1.

0: без прерывания, когда установится бит FULL1.
1: сгенерируется прерывание, когда установлен FULL1.

FMPIE1 (бит 4): FIFO1 Message Pending Interrupt Enable, разрешение прерывания, когда в стеке приема FIFO1 как минимум одно сообщение ожидает обработки.

0: не будет сгенерировано прерывание, когда состояние бит FMP1[1:0] изменится на ненулевое (станет не 00b).
1: сгенерируется прерывание, когда состояние бит FMP1[1:0] не 00b.

FOVIE0 (бит 3): FIFO0 OVerrun Interrupt Enable, разрешение прерывания при переполнении FIFO0.

0: нет прерывания, когда установлен FOVR0.
1: сгенерируется прерывание, когда установлен FOVR0.

FFIE0 (бит 2): FIFO0 Full Interrupt Enable, разрешение прерывания при заполнении стека приема FIFO0.

0: без прерывания, когда установится бит FULL0.
1: сгенерируется прерывание, когда установлен FULL0.

FMPIE0 (бит 1): FIFO0 Message Pending Interrupt Enable, разрешение прерывания, когда в стеке приема FIFO0 как минимум одно сообщение ожидает обработки.

0: не будет сгенерировано прерывание, когда состояние бит FMP0[1:0] изменится на ненулевое (станет не 00b).
1: сгенерируется прерывание, когда состояние бит FMP0[1:0] не 00b.

TMEIE (бит 0): Transmit Mailbox Empty Interrupt Enable, разрешение прерывания при опустошении передающего mailbox.

0: не будет сгенерировано прерывание, когда установится бит RQCPx.
1: сгенерируется прерывание, когда установится бит RQCPx.

Смещение адреса: 0x18
Значение после сброса: 0x00000000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
REC[7:0]
r
TEC[7:0]
r
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано LEC[2:0]
rw
зарез. BOFF
r
EPVF
r
EWGF
r

REC[7:0] (биты 31:24): Receive Error Counter, счетчик ошибок приема. Составная часть реализации механизма обработки отказов на шине (fault confinement mechanism) протокола CAN. В случае ошибки приема этот счетчик увеличивается на 1 или на 8, в зависимости от события ошибки, как это определено стандартом CAN. После каждого успешного приема этот счетчик декрементируется на 1, или сбрасывается в 120, если его значение было выше 128. Когда значение счетчика превысит 127, контроллер CAN войдет в состояние пассивной ошибки (error passive state).

TEC[7:0] (биты 23:16): младший байт 9-битного счетчика ошибок передачи (Transmit Error Counter). Составная часть реализации механизма обработки отказов на шине (fault confinement mechanism) протокола CAN.

Биты 15:7 зарезервированы, и должны находиться в состоянии сброса (все нули).

LEC[2:0] (биты 6:4): Last Error Code, код последней ошибки. Это поле устанавливается аппаратурой, и хранит код, соответствующий последней обнаруженной на шине CAN ошибки. Если сообщение успешно прошло транзакцию (приема или передачи) без ошибки, то это поле сбросится в 0.

Биты LEC[2:0] могут быть установлены в 0b111 программой. Они обновляются аппаратурой для индикации текущего статуса обмена по шине CAN.

000: No Error (нет ошибки).
001: Stuff Error (ошибка бит-стаффинга, т. е. вставки дополнительных бит для обеспечения перепадов синхронизации).
010: Form Error (ошибка формы сигнала).
011: Acknowledgment Error (ошибка подтверждения).
100: Bit recessive Error (ошибка рецессивного бита).
101: Bit dominant Error (ошибка доминантного бита).
110: CRC Error (ошибка контрольной суммы).
111: установлено из программы MCU.

Бит 3 зарезервирован, и должен оставаться в состоянии сброса (0).

BOFF (бит 2): флаг Bus-OFF. Этот бит установится аппаратурой, когда она входит в состояние отключения от шины (bus-off). Состояние bus-off происходит из-за переполнения счетчика ошибок TEC, когда он станет больше 255. Подробнее см. раздел «Обработка ошибок».

EPVF (бит 1): Error PassiVe Flag, флаг пассивной ошибки. Этот бит установится аппаратурой, когда был достигнут порог пассивной ошибки (Receive Error Counter или Transmit Error Counter > 127).

EWGF (бит 0): Error WarninG Flag, флаг предупреждения об ошибках. Этот бит установится аппаратурой, когда был достигнут порог предупреждения о большом количестве ошибок (Receive Error Counter или Transmit Error Counter >= 96).

Смещение адреса: 0x1C
Значение после сброса: 0x01230000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
SILM
rw
LBKM
rw
зарезервировано SJW[1:0]
rw
зарез. TS2[2:0]
rw
TS1[3:0]
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано BRP[9:0]
rw

К этому регистру программа может получить доступ только тогда, когда аппаратура CAN находится в initialization mode.

SILM (бит 31): SILent Mode (работа CAN в режиме отладки).

0: нормальное функционирование.
1: «тихий» режим (Silent Mode).

LBKM (бит 30): Loop BacK Mode (отладочный режим).

0: режим зацикливания данных с выхода на вход (Loop Back Mode) запрещен.
1: режим Loop Back Mode разрешен.

Биты 29:26 зарезервированы, и должны находиться в состоянии сброса (все нули).

SJW[1:0] (биты 25:24): ширина скачка ресинхронизации (reSynchronization Jump Width). Эти биты определяют максимальное количество квантов времени (time quanta), на которое аппаратуре CAN позволено удлинить или укоротить специальные интервалы шины для выполнения ресинхронизации. Интервал скачка tRJW, на который удлиняется или укорачивается время:

tRJW = tq x (SJW[1:0] + 1)

Бит 23 зарезервирован, и должен оставаться в состоянии сброса (0).

TS2[2:0] (биты 22:20): Time Segment 2. Эти биты определяют длительность сегмента времени tBS2 в квантах (time quanta).

tBS2 = tq x (TS2[2:0] + 1)

TS1[3:0] (биты 19:16): Time segment 1. Эти биты определяют длительность сегмента времени tBS1 в квантах (time quanta).

tBS1 = tq x (TS1[3:0] + 1)

Для дополнительной информации по таймингу бит шины см. раздел «Интервалы бит (bit timing)».

Биты 15:10 зарезервированы, и должны находиться в состоянии сброса (все нули).

BRP[9:0] (биты 9:0): Baud Rate Prescaler, прескалер скорости CAN. Эти биты определяют длительность битов в квантах времени (time quanta).

tq = (BRP[9:0]+1) x tPCLK

[Регистры CAN mailbox]

В этом разделе описываются регистры ящиков сообщений передачи и приема (mailbox, подробнее см. раздел «Хранилище сообщений»).

У ящиков передачи и приема одни и те же регистры, кроме:

• Поля FMI в регистре CAN_RDTxR.
• Приемный mailbox всегда защищен от записи.
• Передающий mailbox можно записывать только когда он пуст, т. е. когда установлен соответствующий бит TME в регистре CAN_TSR.

Есть 3 передающих ящика (TX Mailbox) и 2 приемных ящика (RX Mailbox), как показано на рис. 349. Каждый RX Mailbox позволяет получить доступ к FIFO глубиной в 3 уровня (стек глубиной в 3 сохраненных сообщения), причем доступ в FIFO предоставляется к самому старому принятому сообщению. Каждый mailbox состоит из 4 регистров.

bxCAN RX and TX mailboxes fig349

Рис. 349. Ящики приема и передачи.

Смещения адреса: 0x180, 0x190, 0x1A0
Значение после сброса: 0xXXXXXXXX (кроме бита 0, TXRQ = 0).

Все TX-регистры защищены от записи, когда mailbox ожидает передачи (сброшен TMEx). Этот регистр также реализует управляющий запрос передачи TX (бит 0) — его значение после сброса 0.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
STID[10:0]/EXID[28:18]
rw
EXID[17:13]
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
EXID[12:0]
rw
IDE
rw
RTR
rw
TXRQ
rw

STID[10:0]/EXID[28:18] (биты 31:21): стандартный или расширенный идентификатор. Это поле содержит стандартный идентификатор, или старшие биты расширенного идентификатора (в зависимости от значения бита IDE).

EXID[17:0] (биты 20:3): младшие биты расширенного идентификатора.

IDE (бит 2): IDentifier Extension (активация расширенного идентификатора). Этот бит определяет тип идентификатора сообщения в mailbox.

0: стандартный идентификатор.
1: расширенный идентификатор.

RTR (бит 1): Remote Transmission Request, запрос на передачу для дальнего узла сети.

0: фрейм данных (Data Frame), обычный фрейм.
1: фрейм Remote.

TXRQ (бит 0): Transmit mailbox request, запрос для ящика на передачу. Бит устанавливается программой для запроса передачи сообщения в соответствующем ящике. Очищается аппаратно, когда этот ящик становится пустым.

Смещения адреса: 0x184, 0x194, 0x1A4
Значение после сброса: 0xXXXXXXXX

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
TIME[15:0]
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано TGT
rw
зарезервировано DLC[3:0]
rw

TIME[15:0] (биты 31:16): метка времени сообщения. Это поле содержит значение 16-битного таймера, захваченного в момент передачи начального бита фрейма (SOF).

Биты 15:9 зарезервированы, и должны находиться в состоянии сброса.

TGT (бит 8): Transmit Global Time, передача глобального времени. Этот бит активен только когда аппаратура находится в режиме Time Trigger Communication, установлен бит TTCM в регистре CAN_MCR.

0: метка времени TIME[15:0] не отправляется.
1: метка времени TIME[15:0] отправляется в последних двух байтах 8-байтного сообщения: TIME[7:0] в байте данных 7, и TIME[15:8] в байте данных 6, с заменой данных, которые были записаны в регистр CAN_TDHxR[31:16] (DATA6[7:0] и DATA7[7:0]). DLC должен быть запрограммирован в значение 8, чтобы эти 2 байта были переданы по шине CAN.

Биты 7:4 зарезервированы, и должны находиться в состоянии сброса.

DLC[3:0] (биты 3:0): Data Length Code, код длины данных сообщения. Это поле определяет количество байт полезной нагрузки фрейма данных или фрейма запроса передачи от удаленного узла (remote frame request). Сообщение может содержать от 0 до 8 байт данных, в зависимости от значения в поле DLC.

Смещения адреса: 0x188, 0x198, 0x1A8
Значение после сброса: 0xXXXXXXXX

Все биты этого регистра защищены от записи, когда ящик занят еще не переданным сообщением (mailbox not empty state).

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
DATA3[7:0]
rw
DATA2[7:0]
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
DATA1[7:0]
rw
DATA0[7:0]
rw

DATA3[7:0] (биты 31:24): байт данных 3 сообщения.
DATA2[7:0] (биты 23:16): байт данных 2 сообщения.
DATA1[7:0] (биты 15:8): байт данных 1 сообщения.
DATA0[7:0] (биты 7:0): байт данных 0 сообщения.

Смещения адреса: 0x18C, 0x19C, 0x1AC
Значение после сброса: 0xXXXXXXXX

Все биты этого регистра защищены от записи, когда ящик занят еще не переданным сообщением (mailbox not empty state).

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
DATA7[7:0]
rw
DATA6[7:0]
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
DATA5[7:0]
rw
DATA4[7:0]
rw

DATA7[7:0] (биты 31:24): байт данных 7 сообщения.

Если в этом ящике установлен бит TGT, и активен режим TTCM (управление передачей по времени), то байты DATA7 и DATA6 будут заменены значением метки времени TIME.

DATA6[7:0] (биты 23:16): байт данных 6 сообщения.
DATA5[7:0] (биты 15:8): байт данных 5 сообщения.
DATA4[7:0] (биты 7:0): байт данных 4 сообщения.

Смещения адреса: 0x1B0, 0x1C0
Значение после сброса: 0xXXXXXXXX

Все RX-регистры защищены от записи.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
STID[10:0]/EXID[28:18]
r
EXID[17:13]
r
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
EXID[12:0]
r
IDE
r
RTR
r
зарез.

Биты 31:17 зарезервированы, и должны находиться в состоянии сброса (все нули).

STID[10:0]/EXID[28:18] (биты 31:21): стандартный или расширенный идентификатор. Это поле содержит стандартный идентификатор, или старшие биты расширенного идентификатора (в зависимости от значения бита IDE).

EXID[17:0] (биты 20:3): младшие биты расширенного идентификатора.

IDE (бит 2): IDentifier Extension (активация расширенного идентификатора). Этот бит определяет тип идентификатора сообщения в mailbox.

0: стандартный идентификатор.
1: расширенный идентификатор.

RTR (бит 1): Remote Transmission Request, запрос на передачу для дальнего узла сети.

0: фрейм данных (Data Frame), обычный фрейм.
1: фрейм Remote.

Бит 0 зарезервирован, и должен оставаться в состоянии сброса.

Смещения адреса: 0x1B4, 0x1C4
Значение после сброса: 0xXXXXXXXX

Все RX-регистры защищены от записи.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
TIME[15:0]
r
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
FMI[7:0]
r
зарезервировано DLC[3:0]
r

TIME[15:0] (биты 31:16): метка времени сообщения. Это поле содержит значение 16-битного таймера, захваченное при детектировании SOF (начало фрейма).

FMI[7:0] (биты 15:8): Filter Match Index, индекс совпавшего фильтра. Этот регистр содержит индекс фильтра сообщения, который прошло сообщение в этом ящике. Более подробно про фильтрацию сообщений см. раздел «Фильтрация по идентификатору».

Биты 7:4 зарезервированы, и должны находиться в состоянии сброса.

DLC[3:0] (биты 3:0): Data Length Code, код длины данных сообщения. В этом поле содержится количество байт данных фрейма сообщения (от 0 до 8). В случае remote frame request в этом поле находится значение 0.

Смещения адреса: 0x1B8, 0x1C8
Значение после сброса: 0xXXXXXXXX

Все RX-регистры защищены от записи.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
DATA3[7:0]
r
DATA2[7:0]
r
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
DATA1[7:0]
r
DATA0[7:0]
r

DATA3[7:0] (биты 31:24): байт данных 3 сообщения.
DATA2[7:0] (биты 23:16): байт данных 2 сообщения.
DATA1[7:0] (биты 15:8): байт данных 1 сообщения.
DATA0[7:0] (биты 7:0): байт данных 0 сообщения.

Смещения адреса: 0x1BC, 0x1CC
Значение после сброса: 0xXXXXXXXX

Все RX-регистры защищены от записи.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
DATA7[7:0]
r
DATA6[7:0]
r
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
DATA5[7:0]
r
DATA4[7:0]
r

DATA7[7:0] (биты 31:24): байт данных 7 сообщения.
DATA6[7:0] (биты 23:16): байт данных 6 сообщения.
DATA5[7:0] (биты 15:8): байт данных 5 сообщения.
DATA4[7:0] (биты 7:0): байт данных 4 сообщения.

[Регистры фильтра CAN]

Смещение адреса: 0x200
Значение после сброса: 0x2A1C0E01

Все биты этого регистра устанавливаются и сбрасываются программой.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
зарезервировано CAN2SB[5:0]
rw
зарезервировано FINIT
rw

Биты 31:14 зарезервированы, и должны находиться в состоянии сброса.

CAN2SB[5:0] (биты 13:8): CAN2 Start Bank. Эти биты устанавливаются и очищаются программой. Они определяют начальный банк для интерфейса CAN2 (Slave) в диапазоне от 0 до 27.

Примечание: когда CAN2SB[5:0] = 28d, могут быть использованы все фильтры для CAN1. Когда CAN2SB[5:0] = 0, то для CAN1 не назначено ни одного фильтра.

Биты 7:1 зарезервированы, и должны находиться в состоянии сброса.

FINIT (бит 0): Filter init mode, режим инициализации банков фильтра.

0: режим активных банков фильтра (фильтры работают).
1: режим инициализации для фильтров.

Смещение адреса: 0x204
Значение после сброса: 0x00000000

Этот регистр может быть записан только когда установлен режим инициализации фильтров (FINIT=1 в регистре CAN_FMR).

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано FBM27
rw
FBM26
rw
FBM25
rw
FBM24
rw
FBM23
rw
FBM22
rw
FBM21
rw
FBM20
rw
FBM19
rw
FBM18
rw
FBM17
rw
FBM16
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
FBM15
rw
FBM14
rw
FBM13
rw
FBM12
rw
FBM11
rw
FBM10
rw
FBM9
rw
FBM8
rw
FBM7
rw
FBM6
rw
FBM5
rw
FBM4
rw
FBM3
rw
FBM2
rw
FBM1
rw
FBM0
rw

Биты 31:28 зарезервированы, и должны находиться в состоянии сброса (все нули).

FBMx (биты 27:0): Filter Bank Mode, определяет режим регистров фильтра x.

0: два 32-битных регистра банка x фильтра работают в режиме маски идентификатора.
1: два 32-битных регистра банка x фильтра работают в режиме списка идентификаторов.

См. также рис. 342.

Смещение адреса: 0x20C
Значение после сброса: 0x00000000

Этот регистр может быть записан только когда установлен режим инициализации фильтров (FINIT=1 в регистре CAN_FMR).

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано FSC27
rw
FSC26
rw
FSC25
rw
FSC24
rw
FSC23
rw
FSC22
rw
FSC21
rw
FSC20
rw
FSC19
rw
FSC18
rw
FSC17
rw
FSC16
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
FSC15
rw
FSC14
rw
FSC13
rw
FSC12
rw
FSC11
rw
FSC10
rw
FSC9
rw
FSC8
rw
FSC7
rw
FSC6
rw
FSC5
rw
FSC4
rw
FSC3
rw
FSC2
rw
FSC1
rw
FSC0
rw

Биты 31:28 зарезервированы, и должны находиться в состоянии сброса (все нули).

FSCx (биты 27:0): Filter Scale Configuration. Эти биты определяют конфигурацию scale фильтров 13 .. 0.

0: двойная 16-битная конфигурация scale.
1: одиночная 32-битная конфигурация scale.

См. также рис. 342.

Смещение адреса: 0x214
Значение после сброса: 0x00000000

Этот регистр может быть записан только когда установлен режим инициализации фильтров (FINIT=1 в регистре CAN_FMR).

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано FFA27
rw
FFA26
rw
FFA25
rw
FFA24
rw
FFA23
rw
FFA22
rw
FFA21
rw
FFA20
rw
FFA19
rw
FFA18
rw
FFA17
rw
FFA16
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
FFA15
rw
FFA14
rw
FFA13
rw
FFA12
rw
FFA11
rw
FFA10
rw
FFA9
rw
FFA8
rw
FFA7
rw
FFA6
rw
FFA5
rw
FFA4
rw
FFA3
rw
FFA2
rw
FFA1
rw
FFA0
rw

Биты 31:28 зарезервированы, и должны находиться в состоянии сброса (все нули).

FFAx (биты 27:0): Filter FIFO Assignment для фильтра x. Сообщение, прошедшее через этот фильтр, будет сохранено в указанном FIFO.

0: фильтр назначен для FIFO0.
1: фильтр назначен для FIFO1.

Смещение адреса: 0x21C
Значение после сброса: 0x00000000

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
зарезервировано FACT27
rw
FACT26
rw
FACT25
rw
FACT24
rw
FACT23
rw
FACT22
rw
FACT21
rw
FACT20
rw
FACT19
rw
FACT18
rw
FACT17
rw
FACT16
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
FACT15
rw
FACT14
rw
FACT13
rw
FACT12
rw
FACT11
rw
FACT10
rw
FACT9
rw
FACT8
rw
FACT7
rw
FACT6
rw
FACT5
rw
FACT4
rw
FACT3
rw
FACT2
rw
FACT1
rw
FACT0
rw

Биты 31:28 зарезервированы, и должны находиться в состоянии сброса (все нули).

FACTx (биты 27:0): Filter ACTive. Программа установит этот бит для активации фильтра x. Для модификации регистров фильтра x (CAN_FxR[0:7]) должен быть очищен бит FACTx, или должен быть установлен бит FINIT в регистре CAN_FMR.

0: фильтр x не активен.
1: фильтр x активен.

Смещение адреса: 0x240 .. 0x31C
Значение после сброса: 0xXXXXXXXX

Имеется 28 банков фильтра, i = 0 .. 27. Каждый банк i состоит из двух 32-битных регистров, CAN_FiR[2:1]. Этот регистр может быть модифицирован только когда очищен бит FACTx, или установлен бит FINIT в регистре CAN_FMR.

   31      30       29       28       27       26       25       24       23       22       21       20       19       18       17       16   
FB31
rw
FB30
rw
FB29
rw
FB28
rw
FB27
rw
FB26
rw
FB25
rw
FB24
rw
FB23
rw
FB22
rw
FB21
rw
FB20
rw
FB19
rw
FB18
rw
FB17
rw
FB16
rw
   15       14       13       12       11       10       9       8       7       6       5       4       3       2       1       0   
FB15
rw
FB14
rw
FB13
rw
FB12
rw
FB11
rw
FB10
rw
FB9
rw
FB8
rw
FB7
rw
FB6
rw
FB5
rw
FB4
rw
FB3
rw
FB2
rw
FB1
rw
FB0
rw

Во всех конфигурациях:

FB[31:0] (биты 31:0): биты фильтра.

Идентификатор: каждый бит регистра задает значение соответствующего бита ожидаемого идентификатора.

0: ожидается доминантный бит.
1: ожидается рецессивный бит.

Маска: каждый бит регистра задает, должен или нет бит связанного идентификатора совпадать с соответствующим битом ожидаемого идентификатора.

0: не имеет значения, этот бит не используется для сравнения на совпадение.
1: требуется соответствие, этот бит пришедшего идентификатора должен иметь такое же значение, как и соответствующий бит регистра идентификатора в фильтре.

Примечание: в зависимости от конфигурации scale и mode фильтра функция каждого регистра может отличаться. Для отображения фильтра, описания функций и регистров маски см. раздел «Фильтрация по идентификатору».

Регистр маски/идентификатора в режиме маски имеет то же самое отображение бит, как и в режиме списка идентификаторов.

Для отображения / адресов регистров банков фильтра см. таблицу 184.

[Ссылки]

1. RM0090 Reference manual STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 advanced Arm®-based 32-bit MCUs site:st.com.

Универсальные асинхронные последовательные средства связи

231

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(RingBuffer_GetDataLength(&txBuf) > 0) {

RingBuffer_Read(&txBuf, &txData, 1); HAL_UART_Transmit_IT(huart, &txData, 1);

}

}

Функция RingBuffer_Read() является не очень быстрой, какой могла бы быть ее более производительная реализация. В некоторых реальных ситуациях общая нагрузка на процедуру HAL_UART_TxCpltCallback() (которая вызывается из процедуры ISR) может быть слишком высокой. Если это ваш случай, вы можете создать такую функцию:

void processPendingTXTransfers(UART_HandleTypeDef *huart) { if(RingBuffer_GetDataLength(&txBuf) > 0) {

RingBuffer_Read(&txBuf, &txData, 1); HAL_UART_Transmit_IT(huart, &txData, 1);

}

}

Затем вы могли бы вызвать данную функцию из основного кода приложения или из задачи с более низким уровнем привилегий, если используете ОСРВ.

При работе с внешними подключениями обработка ошибок является аспектом, который мы должны строго учитывать. Периферийное устройство UART в STM32 предлагает несколько флагов ошибок, относящихся к ошибкам обмена данными. Более того, возможно, что соответствующее ошибке прерывание не будет обработано при ее возникновении.

CubeHAL предназначен для автоматического обнаружения условий ошибок и предупреждения нас о них. Нам нужно только реализовать функцию HAL_UART_ErrorCallback() внутри кода нашего приложения. HAL_UART_IRQHandler() автоматически вызовет ее в случае возникновения ошибки. Чтобы понять, какая именно произошла ошибка, мы можем проверить значение поля UART_HandleTypeDef->ErrorCode. Список кодов ошибок приве-

ден в таблице 7.

Таблица 7: Список возможных значений UART_HandleTypeDef->ErrorCode

Код ошибки UART

Описание

HAL_UART_ERROR_NONE

Ошибка не произошла

HAL_UART_ERROR_PE

Ошибка при проверке четности

HAL_UART_ERROR_NE

Ошибка вследствие зашумления

HAL_UART_ERROR_FE

Ошибка кадрирования данных

HAL_UART_ERROR_ORE

Ошибка вследствие переполнения

HAL_UART_ERROR_DMA

Ошибка передачи посредством DMA

HAL_UART_IRQHandler() разработан таким образом, что нам не нужно вдаваться в подробности реализации обработки ошибок UART. Код HAL автоматически выполнит все необходимые шаги для обработки ошибки (например, сброс флагов событий, бита отложенного состояния и т. д.), оставляя нам ответственность за обработку ошибки на уровне

HAL_UART_ErrorCallback()

Универсальные асинхронные последовательные средства связи

232

приложения (например, мы можем попросить другой узел повторно отправить поврежденный кадр данных).

Прочитайте внимательно

Во время написания данной главы, 2 декабря 2015 года, едва уловимый баг не позволял правильно контролировать ошибку переполнения Overrun error. Вы можете прочитать больше о нем на официальном форуме ST17. Этот баг можно воспроизвести даже со вторым примером данной главы. Запустите пример на Nucleo и нажмите клавишу «3» на клавиатуре, оставив ее нажатой. Через некоторое время микропрограмма зависнет. Это происходит потому, что после возникновения ошибки переполнения HAL вновь не перезапускает процесс получения. Вы можете устранить данный баг с помощью функции

следующим образом:

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { if(huart->ErrorCode == HAL_UART_ERROR_ORE)

HAL_UART_Receive_IT(huart, readBuf, 1);

}

}

8.6. Перенаправление ввода-вывода

В Главе 5 мы узнали, как использовать функцию полухостинг для отправки отладочных сообщений на консоль OpenOCD с помощью функции Си printf(). Если вы уже использовали данную функцию, то вы знаете, что существует два сильных ограничения:

полухостинг значительно замедляет выполнение микропрограммы;

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

Теперь, когда мы знакомы с управлением UART, мы можем переопределить необходимые системные вызовы (_write(), _read() и т. д.), чтобы перенаправить стандартные потоки STDIN, STDOUT и STDERR на USART2 Nucleo. Это можно легко сделать следующим образом:

Имя файла: system/src/retarget/retarget.c

14 #if !defined(OS_USE_SEMIHOSTING)

15

16#define STDIN_FILENO 0

17#define STDOUT_FILENO 1

18#define STDERR_FILENO 2

20UART_HandleTypeDef *gHuart;

22void RetargetInit(UART_HandleTypeDef *huart) {

23gHuart = huart;

25/* Отключение буферизации ввода/вывода для потока STDOUT,

17 https://community.st.com/s/question/0D50X00009XkflRSAR/haluartirqhandler-bug

Универсальные асинхронные последовательные средства связи

233

26* чтобы символы отправлялись сразу после их печати. */

27setvbuf(stdout, NULL, _IONBF, 0);

28}

29

30int _isatty(int fd) {

31if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)

32return 1;

33

34errno = EBADF;

35return 0;

36}

37

38int _write(int fd, char* ptr, int len) {

39HAL_StatusTypeDef hstatus;

40

41if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {

42hstatus = HAL_UART_Transmit(gHuart, (uint8_t *) ptr, len, HAL_MAX_DELAY);

43if (hstatus == HAL_OK)

44return len;

45else

46return EIO;

47}

48errno = EBADF;

49return -1;

50}

51

52int _close(int fd) {

53if (fd >= STDIN_FILENO && fd <= STDERR_FILENO)

54return 0;

55

56errno = EBADF;

57return -1;

58}

59

60int _lseek(int fd, int ptr, int dir) {

61(void) fd;

62(void) ptr;

63(void) dir;

64

65errno = EBADF;

66return -1;

67}

68

69int _read(int fd, char* ptr, int len) {

70HAL_StatusTypeDef hstatus;

71

72if (fd == STDIN_FILENO) {

73hstatus = HAL_UART_Receive(gHuart, (uint8_t *) ptr, 1, HAL_MAX_DELAY);

74if (hstatus == HAL_OK)

75return 1;

Универсальные асинхронные последовательные средства связи

234

76else

77return EIO;

78}

79errno = EBADF;

80return -1;

81}

82

83int _fstat(int fd, struct stat* st) {

84if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {

85st->st_mode = S_IFCHR;

86return 0;

87}

88

89errno = EBADF;

90return 0;

91}

92

93 #endif //#if !defined(OS_USE_SEMIHOSTING)

Чтобы перенаправить стандартные потоки в вашей микропрограмме, вы должны удалить макрос OS_USE_SEMIHOSTING на уровне проекта и инициализировать библиотеку, вызывая RetargetInit(), передавав указатель на экземпляр UART2 UART_HandleTypeDef. Например, следующий код показывает, как использовать функции printf()/scanf() в вашей микропрограмме:

int main(void) { char buf[20]; HAL_Init();

SystemClock_Config();

MX_GPIO_Init();

MX_USART2_UART_Init();

RetargetInit(&huart2);

printf(«Write your name: «); scanf(«%s», buf); printf(«rnHello %s!rn«, buf); while(1);

}

Если вы собираетесь использовать функции printf()/scanf() для печати/чтения типов данных с плавающей точкой float в консоль последовательного порта (также как и если вы собираетесь использовать sprintf() и аналогичные процедуры), вам нужно явно включить поддержку чисел формата float в newlib-nano – более компактной версии библиотеки среды выполнения Си для встраиваемых систем. Для этого перейдите в меню

Project → Properties…, затем перейдите в C/C++ Build → Settings → Cross ARM C++ Linker → Miscellaneous и установите флажок Use float with nano printf/scanf в соот-

ветствии с нужной вам функцией, как показано на рисунке 13. Это увеличит размер бинарного файла микропрограммы.

Универсальные асинхронные последовательные средства связи

235

Рисунок 13: Как включить поддержку чисел формата float в printf() и scanf()

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

Т.к. урок(и) будут рассчитан для начинающих, то и вестись они будут на связке CubeMX + Keil с использованием «могучей» библиотеки HAL (знающие поймут почему в кавычках), в связи с чем очень прошу не разводить полемику по поводу пристрастий к отдельным CMSIS, HAL, SPL, ни под каким соусом.
В качестве подопытного я решил использовать STM32F042K6T6

мой малыш

в семи известном и любимом корпусе ATMEGA8 (LQFP32), периферию можно посмотреть в кубе. Почему именно он? Во первых он у меня есть, во вторых Keil для него абсолютно бесплатный без каких либо ограничений, в третьих HAL дает возможность перенести код на другой камень без особых проблем (и мозги заодно потренировать в процессе, в виде закрепления материала)
Собственно приступим к самому уроку.
Запускаем куб, выбираем новый проект и камень. Включаем RCC(тактирование от внешнего кварца), SYS (активируем ноги для программирования ST-Link V2), CAN и две ножки на выход что б можно было поморгать диодиками и самое главное потом ногу PB8 посадить на землю иначе МК будет в режиме bootloader HAL про эту ногу позабыл))).

Настраиваем тактирование:

Следующая вкладка Configuration
Проверяем режим GPIO для диодиков, все по Default:

пины

и ползем в настройка CAN:

Строчка Time for one bit имеет прямое отношение к скорости передачи CAN Kbit/s, стандартные скорости:
1000, 500, 250, 125, 100, 83.3, 50, 20, 10 Kbit/s
Моя формула для расчета скорости Time for one bit(ns)=1000000/X
где X скорость в Kbit/s, вот под расчетную скорость и начинаем просчитывать Prescaler, Time Quanta in Bit Segment 1 и Time Quanta in Bit Segment 2
А теперь самое интересное, как все это дело правильно посчитать, все дело в квантах)))
P.S. сам я не особо во все это въехал, но все же расскажу со своей колокольни.
Строчка Time Quantum показывает длину одного кванта она зависит только от делителя.
Вот нашел картинку про кванты:

кванты или как их там…

по картинке мы имеем:
Sync_Seg содержит только 1tq
Prop_Seg + Phase_Seg1 может содержать 1-16tq, строчка в коде hcan.Init.BS1 = CAN_BS1_5TQ;
Phase_Seg2 может содержать 1-8tq, строчка в коде hcan.Init.BS2 = CAN_BS2_2TQ;

По картинке имеем 8 квантов, 1 квант на синхронизацию, 5 на первую фазу и 2 на вторую, для скорости 500Kbit/s (2000ns) Time Quantum=2000/8=250ns, т.е. Prescaler нужно подобрать такой, что бы Time Quantum был равен 250ns.
На что влияет соотношение BS1 к BS2 я так и не смог осознать или понять))), в разных источниках по разному, но по факту выходит, что BS1 должен быть больше BS2 или
как в другом источнике BS1=~(87,5%(BS1+BS2)), мне встречалось следующее BS1/BS2
4/3, 13/2, 6/5, и даже 6/8, 5/6 что как мне показалось не есть правильно, но хз…
P.S. в процессе написания пришлось немного разобраться в этих квантах)))
Если кто то знает больше, пишите, добавлю в статью)))
Продолжим, в самой нижней строчке режим работы
Normal — и прием и передача
LoopBack — передача и слушает сам себя
Silent — только прием и слушает сам себя
Silent+ LoopBack — полностью отключен от внешнего мира)))
Мы выбираем режим Normal.
И чуть не забыл вкладка NVIC Settings поставить галку на против CAN:

галочка

Переходим в Project->Settings и придумываем название проекту, место для хранения и для какой IDE собрать проект (MDK-ARM V5) и последний шаг Project->Generate Code

Открываем проект в Keil и сразу жмакаем на собрать проект (кнопка F7) что бы появились все связи.

Пропишем структуры приема и передачи:
/* Private variables ———————————————————*/
static CanTxMsgTypeDef canTxMessage;
static CanRxMsgTypeDef canRxMessage;

определим нашу рукописную функцию передачи
и несколько переменных для приема:
/* Private function prototypes ————————————————*/
void CAN_Transmit(void);

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */
uint16_t CAN_ID;
uint8_t CAN_DLC;
uint8_t DATA[8];

сама функция передачи:
void CAN_Transmit(void)
{
hcan.pTxMsg->StdId = 0x222;
hcan.pTxMsg->DLC = 8;
hcan.pTxMsg->Data[0] = 1;
hcan.pTxMsg->Data[1] = 2;
hcan.pTxMsg->Data[2] = 3;
hcan.pTxMsg->Data[3] = 4;
hcan.pTxMsg->Data[4] = 5;
hcan.pTxMsg->Data[5] = 6;
hcan.pTxMsg->Data[6] = 7;
hcan.pTxMsg->Data[7] = 8;
HAL_CAN_Transmit(&hcan, 10);
}

и функцию обработчика прерывания по приему с моргающим диодом на ноге PB3 сигнализирующем о удачном принятии посылки:
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
CAN_ID = CanHandle->pRxMsg->StdId;
CAN_DLC = CanHandle->pRxMsg->DLC;
DATA[0] = CanHandle->pRxMsg->Data[0];
DATA[1] = CanHandle->pRxMsg->Data[1];
DATA[2] = CanHandle->pRxMsg->Data[2];
DATA[3] = CanHandle->pRxMsg->Data[3];
DATA[4] = CanHandle->pRxMsg->Data[4];
DATA[5] = CanHandle->pRxMsg->Data[5];
DATA[6] = CanHandle->pRxMsg->Data[6];
DATA[7] = CanHandle->pRxMsg->Data[7];
HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
}

Не забываем про структуры и настраиваем CAN фильтры в режиме IDLIST(перечисляем нужные нам ID), т.к. регистры 16 бит а ID посылки 11 бит и передача организована со старшего бита, то приходится ID двигать влево на 5 бит, не я так придумал)))
Через наш фильтр проскочат только:
0x53A, 0x53D, 0x54D, 0x54F, 0xA, 0x33, 0x44, 0x55, на остальные ID МК ни как не среагирует.
/* USER CODE BEGIN 2 */
hcan.pTxMsg = &canTxMessage;
hcan.pRxMsg = &canRxMessage;

CAN_FilterConfTypeDef canFilterConfig;
canFilterConfig.FilterNumber = 0;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
canFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
canFilterConfig.FilterIdHigh = 0x53A<<5;
canFilterConfig.FilterIdLow = 0x53D<<5;
canFilterConfig.FilterMaskIdHigh = 0x54D<<5;
canFilterConfig.FilterMaskIdLow = 0x54F<<5;
canFilterConfig.FilterFIFOAssignment = 0;
canFilterConfig.FilterActivation = ENABLE;
canFilterConfig.BankNumber = 1;
HAL_CAN_ConfigFilter(&hcan, &canFilterConfig);

canFilterConfig.FilterNumber = 1;
canFilterConfig.FilterIdHigh = 0xA<<5;
canFilterConfig.FilterIdLow = 0x33<<5;
canFilterConfig.FilterMaskIdHigh = 0x44<<5;
canFilterConfig.FilterMaskIdLow = 0x55<<5;
HAL_CAN_ConfigFilter(&hcan, &canFilterConfig);

HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) ;

/* USER CODE END 2 */

Ну и в главном цикле моргаем диодом на ноге PA15 и шлем сообщение в CAN каждые 200мсек
CAN_Transmit();
HAL_Delay(200);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_15);

Финальная проверка на CAN Hacker, при отправке ID прописанными в фильтре, диодик весело моргает.

готовый проект googl диск
про отладочную плату
Продолжение

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Hakko t12 ошибка 500
  • Hair стиральный машина ошибка e4