клас CAN – протокол Controller Area Network

CAN — це двопровідний послідовний протокол для надійної передачі повідомлень у реальному часі між одним або кількома вузлами, підключеними до спільної шини. CAN 2.0 стандартизовано в ISO-11898 і тепер також відомий як CAN Classic.

Існує також новіший, зворотньо сумісний протокол під назвою CAN FD (CAN з гнучкою швидкістю передачі даних). Драйвер machine.CAN наразі не підтримує функції CAN FD; використовуйте pyb.CAN на STM32, якщо потрібна підтримка CAN FD.

Для підтримки CAN потрібен контролер (часто внутрішній периферійний пристрій мікроконтролера) та зовнішній приймач-передавач для узгодження рівнів сигналів шини CAN.

Доступно на камерах OpenMV на базі STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, а також варіанти з брендом Arduino, де підключено приймач-передавач). Ще не підтримується на OpenMV Cam RT1062 (порт mimxrt) та OpenMV Cam AE3 (порт alif).

Інтерфейс machine.CAN — це низькорівневий базовий інтерфейс обміну повідомленнями CAN, який представляє контролер CAN як вихідну чергу пріоритетів для надсилання повідомлень, вхідну чергу для отримання повідомлень і механізми звітування про помилки.

Примітка

Заплановані модулі can і aiocan бібліотеки micropython-lib стануть рекомендованим способом використання CAN разом із MicroPython.

Конструктор

class machine.CAN(id: int, *args, **kwargs)

Створює об’єкт контролера CAN із заданим ідентифікатором:

  • id ідентифікує конкретний об’єкт контролера CAN; він є специфічним для плати та порту.

  • Усі інші аргументи передаються до CAN.init(). Необхідно вказати принаймні один аргумент (bitrate).

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

Приклад

Створення та ініціалізація контролера CAN 1 зі швидкістю передачі 500 кбіт/с:

from machine import CAN
can = CAN(1, 500_000)

Методи

init(bitrate: int, mode: int = CAN.MODE_NORMAL, sample_point: int = 75, sjw: int = 1, tseg1: int | None = None, tseg2: int | None = None) None

Ініціалізує шину CAN із заданими параметрами:

  • bitrate — бажана швидкість передачі на шині в бітах за секунду.

  • mode — одне зі значень, наведених у Режими, що вказує бажаний режим роботи. За замовчуванням — «нормальна» робота на шині.

Наступні параметри є необов’язковими і стосуються тактування бітів CAN. У більшості випадків ці параметри можна залишити зі значеннями за замовчуванням:

  • sample_point — ціле число у відсотках від часу бітового інтервалу. Визначає положення точки вибірки відносно повного номінального часу біту. Драйвер CAN розрахує параметри відповідно. Цей параметр ігнорується, якщо встановлено tseg1 і tseg2.

  • sjw — ширина стрибка ресинхронізації в одиницях часових квантів для номінальних бітів; може приймати значення від 1 до 4 включно для класичного CAN.

  • tseg1 визначає розташування точки вибірки в одиницях часових квантів для номінальних бітів; може приймати значення від 1 до 16 включно для класичного CAN. Це сума фаз Prop_Seg і Phase_Seg1, визначених у стандарті ISO-11898. Якщо це значення задано, необхідно також задати tseg2, а sample_point ігнорується.

  • tseg2 визначає розташування точки передавання в одиницях часових квантів для номінальних бітів; може приймати значення від 1 до 8 включно для класичного CAN. Відповідає Phase_Seg2 за стандартом ISO-11898. Якщо це значення задано, необхідно також задати tseg1.

Якщо ці аргументи задано, контролер CAN налаштовується коректно для бажаного bitrate і вказаної загальної кількості часових квантів на біт. Значення tseg1 і tseg2 мають пріоритет над аргументом sample_point, якщо всі вони задані разом.

Примітка

Конкретне апаратне забезпечення контролера може мати додаткові обмеження на допустимі значення цих параметрів і генерує ValueError, якщо задане значення не підтримується.

Примітка

Конкретне апаратне забезпечення контролера може приймати додаткові необов’язкові іменовані параметри для апаратно-специфічних функцій, наприклад надвибірки.

set_filters(filters: list | tuple | None) None

Встановлює фільтри прийому у контролері CAN. filters може бути:

  • None — приймати всі вхідні повідомлення, або

  • [] або () — вимкнути отримання всіх повідомлень, або

  • Ітерований об’єкт з одним або кількома елементами, що визначають критерії фільтрації. Кожен елемент має бути кортежем або списком із трьох елементів:

    • identifier — ідентифікатор CAN (int).

    • bit_mask — бітова маска для бітів у полі ідентифікатора CAN (int).

    • flags — ціле число з нулем або більше бітів, визначених у Прапорці повідомлення. Визначає властивості, яким має відповідати вхідне повідомлення. Не всі контролери підтримують фільтрацію за всіма прапорцями; генерується ValueError, якщо запитується непідтримуваний прапорець.

Вхідні повідомлення приймаються, якщо біти, що маскуються bit_mask, збігаються між ідентифікатором повідомлення і значенням identifier фільтра, а прапорці, встановлені у фільтрі, відповідають вхідному повідомленню.

Якщо біт CAN.FLAG_EXT_ID встановлено у прапорцях, фільтр відповідає лише розширеним CAN ID. Якщо біт CAN.FLAG_EXT_ID не встановлено, фільтр відповідає лише стандартним CAN ID.

Усі фільтри об’єднуються в контролері операцією АБО. Передача порожнього списку або кортежу як аргументу filters означає, що жодне повідомлення не буде отримано.

Деякі контролери CAN вимагають, щоб кожен фільтр був пов’язаний лише з одним FIFO прийому. У таких випадках елементи фільтрів у аргументі розподіляються по черзі між доступними FIFO. Цей драйвер не розрізняє FIFO в IRQ прийому.

Примітка

Якщо абонент передає ітерований об’єкт із більшою кількістю елементів, ніж CAN.FILTERS_MAX, генерується ValueError.

Примітка

Якщо identifier або bit_mask виходять за межі діапазону для зазначеного типу ID, генерується ValueError з причиною «invalid id».

Приклади

Прийом усіх вхідних повідомлень:

can.set_filters(None)

Прийом лише повідомлень зі стандартними значеннями ID 0x301 і 0x700:

can.set_filters(((0x301, 0x7FF, 0),
                 (0x700, 0x7FF, 0)))

Прийом лише повідомлень зі стандартними значеннями ID в діапазоні 0x300-0x3FF і розширеним ID 0x50700:

can.set_filters(((0x300, 0x700, 0),
                 (0x50700, 0x1FFF_FFFF, CAN.FLAG_EXT_ID)))
FILTERS_MAX: int

Константне значення, що містить максимальну кількість підтримуваних фільтрів прийому для цього апаратного контролера.

Зверніть увагу, що деякі контролери можуть мати складніші апаратні обмеження на кількість використовуваних фільтрів (наприклад, окремий підрахунок фільтрів стандартних і розширених ID). У таких випадках CAN.set_filters може генерувати ValueError навіть коли ліміт FILTERS_MAX не перевищено.

send(id: int, data: bytes, flags: int = 0) int | None

Копіює нове повідомлення CAN у апаратну чергу передавання контролера для надсилання на шину. Черга передавання є чергою пріоритетів, відсортованою за пріоритетом ідентифікатора CAN (менші числові ідентифікатори мають вищий пріоритет).

  • id — ціле значення ідентифікатора CAN.

  • data — об’єкт bytes (або подібний), що містить дані повідомлення CAN, або описує запит на віддалену передачу (див. нижче).

  • flags — ціле число з нулем або більше бітів, визначених у Прапорці повідомлення, що вказує властивості вихідного повідомлення CAN (розширений ID, запит на віддалену передачу тощо).

Якщо повідомлення успішно поставлено в чергу для передавання на шину, функція повертає ціле число в діапазоні від 0 до CAN.TX_QUEUE_LEN (виключно). Це значення є індексом буфера передавання, де повідомлення поставлено в чергу для надсилання; його може використовувати функція CAN.cancel_send та події CAN.IRQ_TX.

Якщо черга заповнена, надсилання завершиться невдачею і буде повернуто None.

Надсилання також може завершитися невдачею і повернути None, якщо задане значення id має однаковий пріоритет з існуючим повідомленням у черзі передавання, а апаратне забезпечення контролера CAN не може гарантувати надсилання повідомлень з однаковим ID на шину в тому ж порядку, в якому їх було додано до черги. Щоб усе одно поставити повідомлення в чергу, передайте прапорець CAN.FLAG_UNORDERED в аргументі flags. Цей прапорець вказує, що допускається надсилання повідомлень з однаковим CAN ID на шину в будь-якому порядку.

Якщо контролер перебуває у стані помилки «Bus Off» або вимкнений, виклик цієї функції генерує OSError.

Примітка

Ця навмисно низькорівнева реалізація розроблена так, щоб абонент міг підтримувати програмну чергу вихідних повідомлень.

Важливо

«Черга передавання» CAN — це не черга FIFO, а черга з пріоритетами. Незважаючи на те, що вона може містити до CAN.TX_QUEUE_LEN елементів, можуть існувати й інші апаратні обмеження на повідомлення, які можна поставити в чергу одночасно.

Запити на віддалену передачу

Якщо біт CAN.FLAG_RTR встановлено в аргументі flags, контролер надсилає запит на віддалену передачу замість повідомлення. У цьому випадку вміст аргументу data ігнорується. Контролер надсилає запит, де поле довжини DLC дорівнює довжині аргументу data.

Приклади

Спроба надіслати повідомлення з трибайтовим навантаженням 0a0b0c та стандартним ID 0x200:

can.send(0x200, b"\x0a\x0b\x0c", 0)

Спроба надіслати повідомлення з порожнім навантаженням і розширеним ID 0x180008. Вказати, що контролер може надсилати повідомлення з цим ID в будь-якому порядку, якщо інші повідомлення вже поставлені в чергу для надсилання з тим самим ID:

can.send(0x180008, b"", can.FLAG_EXT_ID | can.FLAG_UNORDERED)

Спроба надіслати запит на віддалену передачу довжиною 8 байт і стандартним ID 0x555:

can.send(0x555, b" " * 8, can.FLAG_RTR)
recv(arg: list | None = None) list | None

Повертає повідомлення CAN, отримане контролером відповідно до фільтрів, встановлених CAN.set_filters().

Ця функція приймає один необов’язковий аргумент; якщо він наданий, то має бути списком принаймні з 4 елементів, де другий елемент — об’єкт memoryview, що посилається на bytearray або подібний об’єкт із достатньою ємністю для зберігання будь-якого отриманого повідомлення CAN (8 байт для CAN Classic, 64 байти для CAN FD). Наданий список буде повернуто як успішний результат і дозволяє уникнути виділення пам’яті всередині функції.

Якщо контролером CAN не отримано жодного повідомлення, функція повертає None.

Примітка

Перед тим, як контролер зможе отримувати повідомлення, необхідно викликати CAN.set_filters. Щоб отримувати всі повідомлення, викличте set_filters(None).

Якщо контролером CAN отримано повідомлення, функція повертає список із 4 елементів:

  • Індекс 0 — CAN ID отриманого повідомлення у вигляді цілого числа.

  • Індекс 1 — memoryview, що надає доступ до даних отриманого повідомлення.

    • Якщо arg не надано, це memoryview, що містить отримані байти. Цей memoryview підкріплений новоствореним bytearray, достатньо великим для зберігання будь-якого отриманого повідомлення CAN. Це дозволяє безпечно повторно використовувати результат як майбутній arg для економії виділень пам’яті.

    • Якщо arg надано, наданий memoryview буде змінено за розміром для зберігання точно отриманих байтів. Абонент відповідає за те, щоб підкріплюючий об’єкт для memoryview міг зберігати повідомлення CAN будь-якої довжини.

  • Індекс 2 — ціле число з нулем або більше бітів, визначених у Прапорці повідомлення. Вказує метадані про отримане повідомлення.

  • Індекс 3 — ціле число з нулем або більше бітів, визначених у Прапорці помилок прийому. Будь-яке ненульове значення вказує на потенційні проблеми при отриманні повідомлень CAN. Ці прапорці скидаються у контролері щоразу, коли функція повертає результат.

Запити на віддалену передачу

Якщо отримано запит на віддалену передачу, біт CAN.FLAG_RTR буде встановлений в Індексі 2, а memoryview в Індексі 1 міститиме самі нулі довжиною, що дорівнює полю DLC отриманого запиту.

Приклад
can.set_filters(None)   # receive all
while True:
    res = can.recv()
    if res:
        can_id, data, flags, errs = res
        print("Received", hex(can_id), data.hex(), hex(flags), hex(errs))
    else:
        time.sleep_ms(1)  # not a good pattern, use the irq instead!
irq(handler: Callable[[CAN], None] | None = None, trigger: int = 0, hard: bool = False) None

Встановлює функцію-handler переривання, яка викликається при виникненні одної або кількох подій, зазначених у trigger.

  • handler — функція, що викликається при спрацюванні події переривання. Обробник повинен приймати рівно один аргумент — екземпляр CAN.

  • trigger налаштовує подію (події), що можуть генерувати переривання. Допустимі значення — маска з одного або кількох наступних:

    • Подія CAN.IRQ_RX виникає після того, як контролер CAN отримав принаймні одне повідомлення у свій RX FIFO (тобто CAN.recv() поверне результат успішно).

    • Подія CAN.IRQ_TX виникає після того, як контролер CAN або успішно надіслав повідомлення на шину CAN, або не зміг його надіслати. Цей тригер має додаткові вимоги до обробника — докладніше у Прапорці IRQ.

    • Подія CAN.IRQ_STATE виникає, коли контролер CAN переходить у більш серйозний стан помилки. Викличте CAN.state() для отримання оновленого стану.

  • hard — якщо True, використовується апаратне переривання. Це зменшує затримку між подією контролера CAN і викликом обробника. Апаратні обробники переривань не можуть виділяти пам’ять; дивіться Написання обробників переривань.

Повертає об’єкт irq. Якщо викликано без аргументів, повертає раніше налаштований об’єкт irq.

Дивіться Прапорці IRQ для прикладу.

cancel_send(index: int) bool

Запитує у контролера CAN скасування надсилання повідомлення на шину.

Аргумент index ідентифікує окремий буфер передавання. Має бути цілим числом у діапазоні від 0 до CAN.TX_QUEUE_LEN (виключно). Зазвичай це значення, що раніше було повернуто CAN.send().

Результат True означає, що повідомлення очікувало передавання в цьому буфері і передавання було скасовано.

Результат False означає інше (або повідомлення не очікувало передавання в цьому буфері, або передавання вже завершено успішно).

Подія IRQ CAN.IRQ_TX повинна використовуватися для визначення того, чи було повідомлення точно надіслано, але зверніть увагу на потенційні гонки станів, якщо передавання скасовано, а потім той самий буфер використовується для надсилання іншого повідомлення (особливо якщо IRQ контролера CAN не є «апаратним»).

state() int

Повертає ціле значення, що вказує поточний стан контролера. Значення буде одним із значень, визначених у Стани.

Стани помилок меншої серйозності можуть автоматично скидатися при відновленні шини, але стан CAN.STATE_BUS_OFF може бути відновлено лише викликом CAN.restart().

get_counters(list: list | None = None, /) list

Повертає значення лічильників помилок контролера. Результат — список із восьми значень. Якщо вказано необов’язковий параметр list, то наданий об’єкт списку оновлюється і повертається як результат, щоб уникнути виділення пам’яті.

Елементи списку:

  • Значення TEC (лічильник помилок передавання)

  • Значення REC (лічильник помилок прийому)

  • Кількість переходів контролера зі стану Active у стан Warning.

  • Кількість переходів контролера зі стану Warning у стан Error Passive.

  • Кількість переходів контролера зі стану Error Passive у стан Bus Off.

  • Загальна кількість очікуючих TX-повідомлень у апаратній черзі.

  • Загальна кількість очікуючих RX-повідомлень у апаратній черзі.

  • Кількість випадків переповнення RX.

Примітка

Залежно від контролера, ці значення можуть переповнюватися до 0 після досягнення певного значення.

Примітка

Якщо контролер не підтримує певний лічильник, повертається None для відповідного елемента списку.

get_timings(list: list | None = None, /) list

Повертає список елементів, що вказують поточні налаштування тактування у контролері CAN. Може використовуватися для перевірки тактування в цілях налагодження. Результат — список із шести значень. Якщо вказано необов’язковий параметр list, то наданий об’єкт списку оновлюється і повертається як результат, щоб уникнути виділення пам’яті.

Елементи списку:

  • Точна швидкість передачі, яку використовує контролер. Може відрізнятися від аргументу bitrate, переданого до CAN.init(), через квантування для відповідності апаратним обмеженням.

  • Ширина стрибка ресинхронізації (SJW) в одиницях часових квантів для номінальних бітів. Має те саме значення, що й параметр sjw функції CAN.init().

  • Розташування точки вибірки в одиницях часових квантів для номінальних бітів. Має те саме значення, що й параметр tseg1 функції CAN.init().

  • Розташування точки передавання в одиницях часових квантів для номінальних бітів. Має те саме значення, що й параметр tseg2 функції CAN.init().

  • Інформація про тактування CAN FD. None для контролерів, що не підтримують CAN FD, або якщо CAN FD не ініціалізовано. В іншому випадку — вкладений список із чотирьох елементів, що відповідають наведеним вище елементам, але стосуються функції CAN FD BRS.

  • Необов’язкова специфічна для контролера інформація про тактування. Залежно від контролера, це може бути None, якщо контролер не надає жодної інформації, або список фіксованої довжини, елементи якого є специфічними для конкретного апаратного контролера.

Примітка

Якщо CAN.init() не було викликано, ця функція все одно повертає результат, але він залежить від внутрішнього стану контролера і може бути неточним.

restart() None

Примушує контролер вийти зі стану STATE_BUS_OFF без скидання будь-якого іншого внутрішнього стану. Також скидає деякі лічильники помилок (завжди кількість входжень у кожен стан помилки, а TEC і REC — залежно від контролера).

Виклик цієї функції також скасовує всі повідомлення, що очікують надсилання. Переривання IRQ_TX для цих повідомлень не надходять.

Зверніть увагу, що ця функція може або не може вивести контролер зі стану «Error Passive», залежно від того, чи обнуляє апаратне забезпечення контролера TEC і REC.

deinit() None

Деініціалізує раніше активний екземпляр CAN. Усі очікуючі повідомлення (передавання і прийому) відкидаються, і контролер припиняє взаємодію з шиною. Щоб знову використовувати цей екземпляр, викличте CAN.init().

У відповідь на виклик цієї функції не надходять переривання IRQ_TX або IRQ_RX.

Дивіться також CAN.restart().

Константи

TX_QUEUE_LEN: int

Максимальна кількість повідомлень CAN, які можуть бути поставлені в чергу апаратної черги передавання контролера. «Індекси буфера передавання», що використовуються CAN.send(), CAN.cancel_send() і Прапорці IRQ, знаходитимуться в цьому діапазоні.

Режими

Ці значення представляють режими роботи контролера, що передаються до CAN.init(). Не всі контролери можуть підтримувати всі режими.

Для зміни режиму працюючого контролера необхідно викликати CAN.deinit(), а потім знову викликати CAN.init() з новим режимом.

MODE_NORMAL: int

Контролер активний як стандартний вузол мережі CAN (підтверджуватиме дійсні повідомлення і може передавати помилки залежно від поточного стану).

MODE_SLEEP: int

Контролер CAN перебуває у сні у режимі пониженого споживання енергії. Залежно від контролера, може підтримуватися пробудження контролера і перехід до CAN.MODE_NORMAL при отриманні трафіку CAN.

MODE_LOOPBACK: int

Тестовий режим. Контролер CAN все ще підключений до зовнішньої шини, але також отримуватиме власні передані повідомлення і ігноруватиме будь-які помилки ACK.

MODE_SILENT: int

Контролер CAN отримує повідомлення, але не взаємодіє з шиною CAN (включаючи надсилання ACK, помилок тощо).

MODE_SILENT_LOOPBACK: int

Тестовий режим, що не вимагає підключення приймача-передавача CAN. Контролер CAN отримує власні передані повідомлення без будь-якої взаємодії з шиною CAN. Виводи TX і RX CAN залишаються у стані спокою.

Стани

Ці значення повертаються CAN.state() і відображають стан помилки контролера CAN:

STATE_STOPPED: int

Контролер не ініціалізовано.

STATE_ACTIVE: int

Контролер активний, а лічильники помилок TEC і REC знаходяться нижче порогового значення попередження 96. Дивіться CAN.get_counters().

STATE_WARNING: int

Контролер активний, але принаймні один із лічильників помилок TEC і REC знаходиться в діапазоні від 96 до 127. Дивіться CAN.get_counters().

STATE_PASSIVE: int

Контролер перебуває у стані «Error Passive», тобто більше не передає активні помилки на шину, але в іншому є функціональним. Цей стан виникає, коли принаймні один із лічильників помилок TEC і REC дорівнює 128 або більше, але TEC менше 255. Дивіться CAN.get_counters().

STATE_BUS_OFF: int

Контролер перебуває у стані Bus-Off, тобто лічильник помилок TEC перевищує 255. У цьому стані контролер CAN не взаємодіє з шиною і потребує перезапуску через CAN.restart().

Прапорці повідомлення

Ці значення представляють метадані про повідомлення CAN. Функції CAN.send(), CAN.recv() і CAN.set_filters() або приймають, або повертають ціле значення, що складається з нуля або більше цих прапорців, об’єднаних побітовим АБО.

FLAG_RTR: int

Вказує, що повідомлення є запитом на віддалену передачу.

FLAG_EXT_ID: int

Якщо встановлено, вказує, що ідентифікатор повідомлення є розширеним (29-розрядним). Якщо не встановлено, вказує, що ідентифікатор повідомлення є стандартним (11-розрядним).

FLAG_UNORDERED: int

Якщо встановлено в аргументі flags CAN.send(), вказує, що допускається надсилання повідомлень з однаковим CAN ID на шину в будь-якому порядку.

В іншому випадку спроба поставити в чергу кілька повідомлень з однаковим ID може призвести до помилки CAN.send(), якщо апаратне забезпечення контролера не може забезпечити впорядкованість.

Цей прапорець ніколи не встановлюється для отриманих повідомлень і ігнорується CAN.set_filters().

Прапорці помилок прийому

Результат CAN.recv() містить ціле значення, що складається з нуля або більше цих прапорців, об’єднаних побітовим АБО. Якщо встановлено, ці прапорці вказують на потенційні загальні проблеми при отриманні повідомлень CAN.

RECV_ERR_FULL: int

Апаратний FIFO, де отримано це повідомлення, заповнений, і додаткові вхідні повідомлення можуть бути втрачені.

RECV_ERR_OVERRUN: int

Апаратний FIFO, де отримано це повідомлення, заповнений, і одне або кілька вхідних повідомлень втрачено.

Значення IRQ

IRQ_RX: int

Передається в аргумент trigger irq() для спрацювання обробника щоразу, коли контролер CAN отримав повне повідомлення у RX FIFO. Всередині обробника читайте повідомлення за допомогою recv().

IRQ_TX: int

Передається в аргумент trigger irq() для спрацювання обробника щоразу, коли контролер CAN завершує спробу передавання (успішно або з помилкою). Всередині обробника використовуйте додаткові біти нижче, щоб визначити, який поштовий скринька завершив роботу і чи сталася помилка — дивіться Прапорці IRQ.

IRQ_STATE: int

Передається в аргумент trigger irq() для спрацювання обробника щоразу, коли контролер переходить між значеннями STATE_* (active / warning / passive / bus-off). Використовуйте state() всередині обробника для читання нового стану.

IRQ_TX_FAILED: int

Прапорець стану, що може бути встановлений у irq().flags() під час спрацювання події IRQ_TX. Вказує, що спроба передавання завершилася невдачею (як правило, через виклик cancel_send() або перехід контролера у стан помилки).

IRQ_TX_IDX_SHIFT: int

Позиція біта поля індексу поштової скриньки передавання у значенні irq().flags() під час події IRQ_TX. Індекс поштової скриньки витягується як (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.

IRQ_TX_IDX_MASK: int

Бітова маска поля індексу поштової скриньки передавання у значенні irq().flags() під час події IRQ_TX. Витягнутий індекс відповідає цілому числу, поверненому відповідним викликом send() (цілому числу в діапазоні від 0 до TX_QUEUE_LEN).

Прапорці IRQ

Виклик CAN.irq() реєструє обробник переривань для одного або кількох тригерів CAN.IRQ_RX, CAN.IRQ_TX і CAN.IRQ_STATE.

Функція повертає об’єкт IRQ, а виклик функції flags() на цьому об’єкті повертає ціле число, що вказує, яка подія (які події) спровокувала переривання. Обробник IRQ CAN повинен викликати функцію flags() повторно, доки вона не поверне 0.

Коли функція flags() повертається з встановленим бітом CAN.IRQ_TX, обробник також може перевірити наступні бітові прапорці в результаті для отримання додаткової інформації про подію TX:

  • Біт CAN.IRQ_TX_FAILED встановлений, якщо передавання завершилося невдачею. Як правило, це відбувається лише при виклику CAN.cancel_send(), хоча може статися й при переході контролера у стан помилки.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT — замаскована бітова область значення прапорців, що містить індекс буфера передавання, який згенерував подію. Це ціле число в діапазоні від 0 до CAN.TX_QUEUE_LEN (виключно), що відповідає результату попереднього виклику CAN.send().

Приклад IRQ_TX

from machine import CAN

def irq_send(can):
    while flags := can.irq().flags():
        if flags & can.IRQ_TX:
            idx = (flags >> can.IRQ_TX_IDX_SHIFT) & can.IRQ_TX_IDX_MASK
            success = not (flags & can.IRQ_TX_FAILED)
            print("irq_send", idx, success)

can = CAN(1, 500_000)
can.irq(irq_send, trigger=can.IRQ_TX, hard=True)

Важливо

Якщо встановлено тригер CAN.IRQ_TX, обробник повинен викликати flags() повторно, доки вона не поверне 0, як показано в цьому прикладі. В іншому випадку переривання CAN можуть бути неправильно повторно увімкнені.