clasa CAN – protocolul Controller Area Network

CAN este un protocol serial pe două fire, folosit pentru livrarea fiabilă, în timp real, a mesajelor între unul sau mai multe noduri conectate la o magistrală comună. CAN 2.0 a fost standardizat în ISO-11898 și este cunoscut acum și sub numele de CAN Classic.

Există, de asemenea, un protocol mai nou și compatibil cu versiunile anterioare, numit CAN FD (CAN with Flexible Data-Rate). Driverul machine.CAN nu acceptă în prezent funcțiile CAN FD; folosiți pyb.CAN pe STM32 dacă aveți nevoie de CAN FD.

Suportul CAN necesită un controler (adesea un periferic intern al microcontrolerului) și un transceiver extern care să adapteze nivelurile semnalelor pe magistrala CAN.

Disponibil pe camerele OpenMV bazate pe STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, plus variantele cu marca Arduino care includ un transceiver). Nu este încă acceptat pe OpenMV Cam RT1062 (portul mimxrt) sau OpenMV Cam AE3 (portul alif).

Interfața machine.CAN este o interfață de mesagerie CAN de bază, de nivel scăzut, care abstractizează un controler CAN sub forma unei cozi de prioritate de ieșire pentru trimiterea mesajelor, a unei cozi de intrare pentru primirea mesajelor și a unor mecanisme de raportare a erorilor.

Notă

Modulele micropython-lib can și aiocan planificate vor fi modalitatea recomandată de a folosi CAN cu MicroPython.

Constructor

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

Construiește un obiect controler CAN cu id-ul dat:

  • id identifică un anumit obiect controler CAN; depinde de placă și de port.

  • Toate celelalte argumente sunt transmise către CAN.init(). Trebuie furnizat cel puțin un argument (bitrate).

Versiunile viitoare ale acestei clase pot accepta aici și argumente cu cuvinte-cheie specifice portului, care configurează hardware-ul. În prezent nu sunt implementate astfel de argumente cu cuvinte-cheie.

Exemplu

Construiește și inițializează controlerul CAN 1 cu rata de biți de 500kbps:

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

Metode

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

Inițializează magistrala CAN cu parametrii dați:

  • bitrate este rata de biți dorită a magistralei, în biți pe secundă.

  • mode este una dintre valorile prezentate la Moduri, indicând modul de operare dorit. Valoarea implicită este operarea „normal” pe magistrală.

Următorii parametri sunt opționali și se referă la temporizările biților CAN. În majoritatea cazurilor puteți lăsa acești parametri la valorile implicite:

  • sample_point este un procentaj întreg din durata bitului de date. Specifică poziția eșantionării bitului în raport cu durata nominală totală a bitului. Driverul CAN va calcula parametrii în consecință. Acest parametru este ignorat dacă tseg1 și tseg2 sunt setate.

  • sjw este lățimea saltului de resincronizare în unități de cuante de timp pentru biții nominali; poate fi o valoare între 1 și 4 inclusiv pentru CAN clasic.

  • tseg1 definește poziția punctului de eșantionare în unități de cuante de timp pentru biții nominali; poate fi o valoare între 1 și 16 inclusiv pentru CAN clasic. Aceasta este suma fazelor Prop_Seg și Phase_Seg1 așa cum sunt definite în standardul ISO-11898. Dacă această valoare este setată, atunci tseg2 trebuie de asemenea setat, iar sample_point este ignorat.

  • tseg2 definește poziția punctului de transmisie în unități de cuante de timp pentru biții nominali; poate fi o valoare între 1 și 8 inclusiv pentru CAN clasic. Aceasta corespunde fazei Phase_Seg2 din standardul ISO-11898. Dacă această valoare este setată, atunci tseg1 trebuie de asemenea setat.

Dacă aceste argumente sunt specificate, atunci controlerul CAN este configurat corect pentru bitrate-ul dorit și pentru numărul total specificat de cuante de timp per bit. Valorile tseg1 și tseg2 au prioritate față de argumentul sample_point dacă toate acestea sunt furnizate.

Notă

Hardware-ul fiecărui controler poate avea restricții suplimentare privind valorile valide pentru acești parametri și va genera o eroare ValueError dacă o anumită valoare nu este acceptată.

Notă

Hardware-ul specific al controlerului poate accepta parametri opționali suplimentari cu cuvinte-cheie pentru funcții specifice hardware-ului, cum ar fi supraeșantionarea.

set_filters(filters: list | tuple | None) None

Setează filtrele de recepție în controlerul CAN. filters poate fi:

  • None pentru a accepta toate mesajele primite, sau

  • [] sau () pentru a dezactiva primirea tuturor mesajelor, sau

  • Un iterabil cu unul sau mai multe elemente care definesc criteriile de filtrare. Fiecare element trebuie să fie un tuplu sau o listă cu trei elemente:

    • identifier este un identificator CAN (int).

    • bit_mask este o mască de biți pentru biții din câmpul identificatorului CAN (int).

    • flags este un întreg cu zero sau mai mulți dintre biții definiți în Flag-uri de mesaj setați. Acesta specifică proprietățile pe care mesajul primit trebuie să le îndeplinească. Nu toate controlerele acceptă filtrarea pe toate flag-urile; se generează o eroare ValueError dacă se solicită un flag neacceptat.

Mesajele primite sunt acceptate dacă biții mascați în bit_mask se potrivesc între identificatorul mesajului și valoarea identifier a filtrului, iar flag-urile setate în filtru se potrivesc cu mesajul primit.

Dacă bitul CAN.FLAG_EXT_ID este setat în flags, filtrul se potrivește numai cu ID-uri CAN extinse. Dacă bitul CAN.FLAG_EXT_ID nu este setat, filtrul se potrivește numai cu ID-uri CAN standard.

Toate filtrele sunt combinate cu OR în controler. Transmiterea unei liste sau a unui tuplu gol pentru argumentul filters înseamnă că nu va fi primit niciun mesaj.

Unele controlere CAN necesită ca fiecare filtru să fie asociat cu un singur FIFO de recepție. În aceste cazuri, elementele filtrului din argument sunt alocate prin rotație (round-robin) către FIFO-urile disponibile. Acest driver nu face distincție între FIFO-uri în IRQ-ul de recepție.

Notă

Dacă apelantul transmite un iterabil cu mai multe elemente decât CAN.FILTERS_MAX, se va genera o eroare ValueError.

Notă

Dacă fie identifier, fie bit_mask se află în afara intervalului pentru tipul de ID specificat, se va genera o eroare ValueError cu motivul „invalid id”.

Exemple

Primește toate mesajele care sosesc:

can.set_filters(None)

Primește numai mesajele cu valorile ID standard 0x301 și 0x700:

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

Primește numai mesajele cu valori ID standard în intervalul 0x300-0x3FF și valoarea ID extins 0x50700:

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

Valoare constantă care indică numărul maxim de filtre de recepție acceptate pentru acest controler hardware.

Rețineți că unele controlere pot avea restricții hardware mai complexe privind numărul de filtre utilizate (de exemplu, numărarea independentă a filtrelor de ID standard și extins). În aceste cazuri, CAN.set_filters poate genera o eroare ValueError chiar și atunci când limita FILTERS_MAX nu este depășită.

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

Copiază un nou mesaj CAN în coada de transmisie hardware a controlerului pentru a fi trimis pe magistrală. Coada de transmisie este o coadă de prioritate sortată după prioritatea identificatorului CAN (identificatorii numerici mai mici au prioritate mai mare).

  • id este o valoare întreagă de identificator CAN.

  • data este un obiect bytes (sau similar) care conține datele mesajului CAN sau care descrie o cerere de transmisie la distanță (Remote Transmission Request, vezi mai jos).

  • flags este un întreg cu zero sau mai mulți dintre biții definiți în Flag-uri de mesaj setați, specificând proprietățile mesajului CAN de ieșire (ID extins, cerere de transmisie la distanță etc.)

Dacă mesajul este pus cu succes în coadă pentru transmisia pe magistrală, funcția returnează un întreg în intervalul 0 până la CAN.TX_QUEUE_LEN (exclusiv). Această valoare este indexul tamponului (buffer) de transmisie unde mesajul este pus în coadă pentru trimitere și poate fi folosită de funcția CAN.cancel_send și în evenimentele CAN.IRQ_TX.

Dacă coada este plină, atunci trimiterea va eșua și se returnează None.

Trimiterea poate eșua și returna None dacă valoarea id furnizată are aceeași prioritate ca un mesaj existent în coada de transmisie, iar hardware-ul controlerului CAN nu poate garanta că mesajele cu același ID vor fi trimise pe magistrală în aceeași ordine în care au fost adăugate în coadă. Pentru a pune totuși mesajul în coadă, transmiteți flag-ul CAN.FLAG_UNORDERED în argumentul flags. Acest flag indică faptul că este acceptabil ca mesajele cu același ID CAN să fie trimise pe magistrală în orice ordine.

Dacă controlerul se află în starea de eroare „Bus Off” sau este dezactivat, apelarea acestei funcții va genera o eroare OSError.

Notă

Această implementare intenționat de nivel scăzut este concepută astfel încât apelantul să poată stabili o coadă software de mesaje de ieșire.

Important

„Coada de transmisie” CAN nu este o coadă FIFO, ci este ordonată după prioritate și, deși poate conține până la CAN.TX_QUEUE_LEN elemente, pot exista alte restricții hardware privind mesajele care pot fi puse în coadă în același timp.

Cereri de transmisie la distanță (Remote Transmission Requests)

Dacă bitul CAN.FLAG_RTR este setat în argumentul flags, atunci controlerul va trimite o cerere de transmisie la distanță în loc de un mesaj. În acest caz, conținutul argumentului data este ignorat. Controlerul va trimite o cerere în care câmpul de lungime DLC este egal cu lungimea argumentului data.

Exemple

Încearcă să trimită un mesaj cu o sarcină utilă de trei octeți 0a0b0c și ID standard 0x200:

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

Încearcă să trimită un mesaj cu o sarcină utilă goală și ID extins 0x180008. Indică faptul că controlerul poate trimite mesaje cu acest ID în orice ordine, în cazul în care alte mesaje sunt deja în coadă pentru trimitere cu același ID:

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

Încearcă să trimită o cerere de transmisie la distanță cu lungimea de 8 octeți și ID standard 0x555:

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

Returnează un mesaj CAN care a fost primit de controler, în conformitate cu filtrele setate prin CAN.set_filters().

Această funcție acceptă un singur argument opțional; dacă este furnizat, atunci trebuie să fie o listă cu cel puțin 4 elemente, unde al doilea element este un obiect memoryview care se referă la un obiect bytearray sau similar, având capacitate suficientă pentru a conține orice mesaj CAN primit (8 octeți pentru CAN Classic, 64 de octeți pentru CAN FD). Lista furnizată va fi returnată ca rezultat în caz de succes și evită alocarea de memorie în interiorul funcției.

Dacă nu au fost primite mesaje de către controlerul CAN, această funcție returnează None.

Notă

CAN.set_filters trebuie apelată înainte ca orice mesaj să poată fi primit de controler. Pentru a primi toate mesajele, apelați set_filters(None).

Dacă un mesaj a fost primit de controlerul CAN, această funcție returnează o listă cu 4 elemente:

  • Indexul 0 este ID-ul CAN al mesajului primit, ca întreg.

  • Indexul 1 este un memoryview care oferă acces la datele mesajului primit.

    • Dacă arg nu este furnizat, atunci acesta este un memoryview care conține octeții care au fost primiți. Acest memoryview este susținut de un bytearray nou alocat, suficient de mare pentru a conține orice mesaj CAN primit. Acest lucru permite ca rezultatul să fie reutilizat în siguranță ca un viitor arg, pentru a economisi alocările de memorie.

    • Dacă arg este furnizat, atunci memoryview-ul furnizat va fi redimensionat pentru a conține exact octeții care au fost primiți. Apelantul este responsabil să se asigure că obiectul care susține memoryview-ul poate conține un mesaj CAN de orice lungime.

  • Indexul 2 este un întreg cu zero sau mai mulți dintre biții definiți în Flag-uri de mesaj setați. Acesta indică metadate despre mesajul primit.

  • Indexul 3 este un întreg cu zero sau mai mulți dintre biții definiți în Flag-uri de eroare la recepție setați. Orice valoare diferită de zero indică probleme potențiale la primirea mesajelor CAN. Aceste flag-uri sunt resetate în interiorul controlerului de fiecare dată când această funcție returnează.

Cereri de transmisie la distanță (Remote Transmission Requests)

Dacă se primește o cerere de transmisie la distanță, atunci bitul CAN.FLAG_RTR va fi setat în indexul 2, iar memoryview-ul de la indexul 1 va conține numai zerouri, cu o lungime egală cu câmpul DLC al cererii primite.

Exemplu
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

Setează o funcție handler de întrerupere care să fie apelată atunci când a avut loc unul sau mai multe dintre evenimentele marcate în trigger.

  • handler este o funcție care va fi apelată atunci când se declanșează evenimentul de întrerupere. Handler-ul trebuie să accepte exact un argument, care este instanța CAN.

  • trigger configurează evenimentul (evenimentele) care pot genera o întrerupere. Valorile posibile sunt o mască formată din unul sau mai multe dintre următoarele:

    • Evenimentul CAN.IRQ_RX apare după ce controlerul CAN a primit cel puțin un mesaj în FIFO-ul său RX (ceea ce înseamnă că CAN.recv() va returna cu succes).

    • Evenimentul CAN.IRQ_TX apare după ce controlerul CAN fie a trimis cu succes un mesaj pe magistrala CAN, fie nu a reușit să trimită un mesaj. Acest declanșator are cerințe suplimentare pentru handler, vezi Flag-uri IRQ pentru detalii.

    • Evenimentul CAN.IRQ_STATE apare atunci când controlerul CAN a trecut într-o stare de eroare mai gravă. Apelați CAN.state() pentru a obține starea actualizată.

  • hard dacă este True, se folosește o întrerupere hard. Aceasta reduce întârzierea dintre evenimentul controlerului CAN și apelarea handler-ului. Handler-ele de întrerupere hard nu pot aloca memorie; vezi Scrierea handlerelor de întrerupere.

Returnează un obiect irq. Dacă este apelată fără argumente, atunci se returnează un obiect irq configurat anterior.

Vezi Flag-uri IRQ pentru un exemplu.

cancel_send(index: int) bool

Solicită controlerului CAN să anuleze trimiterea unui mesaj pe magistrală.

Argumentul index identifică un singur tampon de transmisie. Trebuie să fie un întreg în intervalul 0 până la CAN.TX_QUEUE_LEN (exclusiv). În general, aceasta va fi o valoare returnată anterior de CAN.send().

Rezultatul este True dacă un mesaj era în așteptare pentru transmisie în acest tampon și transmisia a fost anulată.

Rezultatul este False în caz contrar (fie niciun mesaj nu era în așteptare pentru transmisie în acest tampon, fie transmisia a reușit deja).

Evenimentul IRQ CAN.IRQ_TX ar trebui folosit pentru a determina dacă un mesaj a fost cu siguranță trimis sau nu, dar rețineți că există condiții potențiale de cursă (race) dacă o transmisie este anulată și apoi același tampon este folosit pentru a trimite un alt mesaj (mai ales dacă IRQ-ul controlerului CAN nu este „hard”).

state() int

Returnează o valoare întreagă care indică starea curentă a controlerului. Valoarea va fi una dintre valorile definite în Stări.

Stările de eroare cu severitate mai redusă se pot șterge automat dacă magistrala își revine, dar starea CAN.STATE_BUS_OFF poate fi recuperată numai prin apelarea CAN.restart().

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

Returnează valorile contoarelor de erori ale controlerului. Rezultatul este o listă cu opt valori. Dacă parametrul opțional list este specificat, atunci obiectul listă furnizat este actualizat și returnat ca rezultat, pentru a evita o alocare.

Elementele listei sunt:

  • valoarea TEC (Transmit Error Counter)

  • valoarea REC (Receive Error Counter)

  • Numărul de dăți în care controlerul a intrat în starea Warning din starea Active.

  • Numărul de dăți în care controlerul a intrat în starea Error Passive din starea Warning.

  • Numărul de dăți în care controlerul a intrat în starea Bus Off din starea Error Passive.

  • Numărul total de mesaje TX în așteptare în coada hardware.

  • Numărul total de mesaje RX în așteptare în coada hardware.

  • Numărul de dăți în care a avut loc o depășire (overrun) la recepție RX.

Notă

În funcție de controler, aceste valori pot reveni prin depășire la 0 după o anumită valoare.

Notă

Dacă un controler nu acceptă un anumit contor, va returna None pentru acel element din listă.

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

Returnează o listă de elemente care indică temporizările configurate în prezent în controlerul CAN. Aceasta poate fi folosită pentru a verifica temporizările în scopuri de depanare. Rezultatul este o listă cu șase valori. Dacă parametrul opțional list este specificat, atunci obiectul listă furnizat este actualizat și returnat ca rezultat, pentru a evita o alocare.

Elementele listei sunt:

  • Rata de biți exactă folosită de controler. Poate diferi de argumentul bitrate transmis către CAN.init() din cauza cuantizării necesare pentru a respecta constrângerile hardware.

  • Lățimea saltului de resincronizare (SJW) în unități de cuante de timp pentru biții nominali. Are aceeași semnificație ca parametrul sjw al CAN.init().

  • Poziția punctului de eșantionare în unități de cuante de timp pentru biții nominali. Are aceeași semnificație ca parametrul tseg1 al CAN.init().

  • Poziția punctului de transmisie în unități de cuante de timp pentru biții nominali. Are aceeași semnificație ca parametrul tseg2 al CAN.init().

  • Informații de temporizare CAN FD. None pentru controlerele care nu acceptă CAN FD sau dacă CAN FD nu este inițializat. În caz contrar, o listă imbricată de patru elemente corespunzătoare elementelor de mai sus, dar aplicabile funcției CAN FD BRS.

  • Informații de temporizare opționale, specifice controlerului. În funcție de controler, aceasta va fi fie None dacă controlerul nu raportează nimic, fie o listă cu lungime constantă ale cărei elemente sunt specifice unui anumit controler hardware.

Notă

Dacă CAN.init() nu a fost apelată, atunci această funcție returnează totuși un rezultat, dar rezultatul depinde de interiorul controlerului și poate să nu fie exact.

restart() None

Determină controlerul să iasă din starea STATE_BUS_OFF fără a șterge nicio altă stare internă. De asemenea, șterge unele dintre contoarele de erori (întotdeauna numărul de dăți în care a fost introdusă fiecare stare de eroare, eventual TEC și REC în funcție de controler).

Apelarea acestei funcții anulează, de asemenea, orice mesaje care așteaptă să fie trimise. Nu se livrează întreruperi IRQ_TX pentru aceste mesaje.

Rețineți că această funcție poate sau nu să determine controlerul să iasă din starea „Error Passive”, în funcție de faptul dacă hardware-ul controlerului anulează TEC și REC sau nu.

deinit() None

Dezinițializează o instanță CAN activă anterior. Toate mesajele în așteptare (de transmisie și de recepție) sunt eliminate, iar controlerul încetează să interacționeze pe magistrală. Pentru a folosi din nou această instanță, apelați CAN.init().

Nu se apelează nicio întrerupere IRQ_TX sau IRQ_RX ca răspuns la apelarea acestei funcții.

Vezi de asemenea CAN.restart().

Constante

TX_QUEUE_LEN: int

Numărul maxim de mesaje CAN care pot fi puse în coada hardware de mesaje de ieșire a controlerului. „Indecșii tamponului de transmisie” folosiți de CAN.send(), CAN.cancel_send() și Flag-uri IRQ se vor afla în acest interval.

Moduri

Aceste valori reprezintă modurile de operare ale controlerului, așa cum sunt transmise către CAN.init(). Nu toate controlerele pot accepta toate modurile.

Schimbarea modului unui controler aflat în funcțiune necesită apelarea CAN.deinit() și apoi apelarea din nou a CAN.init() cu noul mod.

MODE_NORMAL: int

Controlerul este activ ca un nod de rețea CAN standard (va confirma mesajele valide și poate transmite erori în funcție de Starea sa curentă).

MODE_SLEEP: int

Controlerul CAN este în repaus într-un mod de consum redus de energie. În funcție de controler, acest mod poate permite trezirea controlerului și trecerea la CAN.MODE_NORMAL dacă se primește trafic CAN.

MODE_LOOPBACK: int

Un mod de testare. Controlerul CAN este încă conectat la magistrala externă, dar va primi și propriile sale mesaje transmise și va ignora orice erori de ACK.

MODE_SILENT: int

Controlerul CAN primește mesaje, dar nu interacționează cu magistrala CAN (inclusiv trimiterea de ACK-uri, erori etc.)

MODE_SILENT_LOOPBACK: int

Un mod de testare care nu necesită deloc conectarea unui transceiver CAN. Controlerul CAN primește propriile sale mesaje transmise fără a interacționa deloc cu magistrala CAN. Pinii CAN TX și RX rămân inactivi.

Stări

Aceste valori sunt returnate de CAN.state() și reflectă starea de eroare a controlerului CAN:

STATE_STOPPED: int

Controlerul nu a fost inițializat.

STATE_ACTIVE: int

Controlerul este activ, iar contoarele de erori TEC și REC sunt ambele sub pragul de avertizare de 96. Vezi CAN.get_counters().

STATE_WARNING: int

Controlerul este activ, dar cel puțin unul dintre contoarele de erori TEC și REC este între 96 și 127. Vezi CAN.get_counters().

STATE_PASSIVE: int

Controlerul se află în starea „Error Passive”, ceea ce înseamnă că nu mai transmite erori active pe magistrală, dar este altfel funcțional. Această stare este introdusă atunci când cel puțin unul dintre contoarele de erori TEC și REC este 128 sau mai mare, dar TEC este mai mic de 255. Vezi CAN.get_counters().

STATE_BUS_OFF: int

Controlerul se află în starea Bus-Off, ceea ce înseamnă că contorul de erori TEC este mai mare de 255. Controlerul CAN nu va interacționa cu magistrala în această stare și trebuie repornit prin CAN.restart() pentru a continua.

Flag-uri de mesaj

Aceste valori reprezintă metadate despre un mesaj CAN. Funcțiile CAN.send(), CAN.recv() și CAN.set_filters() fie acceptă, fie returnează o valoare întreagă alcătuită din zero sau mai multe dintre aceste flag-uri combinate prin OR la nivel de bit.

FLAG_RTR: int

Indică faptul că un mesaj este o cerere de transmisie la distanță.

FLAG_EXT_ID: int

Dacă este setat, indică faptul că un identificator de mesaj este extins (29 de biți). Dacă nu este setat, indică faptul că un identificator de mesaj este standard (11 biți).

FLAG_UNORDERED: int

Dacă este setat în argumentul flags al CAN.send(), indică faptul că este acceptabil ca mesajele cu același ID CAN să fie trimise pe magistrală în orice ordine.

În caz contrar, încercarea de a pune în coadă mai multe mesaje cu același ID poate duce la eșecul CAN.send() dacă hardware-ul controlerului nu poate impune ordinea.

Acest flag nu este niciodată setat pe mesajele primite și este ignorat de CAN.set_filters().

Flag-uri de eroare la recepție

Rezultatul CAN.recv() include o valoare întreagă alcătuită din zero sau mai multe dintre aceste flag-uri combinate prin OR la nivel de bit. Dacă sunt setate, aceste flag-uri indică probleme generale potențiale la primirea mesajelor CAN.

RECV_ERR_FULL: int

FIFO-ul hardware în care a fost primit acest mesaj este plin, iar mesajele suplimentare care sosesc pot fi pierdute.

RECV_ERR_OVERRUN: int

FIFO-ul hardware în care a fost primit acest mesaj este plin, iar unul sau mai multe mesaje care soseau au fost pierdute.

Valori IRQ

IRQ_RX: int

Transmiteți către argumentul trigger al irq() pentru a declanșa handler-ul de fiecare dată când controlerul CAN a primit un mesaj complet în FIFO-ul RX. În interiorul handler-ului, citiți mesajul cu recv().

IRQ_TX: int

Transmiteți către argumentul trigger al irq() pentru a declanșa handler-ul de fiecare dată când controlerul CAN finalizează o încercare de transmisie (reușită sau eșuată). În interiorul handler-ului, folosiți biții suplimentari de mai jos pentru a determina care căsuță poștală (mailbox) s-a finalizat și dacă a eșuat – vezi Flag-uri IRQ.

IRQ_STATE: int

Transmiteți către argumentul trigger al irq() pentru a declanșa handler-ul de fiecare dată când controlerul trece între valorile STATE_* (active / warning / passive / bus-off). Folosiți state() în interiorul handler-ului pentru a citi noua stare.

IRQ_TX_FAILED: int

Flag de stare care poate fi setat în irq().flags() atunci când se declanșează un eveniment IRQ_TX. Indică faptul că încercarea de transmisie a eșuat (de obicei pentru că a fost apelată cancel_send() sau pentru că controlerul a intrat într-o stare de eroare).

IRQ_TX_IDX_SHIFT: int

Poziția bitului câmpului index-căsuță-poștală-de-transmisie din valoarea irq().flags() în timpul unui eveniment IRQ_TX. Indexul căsuței poștale este extras ca (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.

IRQ_TX_IDX_MASK: int

Masca de biți a câmpului index-căsuță-poștală-de-transmisie din valoarea irq().flags() în timpul unui eveniment IRQ_TX. Indexul extras corespunde întregului returnat de apelul send() corespunzător (un int în intervalul 0 până la TX_QUEUE_LEN).

Flag-uri IRQ

Apelarea CAN.irq() înregistrează un handler de întrerupere cu unul sau mai multe dintre declanșatoarele CAN.IRQ_RX, CAN.IRQ_TX și CAN.IRQ_STATE.

Funcția returnează un obiect IRQ, iar apelarea funcției flags() pe acest obiect returnează un întreg care indică ce eveniment(e) declanșator(oare) au declanșat întreruperea. Un handler de IRQ CAN ar trebui să apeleze funcția flags() în mod repetat până când aceasta returnează 0.

Atunci când funcția flags() returnează cu bitul CAN.IRQ_TX setat, handler-ul poate verifica de asemenea următorii biți de flag din rezultat pentru informații suplimentare despre evenimentul TX:

  • Bitul CAN.IRQ_TX_FAILED este setat dacă transmisia a eșuat. De obicei, acest lucru se va întâmpla numai dacă a fost apelată CAN.cancel_send(), deși se poate întâmpla și dacă controlerul intră într-o stare de eroare.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT este o regiune mascată cu biți a valorii flags care conține indexul tamponului de transmisie care a generat evenimentul. Acesta va fi un întreg în intervalul 0 până la CAN.TX_QUEUE_LEN (exclusiv) și va corespunde rezultatului unui apel anterior la CAN.send().

Exemplu 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)

Important

Dacă declanșatorul CAN.IRQ_TX este setat, atunci handler-ul trebuie să apeleze flags() în mod repetat până când acesta returnează 0, așa cum se arată în acest exemplu. În caz contrar, este posibil ca întreruperile CAN să nu fie reactivate corect.