Embedded HandbookПриложения
Все разделы › III. Периферия
STM32F103, STM32F407 · уровень продвинутый · 10 мин чтения
Открыть в интерактивном справочнике

19. Шина CAN

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

Как это называется в документации

Оригинал Перевод
transceiver приёмопередатчик, трансивер
dominant / recessive bit доминантный / рецессивный бит
arbitration арбитраж
identifier идентификатор сообщения
mailbox почтовый ящик передачи
receive FIFO очередь приёма
acceptance filter фильтр приёма
bit timing битовый тайминг
sample point точка выборки
bus-off отключение от шины по ошибкам
loopback mode режим самопроверки

19.1 Чем она отличается от всего остального

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

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

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

Контроль ошибок встроен в железо. Контрольная сумма, подтверждение приёма, автоматический повтор при сбое — всё это делает контроллер сам.


19.2 ⚠️ Трансивер обязателен

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

Между ними ставится трансивер — отдельная микросхема:

Трансивер Питание
SN65HVD230 3,3 В — удобно для STM32
MCP2551, TJA1050 5 В — нужен согласователь уровней или толерантные выводы

Терминаторы. На обоих концах линии — резисторы 120 Ом. Не два где попало, а именно на концах: они гасят отражения. Один резистор или три вместо двух — и связь работает через раз, тем хуже, чем длиннее линия. Многие готовые модули имеют терминатор на плате и перемычку для его отключения; на промежуточных узлах его надо снимать.

Узел CAN: выводы PA12 и PA11 через трансивер SN65HVD230 на дифференциальную пару, по 120 Ом на обоих концах линии, промежуточный узел без терминатора


19.3 Арбитраж: почему выигрывает меньший идентификатор

Логика шины устроена так, что ноль доминирует над единицей: если один узел передаёт ноль, а другой единицу, на линии будет ноль.

Отсюда весь арбитраж. Начав передачу одновременно, узлы выдают свои идентификаторы бит за битом и одновременно слушают линию. Как только узел видит, что передал единицу, а на линии ноль, — он понимает, что проиграл, и молча замолкает. Победитель даже не знает, что был конфликт, и продолжает передачу без задержки.

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

Так выглядит арбитраж двух узлов, начавших передачу одновременно, — на экране анализатора, подключённого к выходам обоих контроллеров и к шине:

Арбитраж CAN на экране анализатора: узлы 0x123 и 0x125, проигрыш узла B на бите ID2


19.4 Битовый тайминг

Самая техничная часть настройки. Каждый бит делится на кванты времени:

бит = 1 (синхронизация) + TS1 + TS2 квантов
скорость = частота шины / (BRP × (1 + TS1 + TS2))

Значение считывается на границе между TS1 и TS2 — это точка выборки. Её положение важно: слишком рано — не успеет установиться уровень на длинной линии, слишком поздно — не останется запаса на рассинхронизацию.

Рекомендуемое значение — около 87,5 % длины бита.

Пример для 500 кбит/с при 36 МГц:

BRP = 9, TS1 = 6, TS2 = 1  →  8 квантов на бит
36 000 000 / (9 × 8) = 500 000 бит/с
точка выборки = (1 + 6) / 8 = 87,5 %

Бит CAN на 500 кбит/с при 36 МГц: BRP 9 даёт квант 250 нс, бит из восьми квантов — синхронизация, TS1 из шести и TS2 из одного — длится 2 мкс, точка выборки на границе TS1 и TS2 приходится на 87,5 %; ниже те же 36 МГц для 1 Мбит/с, 250 и 125 кбит/с с их BRP и числом квантов

Другие ходовые скорости от той же тактовой:

Скорость BRP Квантов
1 Мбит/с 4 9
500 кбит/с 9 8
250 кбит/с 18 8
125 кбит/с 36 8

Регистр BTR пишется только в режиме инициализации, а после сброса блок ещё и спит (бит SLEEP в MCR). Порядок такой:

CAN1->MCR &= ~CAN_MCR_SLEEP;              /* после сброса блок спит */
CAN1->MCR |= CAN_MCR_INRQ;                /* режим инициализации: BTR пишется только в нём */
for (timeout = 100000u; !(CAN1->MSR & CAN_MSR_INAK); timeout--) {
    if (timeout == 0u) {
        return 1u;
    }
}

CAN1->BTR = ((CAN_BRP - 1u) << 0)
          | ((CAN_TS1 - 1u) << 16)
          | ((CAN_TS2 - 1u) << 20)
          | ((CAN_SJW - 1u) << 24);

CAN1->MCR &= ~CAN_MCR_INRQ;               /* выход: ждёт 11 рецессивных бит подряд на RX */
for (timeout = 100000u; CAN1->MSR & CAN_MSR_INAK; timeout--) {
    if (timeout == 0u) {
        return 2u;                        /* на RX нет рецессивного уровня */
    }
}

Второе ожидание кончается, только когда на RX пройдут 11 рецессивных бит подряд. Если там ноль — трансивер не запитан или не подключён, выбран не тот вывод (у F103 CAN по умолчанию на PA11 и PA12, после ремапа — на PB8 и PB9), — без тайм-аута программа повиснет здесь навсегда.

⚠️ Все поля кодируются как «значение минус один». Хотите TS1 = 6 квантов — записываете 5. Забыли вычесть — получите другую скорость и связь, которая не работает, хотя формула вроде посчитана верно.

Вкладка «CAN» в калькуляторах приложения подбирает BRP, TS1 и TS2 под скорость и такт, показывает точку выборки и слово BTR уже с вычтенными единицами; свои поля можно проверить там же.

⚠️ Скорость должна совпадать у всех узлов точно. В отличие от UART, где допустима погрешность в пару процентов, здесь расхождение приводит к ошибкам кадров и уходу узла с шины.

Насколько точно — считают из тайминга. Допуск частоты каждого узла — меньшее из двух чисел: Δf ≤ TS2 / (2 · (13 · N − TS2)) и Δf ≤ SJW / (20 · N), где N — квантов на бит, а SJW — на сколько квантов узел подстраивает бит по фронту: от 1 до 4 и не больше TS2 (в примере — 1). Первая формула — для TS2 не длиннее TS1, как здесь. Для примера (8 квантов, TS2 = 1, SJW = 1) это 1 / 206 = 0,49 % и 1 / 160 = 0,63 %: каждому узлу — не хуже 0,49 %. Внутренний генератор HSI с его ±1 % этого не даёт — CAN тактуют от кварца.


19.5 Фильтры приёма

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

Фильтр работает в одном из двух режимов:

void can1_filter_accept_all(void)
{
    CAN1->FMR |= CAN_FMR_FINIT;           /* фильтры в режим настройки */

    CAN1->FA1R &= ~(1u << 0);             /* банк выключить на время правки */
    CAN1->FS1R |= (1u << 0);              /* один 32-битный фильтр */
    CAN1->FM1R &= ~(1u << 0);             /* режим маски */

    CAN1->sFilterRegister[0].FR1 = 0;     /* идентификатор — любой */
    CAN1->sFilterRegister[0].FR2 = 0;     /* маска нулевая: всё равно */

    CAN1->FFA1R &= ~(1u << 0);            /* складывать в очередь 0 */
    CAN1->FA1R |= (1u << 0);              /* банк включить */

    CAN1->FMR &= ~CAN_FMR_FINIT;
}

⚠️ Без настроенного фильтра не принимается ничего. Это первое, на чём спотыкаются: передача работает, а приём молчит. Контроллер по умолчанию отвергает все сообщения, и «пропускать всё» надо задать явно.


19.6 Передача

Три почтовых ящика на передачу: можно поставить в очередь три сообщения, дальше ждать. Приём складывается в две очереди по три сообщения.

uint8_t can1_send(uint16_t id, const uint8_t *data, uint8_t len)
{
    uint8_t box;

    if (len > 8u) {
        return 1u;                        /* в кадр помещается максимум 8 байт */
    }

    if (CAN1->TSR & CAN_TSR_TME0)      box = 0u;
    else if (CAN1->TSR & CAN_TSR_TME1) box = 1u;
    else if (CAN1->TSR & CAN_TSR_TME2) box = 2u;
    else return 2u;                       /* все заняты */

    CAN1->sTxMailBox[box].TIR = ((uint32_t)id << 21);   /* 11-битный номер */
    CAN1->sTxMailBox[box].TDTR = len;
    /* ... данные в TDLR и TDHR ... */
    CAN1->sTxMailBox[box].TIR |= CAN_TI0R_TXRQ;        /* запрос передачи */
    return 0u;
}

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


19.7 Ошибки и уход с шины

Контроллер ведёт счётчики ошибок передачи и приёма. Логика такая:

Состояние Что означает
активный всё в порядке, узел сообщает об ошибках нормально
пассивный ошибок накопилось много, узел ведёт себя осторожнее
bus-off ошибок слишком много, узел отключён от шины

Уход в bus-off — защита шины от неисправного узла: сломанный передатчик не должен парализовать всех остальных. Восстановление либо ручное, либо автоматическое — если включён соответствующий бит:

CAN1->MCR |= CAN_MCR_ABOM;   /* восстанавливаться автоматически */

Самая частая ловушка у новичка — одинокий узел на шине. Передатчик ждёт подтверждения приёма хотя бы от одного слушателя; если на линии больше никого нет, подтверждения не будет. Счётчик ошибок передачи дорастает до 128, и узел становится пассивным. Дальше по правилам стандарта ошибка подтверждения у пассивного передатчика счётчик не растит: в bus-off узел не уходит, а повторяет кадр без конца. Нужна однократная попытка — бит NART в CAN_MCR (без автоповтора). В bus-off уводят настоящие ошибки: разная скорость узлов, перепутанные CANH и CANL, нет терминаторов.

Состояния узла CAN: из активного в пассивное, когда TEC или REC больше 127, из пассивного в отключение, когда TEC больше 255, обратно — после 128 раз по 11 рецессивных бит; одинокий узел доходит до 128 и застревает в пассивном

Отсюда полезный режим самопроверки (loopback): контроллер слушает собственные передачи и сам себе подтверждает приём. Позволяет отлаживать код и проверять тайминг, имея одну плату и вообще без трансивера.


19.8 ⚠️ Особенность F103: CAN и USB не уживаются

У STM32F103 контроллеры CAN и USB делят общую память для буферов сообщений — 512 байт. Одновременно работать они не могут: используется либо один, либо другой.

На BluePill это ощутимо: разъём USB там разведён, и если проект задуман с USB‑интерфейсом, CAN придётся исключить, и наоборот. У линии подключения F105/F107 эта проблема решена — там контроллеры независимы, как и у F4.


19.9 Грабли

Нет трансивера. Прямое подключение к шине не работает и может повредить выводы.

Неверные терминаторы. Ровно два по 120 Ом, ровно на концах линии.

Поля тайминга не уменьшены на единицу. Скорость получается другой.

Не настроен фильтр. Приём молчит при работающей передаче.

Одинокий узел повторяет кадр без конца. Нет второго участника, некому подтвердить приём: узел пассивный, но не в bus-off. Для отладки — режим самопроверки.

Скорости узлов не совпадают. CAN не прощает расхождения так, как UART.

CAN и USB одновременно на F103. Не заработает, память общая.

Земля не соединена. Дифференциальная пара помогает от помех, но общий потенциал всё равно нужен.


19.10 Итоги

Дальше: раздел 19а «CAN FD на FDCAN: 64 байта, две скорости, память сообщений».

Открыть в интерактивном справочнике