class CAN – шина связи controller area network¶
CAN реализует поддержку как классического CAN (bxCAN, используется на OpenMV Cam M4 и M7), так и CAN FD (FDCAN, используется на OpenMV Cam H7, H7 Plus и Pure Thermal) контроллеров. На физическом уровне шина CAN состоит из двух линий, RX и TX. Чтобы подключить OpenMV Cam к шине CAN, необходимо использовать приёмопередатчик CAN для преобразования логических сигналов CAN от MCU в корректные уровни напряжения на шине.
Классический CAN в режиме петлевого замыкания (без приёмопередатчика):
from pyb import CAN
can = CAN(1, CAN.LOOPBACK)
# Accept messages with id 123, 124, 125 or 126.
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))
can.send("message!", 123) # send a message with id 123
can.recv(0) # receive a message on FIFO 0
CAN FD со всеми включёнными дополнительными функциями (FD-кадр, переключение скорости передачи, расширенные идентификаторы кадров; фаза арбитража 500 кбит/с, фаза данных 1 Мбит/с):
from pyb import CAN
can = CAN(
1,
CAN.NORMAL,
baudrate=500_000,
brs_baudrate=1_000_000,
sample_point=80,
)
# Accept any id in the range 0xFFF0 .. 0xFFFF.
can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF))
can.send(b"a" * 64, 0xFFFF, fdf=True, brs=True, extframe=True)
can.recv(0)
Следующие функции модуля CAN и их аргументы доступны как для классических, так и для FD-контроллеров CAN, если не указано иное.
Конструкторы¶
- class pyb.CAN(bus: int | str, *args, **kwargs)¶
Создаёт объект CAN на заданной шине
bus(целочисленный индекс периферийного устройства, например,1дляCAN1,2дляCAN2). Без дополнительных параметров объект создаётся, но не инициализируется (он сохраняет предыдущие настройки шины, если они есть); если переданы дополнительные аргументы, шина инициализируется. См.CAN.init()для доступных параметров.CAN(2)подключён к одним и тем же выводам разъёма на каждой OpenMV Cam, которая предоставляетpyb.CAN(M4 / M7 / H7 / H7 Plus / Pure Thermal):Сигнал
Вывод разъёма
Примечания
RXP3TXP2Периферийное устройство CAN предоставляет только сигналы логического уровня; для управления реальной шиной CAN требуется внешний приёмопередатчик CAN.
pyb.CANнедоступен на OpenMV Cam N6.Методы¶
- init(mode: int, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, baudrate: int = 0, sample_point: int = 75, num_filter_banks: int = 14, brs_sjw: int = 1, brs_bs1: int = 8, brs_bs2: int = 3, brs_baudrate: int = 0, brs_sample_point: int = 75) None¶
Инициализирует шину CAN с заданными параметрами:
mode — один из: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
prescaler — это значение, на которое делится входная тактовая частота CAN для генерации квантов времени номинального бита. Предделитель может принимать значение от 1 до 1024 включительно для классического CAN и от 1 до 512 включительно для CAN FD.
sjw — это ширина скачка ресинхронизации в единицах квантов времени для номинальных битов; она может принимать значение от 1 до 4 включительно для классического CAN и от 1 до 128 включительно для CAN FD.
bs1 определяет расположение точки выборки в единицах квантов времени для номинальных битов; оно может принимать значение от 1 до 16 включительно для классического CAN и от 2 до 256 включительно для CAN FD.
bs2 определяет расположение точки передачи в единицах квантов времени для номинальных битов; оно может принимать значение от 1 до 8 включительно для классического CAN и от 2 до 128 включительно для CAN FD.
auto_restart задаёт, будет ли контроллер автоматически пытаться перезапустить связь после перехода в состояние bus-off; если эта функция отключена, то для выхода из состояния bus-off можно использовать
restart()baudrate если указана скорость передачи, отличная от 0, эта функция попытается автоматически вычислить номинальное битовое время CAN (переопределяя prescaler, bs1 и bs2), которое удовлетворяет как baudrate (с точностью до .1%), так и желаемой sample_point (с точностью до ближайшего 1%). Для более точного контроля над таймингом CAN задайте параметры prescaler, bs1 и bs2 напрямую.
sample_point задаёт позицию выборки бита относительно всего номинального битового времени, выраженную как целочисленный процент от номинального битового времени. По умолчанию sample_point равна 75%. Этот параметр игнорируется, если не задан baudrate.
num_filter_banks для классического CAN — это количество банков, которые будут назначены CAN(1), остальные из 28 назначаются CAN(2).
Остальные параметры присутствуют только на платах с поддержкой CAN FD и настраивают дополнительную функцию CAN FD Bit Rate Switch (BRS):
brs_prescaler — это значение, на которое делится входная тактовая частота CAN FD для генерации квантов времени бита данных. Предделитель может принимать значение от 1 до 32 включительно.
brs_sjw — это ширина скачка ресинхронизации в единицах квантов времени для битов данных; она может принимать значение от 1 до 16 включительно
brs_bs1 определяет расположение точки выборки в единицах квантов времени для битов данных; оно может принимать значение от 1 до 32 включительно
brs_bs2 определяет расположение точки передачи в единицах квантов времени для битов данных; оно может принимать значение от 1 до 16 включительно
brs_baudrate если указана скорость передачи, отличная от 0, эта функция попытается автоматически вычислить битовое время данных CAN (переопределяя brs_prescaler, brs_bs1 и brs_bs2), которое удовлетворяет как brs_baudrate (с точностью до .1%), так и желаемой brs_sample_point (с точностью до ближайшего 1%). Для более точного контроля над таймингом BRS задайте параметры brs_prescaler, brs_bs1 и brs_bs2 напрямую.
brs_sample_point задаёт позицию выборки бита относительно всего номинального битового времени, выраженную как целочисленный процент от номинального битового времени. По умолчанию brs_sample_point равна 75%. Этот параметр игнорируется, если не задан brs_baudrate.
Квант времени tq — это базовая единица времени для шины CAN. tq равно значению предделителя CAN, делённому на PCLK1 (частота внутренней периферийной шины 1); см.
pyb.freq()для определения PCLK1.Один бит состоит из сегмента синхронизации, который всегда равен 1 tq. Затем следует битовый сегмент 1, затем битовый сегмент 2. Точка выборки находится после окончания битового сегмента 1. Точка передачи находится после окончания битового сегмента 2. Скорость передачи будет равна 1/bittime, где bittime равно 1 + BS1 + BS2, умноженному на квант времени tq.
Например, на OpenMV Cam H7 (PCLK1 = 100 МГц) CAN со скоростью 250 кбит/с и точкой выборки 75% можно настроить как
prescaler=25, sjw=1, bs1=11, bs2=4:tq = 25 / 100 MHz = 250 ns,bittime = (1 + 11 + 4) × 250 ns = 4 µs, точка выборки =(1 + 11) / 16 = 75%, а скорость передачи равна1 / 4 µs = 250 kHz.См. раздел bxCAN / FDCAN справочного руководства STM32 для MCU OpenMV Cam для получения более подробной информации.
- restart() None¶
Принудительно выполняет программный перезапуск контроллера CAN без сброса его конфигурации.
Если контроллер переходит в состояние bus-off, то он больше не участвует в активности на шине. Если контроллер не настроен на автоматический перезапуск (см.
init()), то этот метод можно использовать для запуска перезапуска, и контроллер будет следовать протоколу CAN, чтобы выйти из состояния bus-off и перейти в активное состояние ошибки.
- state() int¶
Возвращает состояние контроллера. Возвращаемое значение может быть одним из:
CAN.STOPPED— контроллер полностью выключен и сброшен;CAN.ERROR_ACTIVE— контроллер включён и находится в активном состоянии ошибки (Error Active) (как TEC, так и REC меньше 96);CAN.ERROR_WARNING— контроллер включён и находится в состоянии предупреждения об ошибке (Error Warning) (хотя бы одно из TEC или REC равно 96 или больше);CAN.ERROR_PASSIVE— контроллер включён и находится в пассивном состоянии ошибки (Error Passive) (хотя бы одно из TEC или REC равно 128 или больше);CAN.BUS_OFF— контроллер включён, но не участвует в активности на шине (TEC переполнился сверх 255).
- info(list: list | None = None) list¶
Получает информацию о состояниях ошибок контроллера и буферах TX и RX. Если предоставлен list, то это должен быть объект списка как минимум с 8 элементами, которые будут заполнены этой информацией. В противном случае будет создан и заполнен новый список. В обоих случаях возвращаемым значением метода является заполненный список.
Значения в списке таковы:
значение TEC
значение REC
количество раз, когда контроллер переходил в состояние предупреждения об ошибке (Error Warning) (сбрасывается в 0 после 65535)
количество раз, когда контроллер переходил в пассивное состояние ошибки (Error Passive) (сбрасывается в 0 после 65535)
количество раз, когда контроллер переходил в состояние Bus Off (сбрасывается в 0 после 65535)
количество ожидающих сообщений TX
количество ожидающих сообщений RX в fifo 0
количество ожидающих сообщений RX в fifo 1
- setfilter(bank: int, mode: int, fifo: int, params: Tuple[int, ...], *, rtr: Tuple[bool, ...] | None = None, extframe: bool = False) None¶
Настраивает банк фильтра:
bank — это банк фильтра классического контроллера CAN или индекс фильтра CAN FD, который нужно настроить.
mode — это режим, в котором должен работать фильтр, см. таблицы ниже.
fifo — это то, в каком fifo (0 или 1) должно храниться сообщение, если оно принято этим фильтром.
params — это массив значений, которые определяют фильтр. Содержимое массива зависит от аргумента mode.
Содержимое массива params для классических контроллеров CAN (OpenMV Cam M4 / M7):
mode
Содержимое params
CAN.LIST16Четыре 16-битных ID, которые будут приняты.
CAN.LIST32Два 32-битных ID, которые будут приняты.
CAN.MASK16Две пары id/маска по 16 бит, например,
(1, 3, 4, 4). Первая пара (1, 3) принимает все ID с битом 0 = 1 и битом 1 = 0; вторая пара (4, 4) принимает все ID с битом 2 = 1.CAN.MASK32Одна пара id/маска по 32 бита (в остальном то же самое, что
CAN.MASK16).Содержимое массива params для CAN FD контроллеров (OpenMV Cam H7 / H7 Plus / Pure Thermal):
mode
Содержимое params
CAN.RANGEДва ID, образующих диапазон принимаемых ID.
CAN.DUALДва ID, которые будут приняты (например,
(1, 2)).CAN.MASKОдна пара
(id, mask)(например,(0x111, 0x7FF)).rtr Для классических контроллеров CAN это массив булевых значений, который определяет, должен ли фильтр принимать сообщение запроса удалённой передачи (remote transmission request). Если этот аргумент не задан, по умолчанию для всех элементов используется
False. Длина зависит от mode:mode
len(rtr)Примечания
CAN.LIST164
CAN.LIST322
CAN.MASK162
CAN.MASK321
Для CAN FD этот аргумент игнорируется.
extframe Если True, кадр будет иметь расширенный идентификатор (29 бит), в противном случае используется стандартный идентификатор (11 бит).
- clearfilter(bank: int, extframe: bool = False) None¶
Очищает и отключает банк фильтра:
bank — это банк фильтра классического контроллера CAN или индекс фильтра CAN FD, который нужно очистить.
extframe Для контроллеров CAN FD, если True, очищает расширенный фильтр (настроенный с extframe=True), в противном случае очищает стандартный идентификатор (настроенный с extframe=False).
- recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list¶
Принимает данные на шине:
fifo — это целое число, обозначающее FIFO, на котором осуществляется приём
list — это необязательный объект списка, используемый в качестве возвращаемого значения
timeout — это тайм-аут в миллисекундах для ожидания приёма.
Возвращаемое значение: список, содержащий пять значений.
ID сообщения.
Булево значение, указывающее, является ли ID сообщения стандартным или расширенным.
Булево значение, указывающее, является ли сообщение RTR-сообщением.
Значение FMI (Filter Match Index).
Массив, содержащий данные.
Если list равен
None, то будет выделен новый список, а также новый объект bytes для хранения данных (в качестве пятого элемента списка).Если list не равен
None, то это должен быть объект списка как минимум с пятью элементами. Пятый элемент должен быть объектом memoryview, созданным из bytearray или массива типа „B“ или „b“, и этот массив должен иметь достаточно места как минимум для 8 байт. Объект списка затем будет заполнен первыми четырьмя возвращаемыми значениями выше, а объект memoryview будет изменён по размеру на месте до размера данных и заполнен этими данными. Одни и те же объекты списка и memoryview можно повторно использовать в последующих вызовах этого метода, что обеспечивает способ приёма данных без использования кучи. Например:buf = bytearray(8) lst = [0, 0, 0, 0, memoryview(buf)] # No heap memory is allocated in the following call can.recv(0, lst)
- send(data: int | bytes | bytearray, id: int, *, timeout: int = 0, rtr: bool = False, extframe: bool = False, fdf: bool = False, brs: bool = False) None¶
Отправляет сообщение на шине:
data — это данные для отправки (целое число для отправки или объект буфера).
id — это ID отправляемого сообщения.
timeout — это тайм-аут в миллисекундах для ожидания отправки.
rtr — это булево значение, которое определяет, должно ли сообщение быть отправлено как запрос удалённой передачи (remote transmission request). Если rtr равно True, то для заполнения слота DLC кадра используется только длина data; фактические байты в data не используются.
extframe если True, кадр будет иметь расширенный идентификатор (29 бит), в противном случае используется стандартный идентификатор (11 бит).
fdf для контроллеров CAN FD, если установлено в True, кадр будет иметь формат FD-кадра, который поддерживает полезную нагрузку данных до 64 байт.
brs для контроллеров CAN FD, если установлено в True, включается режим переключения скорости передачи, при котором фаза данных передаётся с другой скоростью. См.
CAN.init()для параметров конфигурации тайминга бита данных.
Если timeout равен 0, сообщение помещается в один из трёх аппаратных буферов, и метод немедленно возвращается. Если все три буфера используются, генерируется исключение. Если timeout не равен 0, метод ждёт, пока сообщение не будет передано. Если сообщение не может быть передано в течение указанного времени, генерируется исключение.
Возвращаемое значение:
None.
- rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None¶
Регистрирует функцию, которая будет вызвана, когда сообщение принимается в пустой FIFO:
fifo — это принимающий FIFO.
fun — это функция, которая будет вызвана, когда FIFO станет непустым.
Функция обратного вызова принимает два аргумента: первый — это сам объект CAN; второй — это целое число, указывающее причину вызова:
Причина
Значение
0Сообщение принято в пустой FIFO.
1FIFO заполнен.
2Сообщение потеряно из-за заполненного FIFO.
Пример использования rxcallback:
def cb0(bus, reason): print('cb0') if reason == 0: print('pending') if reason == 1: print('full') if reason == 2: print('overflow') can = CAN(1, CAN.LOOPBACK) can.rxcallback(0, cb0)
Константы¶
Константы режима шины (аргумент
modeметодаinit()):- NORMAL: int¶
Контроллер участвует в работе шины обычным образом — передаёт собственные кадры и подтверждает корректно принятые кадры.
- LOOPBACK: int¶
Внутренний режим петлевого замыкания: контроллер отключён от выводов и направляет переданные кадры прямо обратно на путь приёма. Полезно для самотестирования без приёмопередатчика.
- SILENT: int¶
Режим только прослушивания: контроллер принимает кадры, но никогда не управляет шиной (нет ACK, нет передач). Полезно для прослушивания шины.
- SILENT_LOOPBACK: int¶
Сочетает
SILENTиLOOPBACK: нет активности на выводах и нет подтверждений, с внутренним петлевым замыканием TX на RX.
Константы состояния контроллера (возвращаются методом
state()):- ERROR_ACTIVE: int¶
Контроллер включён и находится в активном состоянии ошибки (Error Active) (как TEC, так и REC меньше 96).
- ERROR_WARNING: int¶
Контроллер включён и находится в состоянии предупреждения об ошибке (Error Warning) (хотя бы одно из TEC или REC равно 96 или больше).
- ERROR_PASSIVE: int¶
Контроллер включён и находится в пассивном состоянии ошибки (Error Passive) (хотя бы одно из TEC или REC равно 128 или больше).
- BUS_OFF: int¶
Контроллер включён, но не участвует в активности на шине (TEC переполнился сверх 255).
Режимы фильтра классического CAN (аргумент
modeметодаsetfilter()на OpenMV Cam M4 / M7):Режимы фильтра CAN FD (аргумент
modeметодаsetfilter()на OpenMV Cam H7 / H7 Plus / Pure Thermal):