MicroPython:Библиотеки/pyb/Класс CAN
Класс CAN – коммуникационная шина CAN[1]
В классе CAN реализован коммуникационный протокол CAN. На физическом уровне он состоит из 2 линий: RX и TX. Для подключения PyBoard к шине CAN нужно использовать CAN-трансивер – чтобы преобразовать сигналы CAN-логики от PyBoard в правильные уровни напряжения на шине.
Пример использования (работает, даже если ничего не подключено):
from pyb import CAN
can = CAN(1, CAN.LOOPBACK)
# задаем фильтр для получения сообщений с id 123, 124, 125 и 126:
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))
can.send('message!', 123) # отправляем сообщение с ID 123
can.recv(0) # получаем сообщение на FIFO 0
Конструкторы
Методы класса
- CAN.initfilterbanks(nr) – сбрасывает и отключает все банки фильтров, а также задает, сколько банков будет присвоено шине CAN(1).
Микроконтроллер STM32F405 оснащен 28 банками фильтров, которыми могут пользоваться оба контроллера CAN-шин. Эта функция задает то, сколько банков фильтров нужно присвоить каждой шине. Аргумент nr – это количество банков, которое будет присвоено шине CAN(1), а оставшиеся из 28 банков будут присвоены шине CAN(2). При загрузке каждому из контроллеров будет присвоено по 14 банков.
Методы
- CAN.init(mode, extframe=False, prescaler=100, *, sjw=1, bs1=6, bs2=8, auto_restart=False) – инициализирует CAN-шину со следующими параметрами:
- mode – здесь может быть NORMAL, LOOPBACK, SILENT или SILENT_LOOPBACK.
- extframe – если задать здесь True, шина будет использовать в фреймах расширенные идентификаторы (29 бит). В противном случае она будет использовать в идентификаторах стандартные 11 бит.
- prescaler – этот параметр используется, чтобы задать продолжительность 1 кванта времени. Чтобы рассчитать квант времени, значение в prescaler нужно поделить на входную частоту (PCLK1, более подробно читайте в описании метода pyb.freq()).
- sjw – это ширина скачка синхронизации в квантах времени; здесь может быть «1», «2», «3» или «4».
- bs1 – это место точки захвата (в квантах времени). Здесь может быть от «1» до «1024» включительно.
- bs2 – это место точки передачи (в квантах времени). Здесь может быть от «1» до «16» включительно.
- auto_restart – здесь задается, будет ли контроллер автоматически пытаться перезапустить коммуникацию после входа в режим Bus Off. Если здесь будет стоять False, то restart() можно будет использовать для выхода из режима Bus Off.
Квант времени – это базовая единица измерения времени для CAN-шины. Квант времени рассчитывается как значение предварительного делителя тактовой частоты (prescaler), поделенное на частоту PCLK1 (это частота внутренней периферийной шины 1). Более подробно о PCLK1 читайте в описании функции pyb.freq(). Один бит состоит из сегмента синхронизации (который всегда равен одному кванту), после чего идут сегмент бита 1 и сегмент бита 2. Точка захвата находится в конце сегмента бита 1, а точка передачи – в конце сегмента бита 2. Скорость передачи данных рассчитывается как 1, поделенное на время бита. Время бита – это (1 + сегмент бита 1 + сегмент бита 2), умноженное на квант времени. Допустим, PCLK1 – это 42 МГц, предварительный делитель тактовой частоты (prescaler) – это 100, ширина скачка синхронизации (sjw) – 1, сегмент бита 1 (bs1) – 6, а сегмент бита 2 (bs2) – 8. Отсюда можно вычислить, что… a. Квант времени составляет 2.38 микросекунд: 100 / 42 МГц = 2.38 мкс b. Время бита составляет 35.7 микросекунд: (1 + 6 + 8) * 2.38 = 35.7 мкс c. Скорость передачи данных составляет 28 КГц: 1 / 35.7 = 0.028 Более подробно читайте на странице 680 документации к STM32F405.
- CAN.deinit() – выключает шину CAN.
- CAN.restart() – выполняет принудительный программный перезапуск CAN-контроллера без его перенастройки.
Если контроллер войдет в режим Buss Off, то уже больше не будет участвовать в активности шины. Если контроллер не настроен на автоматический перезапуск (см. init()), то этим методом можно воспользоваться для активации перезапуска, а контроллер, следуя протоколу CAN, выйдет из режима Bus Off и войдет в режим Error Active.
- CAN.state() – возвращает режим работы контроллера. Может вернуть одно из следующих значений:
- 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).
- CAN.info([list]) – считывает информацию об Error-режимах контроллера и данные в буферах RX и TX. Если задан аргумент list, то в нем должен быть списковый объект как минимум с 8 записями, которые будут заполнены информацией (какой именно – смотрите ниже). В противном случае будет создан и заполнен новый список. В обоих случаях метод вернет заполненный информацией список.
Элементы списка:
- Значение TEC.
- Значение REC.
- Количество раз, когда контроллер входил в режим Error Warning (после достижения 65535 значение будет сброшено до 0).
- Количество раз, когда контроллер входил в режим Error Passive (после достижения 65535 значение будет сброшено до 0).
- Количество раз, когда контроллер входил в режим Bus Off (после достижения 65535 значение будет сброшено до 0).
- Количество ждущих обработки TX-сообщений.
- Количество ждущих обработки RX-сообщений на FIFO 0.
- Количество ждущих обработки RX-сообщений на FIFO 1.
- CAN.setfilter(bank, mode, fifo, params, *, rtr) – настраивает банк фильтров:
- bank – банк фильтров, который нужно настроить.
- mode – режим, в котором должен работать фильтр.
- fifo – в какой FIFO (0 или 1) нужно сохранить сообщение, если оно будет принято фильтром.
- params – массив значений, задающих фильтр. Содержимое этого массива зависит от аргумента mode.
Режим Содержимое массива «params» CAN.LIST16 Четыре разрешенных 16-битных ID. CAN.LIST32 Два разрешенных 32-битных ID. CAN.MASK16 Две пары 16-битных масок. Например, (1, 3, 4, 4). 1. Первая пара (1 и 3) пропускает все ID, у которых бит 0 равен 1, а бит 1 равен 0. 2. Вторая пара (4 и 4) пропускает все ID, у которых бит 2 равен 1. CAN.MASK32 То же самое, что и в CAN.MASK16, только с одной парой 32-битных масок.
- rtr – это массив булевых значений, которые сообщают о том, должен ли фильтр разрешать сообщения с запросами об удаленной передаче данных. Если этот аргумент задан не будет, то по умолчанию во всех элементах будет стоять False. Размер массива зависит от аргумента mode.
Режим Размер массива «rtr» CAN.LIST16 4 CAN.LIST32 2 CAN.MASK16 2 CAN.MASK32 1
- CAN.clearfilter(bank) – очищает и выключает банк фильтров.
- bank – это банк фильтров, который надо очистить.
- CAN.any(fifo) – возвращает True, если в FIFO есть сообщение для считывания. В противном случае возвращает False.
- CAN.recv(fifo, list=None, *, timeout=5000) – принимает данные на шине:
- fifo – это целое число, обозначающее то, какой FIFO будет принимать данные.
- list – это опциональный списковый объект, который будет использоваться в качестве возвращаемого значения.
- timeout – таймаут в миллисекундах для ожидания приема данных.
Возвращаемое значение – это кортеж с 4 элементами:
- ID сообщения.
- Булево значение, сообщающее о том, является ли сообщение RTR-сообщением.
- Значение FMI («filter match index», т.е. «индекс совпадения фильтра»).
- Массив, содержащий данные.
Если в list задано None, система выделит память под новый кортеж и новый объект bytes – для хранения данных (в виде четвертого элемента этого кортежа). Если в list будет задано не None, то это должен быть списковый объект, содержащий как минимум 4 элемента. Четвертым элементом должен быть объект memoryview, который создается либо из массива байтов, либо из массива типа «B» или «b», и этот массив должен быть достаточно велик, чтобы вместить как минимум 8 байтов. Затем этот списковый объект будет наполнен первыми тремя возвращенными значениями из списка выше, а размер объекта memoryview будет изменен в соответствии с размером присланных данных и заполнен этими данными. При последующих вызовах этого метода этот же список и объект memoryview можно будет использовать повторно, что позволяет получать данные без использования кучи. Например:
buf = bytearray(8)
lst = [0, 0, 0, memoryview(buf)]
# При следующем вызове память в куче выделена не будет.
can.recv(0, lst)
- CAN.send(data, id, *, timeout=0, rtr=False) – отправляет сообщение на шину:
- data – данные, которые нужно отправить (целое число или буферный объект).
- id – ID отправляемого сообщения.
- timeout – таймаут в миллисекундах для ожидания отправки данных.
- rtr – это булево значение, задающее, будет ли это сообщение отправлено как запрос на удаленную передачу данных. Если задать здесь True, будет использован только размер данных data (чтобы заполнить поле DLC фрейма). Сами байты из data использованы не будут.
Если задать в timeout значение «0», сообщение будет помещено в один из трех аппаратных буферов, а метод вернет значение немедленно. Если все три буфера уже используются, будет возбуждено исключение. Если значение в timeout будет ненулевым, метод будет ждать, пока сообщение не будет отправлено. Если сообщение не будет отправлено в пределах заданного времени, будет возбуждено исключение. Возвращаемое значение: None.
- CAN.rxcallback(fifo, fun) – регистрирует функцию, которая будет вызвана при приеме сообщения в пустой FIFO.
- fifo – FIFO, получающий сообщение.
- fun – функция, которая будет вызвана, когда FIFO перестанет быть пустым.
Функция обратного вызова принимает два аргумента. Первый – это сам объект CAN, а второй – это целое число, информирующее о причине запуска функции обратного вызова:
- «0» – сообщение принято в пустой FIFO.
- «1» – FIFO заполнен.
- «2» – сообщение было потеряно из-за полного FIFO.
Пример использования CAN.rxcallback(fifo, fun):
def cb0(bus, reason):
print('cb0')
if reason == 0:
print('в режиме ожидания')
if reason == 1:
print('полный')
if reason == 2:
print('переполнение')
can = CAN(1, CAN.LOOPBACK)
can.rxcallback(0, cb0)
Константы
- CAN.NORMAL, CAN.LOOPBACK, CAN.SILENT, CAN.SILENT_LOOPBACK – режимы работы CAN-шины, используемые в init().
- CAN.STOPPED, CAN.ERROR_ACTIVE, CAN.ERROR_WARNING, CAN.ERROR_PASSIVE, CAN.BUS_OFF – режимы работы CAN-контроллера, возвращаемые функцией state().
- CAN.LIST16, CAN.MASK16, CAN.LIST32, CAN.MASK32 – режимы работы фильтра, используемые в setfilter().
<syntaxhighlight lang="python" enclose="div">