klasa CAN – protokół Controller Area Network

CAN to dwuprzewodowy protokół szeregowy używany do niezawodnego dostarczania komunikatów w czasie rzeczywistym pomiędzy jednym lub wieloma węzłami podłączonymi do wspólnej magistrali. CAN 2.0 został znormalizowany w ISO-11898 i obecnie znany jest również jako CAN Classic.

Istnieje także nowszy, wstecznie zgodny protokół o nazwie CAN FD (CAN with Flexible Data-Rate). Sterownik machine.CAN nie obsługuje obecnie funkcji CAN FD; jeśli potrzebujesz CAN FD, użyj pyb.CAN na STM32.

Obsługa CAN wymaga kontrolera (często wewnętrznego peryferium mikrokontrolera) oraz zewnętrznego transceivera, który dostosowuje poziomy sygnałów do magistrali CAN.

Dostępne na kamerach OpenMV opartych na STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, a także wariantach marki Arduino, które mają wbudowany transceiver). Nieobsługiwane jeszcze na OpenMV Cam RT1062 (port mimxrt) ani na OpenMV Cam AE3 (port alif).

Interfejs machine.CAN to niskopoziomowy, podstawowy interfejs do przesyłania komunikatów CAN, który przedstawia kontroler CAN jako wychodzącą kolejkę priorytetową do wysyłania komunikatów, przychodzącą kolejkę do odbierania komunikatów oraz mechanizmy zgłaszania błędów.

Informacja

Planowane moduły can i aiocan z micropython-lib będą zalecanym sposobem korzystania z CAN w MicroPython.

Konstruktor

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

Tworzy obiekt kontrolera CAN o podanym identyfikatorze:

  • id identyfikuje konkretny obiekt kontrolera CAN; jest zależny od płytki i portu.

  • Wszystkie pozostałe argumenty są przekazywane do CAN.init(). Należy podać co najmniej jeden argument (bitrate).

Przyszłe wersje tej klasy mogą również przyjmować tutaj specyficzne dla portu argumenty nazwane, które konfigurują sprzęt. Obecnie żadne takie argumenty nazwane nie są zaimplementowane.

Przykład

Utwórz i zainicjalizuj kontroler CAN 1 z przepływnością 500 kb/s:

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

Metody

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

Inicjalizuje magistralę CAN z podanymi parametrami:

  • bitrate to żądana szybkość transmisji magistrali w bitach na sekundę.

  • mode to jedna z wartości pokazanych w Tryby, wskazująca żądany tryb pracy. Domyślnie jest to „normalna” praca na magistrali.

Kolejne parametry są opcjonalne i dotyczą taktowania bitów CAN. W większości przypadków można pozostawić te parametry ustawione na wartości domyślne:

  • sample_point to całkowita wartość procentowa czasu trwania bitu danych. Określa położenie próbkowania bitu względem całego nominalnego czasu trwania bitu. Sterownik CAN odpowiednio obliczy parametry. Ten parametr jest ignorowany, jeśli ustawiono tseg1 i tseg2.

  • sjw to szerokość skoku resynchronizacji w jednostkach kwantów czasu dla bitów nominalnych; dla klasycznego CAN może przyjmować wartość od 1 do 4 włącznie.

  • tseg1 definiuje położenie punktu próbkowania w jednostkach kwantów czasu dla bitów nominalnych; dla klasycznego CAN może przyjmować wartość od 1 do 16 włącznie. Jest to suma faz Prop_Seg i Phase_Seg1 zdefiniowanych w normie ISO-11898. Jeśli ta wartość jest ustawiona, to tseg2 również musi być ustawione, a sample_point jest ignorowane.

  • tseg2 definiuje położenie punktu nadawania w jednostkach kwantów czasu dla bitów nominalnych; dla klasycznego CAN może przyjmować wartość od 1 do 8 włącznie. Odpowiada to Phase_Seg2 w normie ISO-11898. Jeśli ta wartość jest ustawiona, to tseg1 również musi być ustawione.

Jeśli te argumenty są podane, kontroler CAN jest poprawnie skonfigurowany dla żądanej wartości bitrate oraz określonej całkowitej liczby kwantów czasu na bit. Wartości tseg1 i tseg2 nadpisują argument sample_point, jeśli wszystkie z nich są podane.

Informacja

Konkretny sprzęt kontrolera może mieć dodatkowe ograniczenia dotyczące dopuszczalnych wartości tych parametrów i zgłosi ValueError, jeśli dana wartość nie jest obsługiwana.

Informacja

Konkretny sprzęt kontrolera może przyjmować dodatkowe opcjonalne argumenty nazwane dla funkcji specyficznych dla sprzętu, takich jak nadpróbkowanie.

set_filters(filters: list | tuple | None) None

Ustawia filtry odbioru w kontrolerze CAN. filters może być:

  • None, aby akceptować wszystkie przychodzące komunikaty, lub

  • [] lub (), aby wyłączyć odbiór wszystkich komunikatów, lub

  • obiektem iterowalnym zawierającym jeden lub więcej elementów definiujących kryteria filtrowania. Każdy element powinien być krotką lub listą z trzema elementami:

    • identifier to identyfikator CAN (int).

    • bit_mask to maska bitów dla bitów w polu identyfikatora CAN (int).

    • flags to liczba całkowita z zerem lub więcej ustawionych bitów zdefiniowanych w Flagi komunikatów. Określa właściwości, którym musi odpowiadać przychodzący komunikat. Nie wszystkie kontrolery obsługują filtrowanie po wszystkich flagach; jeśli zażądano nieobsługiwanej flagi, zgłaszany jest ValueError.

Przychodzące komunikaty są akceptowane, jeśli bity zamaskowane w bit_mask są zgodne pomiędzy identyfikatorem komunikatu a wartością identifier filtra, a flagi ustawione w filtrze pasują do przychodzącego komunikatu.

Jeśli bit CAN.FLAG_EXT_ID jest ustawiony we flagach, filtr dopasowuje wyłącznie rozszerzone identyfikatory CAN (Extended). Jeśli bit CAN.FLAG_EXT_ID nie jest ustawiony, filtr dopasowuje wyłącznie standardowe identyfikatory CAN (Standard).

Wszystkie filtry są w kontrolerze łączone operacją OR. Przekazanie pustej listy lub krotki jako argumentu filtrów oznacza, że żadne komunikaty nie będą odbierane.

Niektóre kontrolery CAN wymagają, aby każdy filtr był powiązany tylko z jednym odbiorczym FIFO. W takich przypadkach elementy filtra z argumentu są przydzielane do dostępnych kolejek FIFO metodą round-robin. Ten sterownik nie rozróżnia kolejek FIFO w odbiorczym IRQ.

Informacja

Jeśli wywołujący przekaże obiekt iterowalny z większą liczbą elementów niż CAN.FILTERS_MAX, zgłoszony zostanie ValueError.

Informacja

Jeśli identifier lub bit_mask jest poza zakresem dla określonego typu ID, zgłoszony zostanie ValueError z powodem „invalid id”.

Przykłady

Odbieraj wszystkie przychodzące komunikaty:

can.set_filters(None)

Odbieraj tylko komunikaty ze standardowymi wartościami ID 0x301 i 0x700:

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

Odbieraj tylko komunikaty ze standardowymi wartościami ID z zakresu 0x300-0x3FF oraz z rozszerzoną wartością ID 0x50700:

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

Stała, której odczyt zwraca maksymalną liczbę obsługiwanych filtrów odbioru dla tego sprzętowego kontrolera.

Należy pamiętać, że niektóre kontrolery mogą mieć bardziej złożone sprzętowe ograniczenia dotyczące liczby używanych filtrów (na przykład zliczając niezależnie filtry standardowych i rozszerzonych ID). W takich przypadkach CAN.set_filters może zgłosić ValueError nawet wtedy, gdy limit FILTERS_MAX nie został przekroczony.

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

Kopiuje nowy komunikat CAN do sprzętowej kolejki nadawczej kontrolera w celu wysłania go na magistralę. Kolejka nadawcza to kolejka priorytetowa posortowana według priorytetu identyfikatora CAN (niższe numerycznie identyfikatory mają wyższy priorytet).

  • id to całkowita wartość identyfikatora CAN.

  • data to obiekt bytes (lub podobny) zawierający dane komunikatu CAN lub opisujący żądanie zdalnej transmisji (Remote Transmission Request, patrz niżej).

  • flags to liczba całkowita z zerem lub więcej ustawionych bitów zdefiniowanych w Flagi komunikatów, określająca właściwości wychodzącego komunikatu CAN (rozszerzony ID, żądanie zdalnej transmisji itp.).

Jeśli komunikat zostanie pomyślnie umieszczony w kolejce do wysłania na magistralę, funkcja zwraca liczbę całkowitą z zakresu od 0 do CAN.TX_QUEUE_LEN (wyłącznie). Ta wartość to indeks bufora nadawczego, w którym komunikat został umieszczony do wysłania, i może być użyta przez funkcję CAN.cancel_send oraz w zdarzeniach CAN.IRQ_TX.

Jeśli kolejka jest pełna, wysłanie się nie powiedzie i zwracane jest None.

Wysłanie może się również nie powieść i zwrócić None, jeśli podana wartość id ma taki sam priorytet jak istniejący komunikat w kolejce nadawczej, a sprzęt kontrolera CAN nie może zagwarantować, że komunikaty o tym samym ID zostaną wysłane na magistralę w tej samej kolejności, w jakiej zostały dodane do kolejki. Aby mimo to umieścić komunikat w kolejce, przekaż flagę CAN.FLAG_UNORDERED w argumencie flags. Ta flaga wskazuje, że można wysyłać komunikaty o tym samym ID CAN na magistralę w dowolnej kolejności.

Jeśli kontroler jest w stanie błędu „Bus Off” lub jest wyłączony, wywołanie tej funkcji zgłosi OSError.

Informacja

Ta celowo niskopoziomowa implementacja jest zaprojektowana tak, aby wywołujący mógł utworzyć programową kolejkę komunikatów wychodzących.

Ważne

„Kolejka nadawcza” CAN nie jest kolejką FIFO, jest uporządkowana priorytetowo i chociaż może pomieścić do CAN.TX_QUEUE_LEN elementów, mogą istnieć inne sprzętowe ograniczenia dotyczące komunikatów, które można umieścić w kolejce jednocześnie.

Żądania zdalnej transmisji (Remote Transmission Requests)

Jeśli bit CAN.FLAG_RTR jest ustawiony w argumencie flags, kontroler wyśle żądanie zdalnej transmisji zamiast komunikatu. W tym przypadku zawartość argumentu data jest ignorowana. Kontroler wyśle żądanie, w którym pole długości DLC jest równe długości argumentu data.

Przykłady

Próba wysłania komunikatu z trzybajtową zawartością 0a0b0c i standardowym ID 0x200:

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

Próba wysłania komunikatu z pustą zawartością i rozszerzonym ID 0x180008. Wskaż, że kontroler może wysyłać komunikaty o tym ID w dowolnej kolejności, na wypadek gdyby inne komunikaty o tym samym ID były już w kolejce do wysłania:

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

Próba wysłania żądania zdalnej transmisji o długości 8 bajtów i standardowym ID 0x555:

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

Zwraca komunikat CAN, który został odebrany przez kontroler, zgodnie z filtrami ustawionymi przez CAN.set_filters().

Ta funkcja przyjmuje jeden opcjonalny argument; jeśli jest podany, musi być listą o co najmniej 4 elementach, w której drugim elementem jest obiekt memoryview odwołujący się do obiektu bytearray lub podobnego, który ma wystarczającą pojemność, aby pomieścić dowolny odebrany komunikat CAN (8 bajtów dla CAN Classic, 64 bajty dla CAN FD). Podana lista zostanie zwrócona jako pomyślny wynik, co pozwala uniknąć alokacji pamięci wewnątrz funkcji.

Jeśli kontroler CAN nie odebrał żadnych komunikatów, ta funkcja zwraca None.

Informacja

Funkcja CAN.set_filters musi zostać wywołana, zanim kontroler będzie mógł odebrać jakiekolwiek komunikaty. Aby odbierać wszystkie komunikaty, wywołaj set_filters(None).

Jeśli kontroler CAN odebrał komunikat, ta funkcja zwraca listę z 4 elementami:

  • Indeks 0 to ID CAN odebranego komunikatu jako liczba całkowita.

  • Indeks 1 to memoryview zapewniający dostęp do danych odebranego komunikatu.

    • Jeśli arg nie jest podany, jest to memoryview przechowujący odebrane bajty. Ten memoryview jest oparty na nowo zaalokowanym obiekcie bytearray, wystarczająco dużym, aby pomieścić dowolny odebrany komunikat CAN. Pozwala to bezpiecznie ponownie wykorzystać wynik jako przyszły arg, aby zaoszczędzić na alokacjach pamięci.

    • Jeśli arg jest podany, podany memoryview zostanie zmieniony tak, aby pomieścił dokładnie odebrane bajty. Wywołujący jest odpowiedzialny za upewnienie się, że obiekt bazowy dla memoryview może pomieścić komunikat CAN o dowolnej długości.

  • Indeks 2 to liczba całkowita z zerem lub więcej ustawionych bitów zdefiniowanych w Flagi komunikatów. Wskazuje metadane dotyczące odebranego komunikatu.

  • Indeks 3 to liczba całkowita z zerem lub więcej ustawionych bitów zdefiniowanych w Flagi błędów odbioru. Każda wartość niezerowa wskazuje potencjalne problemy podczas odbierania komunikatów CAN. Te flagi są resetowane wewnątrz kontrolera za każdym razem, gdy ta funkcja zwraca wynik.

Żądania zdalnej transmisji (Remote Transmission Requests)

Jeśli odebrano żądanie zdalnej transmisji, bit CAN.FLAG_RTR zostanie ustawiony w indeksie 2, a memoryview w indeksie 1 będzie zawierać same zera, o długości równej polu DLC odebranego żądania.

Przykład
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

Ustawia funkcję obsługi przerwań handler, która ma być wywoływana, gdy wystąpi jedno lub więcej zdarzeń oznaczonych w trigger.

  • handler to funkcja wywoływana po wyzwoleniu zdarzenia przerwania. Funkcja obsługi musi przyjmować dokładnie jeden argument, którym jest instancja CAN.

  • trigger konfiguruje zdarzenie lub zdarzenia, które mogą generować przerwanie. Możliwe wartości to maska jednego lub więcej z następujących:

    • Zdarzenie CAN.IRQ_RX występuje po tym, jak kontroler CAN odebrał co najmniej jeden komunikat do swojego FIFO RX (co oznacza, że CAN.recv() zwróci wynik pomyślnie).

    • Zdarzenie CAN.IRQ_TX występuje po tym, jak kontroler CAN albo pomyślnie wysłał komunikat na magistralę CAN, albo nie udało mu się wysłać komunikatu. Ten wyzwalacz ma dodatkowe wymagania wobec funkcji obsługi, szczegóły w Flagi IRQ.

    • Zdarzenie CAN.IRQ_STATE występuje, gdy kontroler CAN przeszedł do poważniejszego stanu błędu. Wywołaj CAN.state(), aby uzyskać zaktualizowany stan.

  • hard jeśli True, używane jest przerwanie sprzętowe (hard). Zmniejsza to opóźnienie pomiędzy zdarzeniem kontrolera CAN a wywołaniem funkcji obsługi. Sprzętowe funkcje obsługi przerwań nie mogą alokować pamięci; patrz Pisanie procedur obsługi przerwań.

Zwraca obiekt irq. Jeśli wywołano bez argumentów, zwracany jest wcześniej skonfigurowany obiekt irq.

Przykład znajduje się w Flagi IRQ.

cancel_send(index: int) bool

Żąda od kontrolera CAN anulowania wysyłania komunikatu na magistralę.

Argument index identyfikuje pojedynczy bufor nadawczy. Powinien być liczbą całkowitą z zakresu od 0 do CAN.TX_QUEUE_LEN (wyłącznie). Zwykle będzie to wartość zwrócona wcześniej przez CAN.send().

Wynikiem jest True, jeśli w tym buforze oczekiwał komunikat do wysłania, a jego transmisja została anulowana.

W przeciwnym razie wynikiem jest False (albo w tym buforze nie oczekiwał żaden komunikat do wysłania, albo transmisja już się powiodła).

Zdarzenie IRQ CAN.IRQ_TX powinno być używane do ustalenia, czy komunikat został na pewno wysłany, czy nie, ale należy pamiętać o potencjalnych sytuacjach wyścigu, jeśli transmisja zostanie anulowana, a następnie ten sam bufor zostanie użyty do wysłania kolejnego komunikatu (zwłaszcza jeśli IRQ kontrolera CAN nie jest sprzętowe „hard”).

state() int

Zwraca liczbę całkowitą wskazującą bieżący stan kontrolera. Wartość będzie jedną z wartości zdefiniowanych w Stany.

Stany błędów o niższej wadze mogą zostać automatycznie wyczyszczone, jeśli magistrala odzyska sprawność, ale ze stanu CAN.STATE_BUS_OFF można wyjść tylko przez wywołanie CAN.restart().

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

Zwraca wartości liczników błędów kontrolera. Wynikiem jest lista ośmiu wartości. Jeśli podano opcjonalny parametr list, podany obiekt listy jest aktualizowany i zwracany jako wynik, aby uniknąć alokacji.

Elementy listy to:

  • wartość TEC (licznik błędów nadawania, Transmit Error Counter)

  • wartość REC (licznik błędów odbioru, Receive Error Counter)

  • Liczba przejść kontrolera ze stanu Active do stanu Warning.

  • Liczba przejść kontrolera ze stanu Warning do stanu Error Passive.

  • Liczba przejść kontrolera ze stanu Error Passive do stanu Bus Off.

  • Całkowita liczba oczekujących komunikatów TX w kolejce sprzętowej.

  • Całkowita liczba oczekujących komunikatów RX w kolejce sprzętowej.

  • Liczba wystąpień przepełnienia RX (overrun).

Informacja

W zależności od kontrolera, te wartości mogą po osiągnięciu pewnej wartości przepełnić się z powrotem do 0.

Informacja

Jeśli kontroler nie obsługuje danego licznika, dla tego elementu listy zwróci None.

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

Zwraca listę elementów wskazujących bieżące taktowania skonfigurowane w kontrolerze CAN. Można jej użyć do zweryfikowania taktowań w celach diagnostycznych. Wynikiem jest lista sześciu wartości. Jeśli podano opcjonalny parametr list, podany obiekt listy jest aktualizowany i zwracany jako wynik, aby uniknąć alokacji.

Elementy listy to:

  • Dokładna przepływność używana przez kontroler. Może różnić się od argumentu bitrate przekazanego do CAN.init() z powodu kwantyzacji wymaganej do spełnienia ograniczeń sprzętowych.

  • Szerokość skoku resynchronizacji (SJW) w jednostkach kwantów czasu dla bitów nominalnych. Ma takie samo znaczenie jak parametr sjw funkcji CAN.init().

  • Położenie punktu próbkowania w jednostkach kwantów czasu dla bitów nominalnych. Ma takie samo znaczenie jak parametr tseg1 funkcji CAN.init().

  • Położenie punktu nadawania w jednostkach kwantów czasu dla bitów nominalnych. Ma takie samo znaczenie jak parametr tseg2 funkcji CAN.init().

  • Informacje o taktowaniu CAN FD. None dla kontrolerów, które nie obsługują CAN FD, lub jeśli CAN FD nie zostało zainicjalizowane. W przeciwnym razie zagnieżdżona lista czterech elementów odpowiadających powyższym pozycjom, ale mających zastosowanie do funkcji BRS CAN FD.

  • Opcjonalne informacje o taktowaniu specyficzne dla kontrolera. W zależności od kontrolera będzie to albo None, jeśli kontroler niczego nie zgłasza, albo lista o stałej długości, której elementy są specyficzne dla konkretnego sprzętowego kontrolera.

Informacja

Jeśli CAN.init() nie zostało wywołane, ta funkcja nadal zwraca wynik, ale wynik zależy od wewnętrznych mechanizmów kontrolera i może nie być dokładny.

restart() None

Powoduje wyjście kontrolera ze stanu STATE_BUS_OFF bez czyszczenia żadnego innego stanu wewnętrznego. Czyści również niektóre liczniki błędów (zawsze liczbę przejść do każdego stanu błędu, a w zależności od kontrolera ewentualnie TEC i REC).

Wywołanie tej funkcji anuluje również wszystkie komunikaty oczekujące na wysłanie. Dla tych komunikatów nie są dostarczane żadne przerwania IRQ_TX.

Należy pamiętać, że ta funkcja może, ale nie musi, spowodować wyjście kontrolera ze stanu „Error Passive”, w zależności od tego, czy sprzęt kontrolera zeruje TEC i REC, czy nie.

deinit() None

Deinicjalizuje wcześniej aktywną instancję CAN. Wszystkie oczekujące komunikaty (nadawane i odbierane) są odrzucane, a kontroler przestaje interakcję z magistralą. Aby ponownie użyć tej instancji, wywołaj CAN.init().

W odpowiedzi na wywołanie tej funkcji nie są wywoływane żadne przerwania IRQ_TX ani IRQ_RX.

Patrz także CAN.restart().

Stałe

TX_QUEUE_LEN: int

Maksymalna liczba komunikatów CAN, które można umieścić w wychodzącej sprzętowej kolejce komunikatów kontrolera. „Indeksy bufora nadawczego” używane przez CAN.send(), CAN.cancel_send() i Flagi IRQ będą mieścić się w tym zakresie.

Tryby

Te wartości reprezentują tryby pracy kontrolera, przekazywane do CAN.init(). Nie wszystkie kontrolery muszą obsługiwać wszystkie tryby.

Zmiana trybu działającego kontrolera wymaga wywołania CAN.deinit(), a następnie ponownego wywołania CAN.init() z nowym trybem.

MODE_NORMAL: int

Kontroler jest aktywny jako standardowy węzeł sieci CAN (będzie potwierdzał poprawne komunikaty i może nadawać błędy w zależności od bieżącego Stanu).

MODE_SLEEP: int

Kontroler CAN jest uśpiony w trybie niskiego poboru mocy. W zależności od kontrolera, może to umożliwiać wybudzenie kontrolera i przejście do CAN.MODE_NORMAL po odebraniu ruchu CAN.

MODE_LOOPBACK: int

Tryb testowy. Kontroler CAN jest nadal podłączony do zewnętrznej magistrali, ale będzie również odbierał własne nadane komunikaty i ignorował wszelkie błędy ACK.

MODE_SILENT: int

Kontroler CAN odbiera komunikaty, ale nie wchodzi w interakcję z magistralą CAN (w tym nie wysyła ACK, błędów itp.).

MODE_SILENT_LOOPBACK: int

Tryb testowy, który w ogóle nie wymaga podłączenia transceivera CAN. Kontroler CAN odbiera własne nadane komunikaty bez jakiejkolwiek interakcji z magistralą CAN. Piny TX i RX CAN pozostają w stanie bezczynności.

Stany

Te wartości są zwracane przez CAN.state() i odzwierciedlają stan błędu kontrolera CAN:

STATE_STOPPED: int

Kontroler nie został zainicjalizowany.

STATE_ACTIVE: int

Kontroler jest aktywny, a liczniki błędów TEC i REC są oba poniżej progu ostrzeżenia wynoszącego 96. Patrz CAN.get_counters().

STATE_WARNING: int

Kontroler jest aktywny, ale co najmniej jeden z liczników błędów TEC i REC ma wartość między 96 a 127. Patrz CAN.get_counters().

STATE_PASSIVE: int

Kontroler jest w stanie „Error Passive”, co oznacza, że nie nadaje już aktywnych błędów na magistralę, ale poza tym jest funkcjonalny. Ten stan jest osiągany, gdy co najmniej jeden z liczników błędów TEC i REC ma wartość 128 lub większą, ale TEC jest mniejszy niż 255. Patrz CAN.get_counters().

STATE_BUS_OFF: int

Kontroler jest w stanie Bus-Off, co oznacza, że licznik błędów TEC jest większy niż 255. W tym stanie kontroler CAN nie wchodzi w interakcję z magistralą i aby kontynuować, musi zostać zrestartowany za pomocą CAN.restart().

Flagi komunikatów

Te wartości reprezentują metadane dotyczące komunikatu CAN. Funkcje CAN.send(), CAN.recv() i CAN.set_filters() przyjmują lub zwracają wartość całkowitą złożoną z zera lub więcej tych flag połączonych bitową operacją OR.

FLAG_RTR: int

Wskazuje, że komunikat jest żądaniem zdalnej transmisji.

FLAG_EXT_ID: int

Jeśli ustawiony, wskazuje, że identyfikator komunikatu jest rozszerzony (Extended, 29-bitowy). Jeśli nieustawiony, wskazuje, że identyfikator komunikatu jest standardowy (Standard, 11-bitowy).

FLAG_UNORDERED: int

Jeśli ustawiony w argumencie flags funkcji CAN.send(), wskazuje, że można wysyłać komunikaty o tym samym ID CAN na magistralę w dowolnej kolejności.

W przeciwnym razie próba umieszczenia w kolejce wielu komunikatów o tym samym ID może spowodować niepowodzenie CAN.send(), jeśli sprzęt kontrolera nie potrafi wymusić kolejności.

Ta flaga nigdy nie jest ustawiana w odebranych komunikatach i jest ignorowana przez CAN.set_filters().

Flagi błędów odbioru

Wynik CAN.recv() zawiera wartość całkowitą złożoną z zera lub więcej tych flag połączonych bitową operacją OR. Jeśli są ustawione, flagi te wskazują potencjalne ogólne problemy z odbieraniem komunikatów CAN.

RECV_ERR_FULL: int

Sprzętowe FIFO, w którym odebrano ten komunikat, jest pełne, a dodatkowe przychodzące komunikaty mogą zostać utracone.

RECV_ERR_OVERRUN: int

Sprzętowe FIFO, w którym odebrano ten komunikat, jest pełne i jeden lub więcej przychodzących komunikatów zostało utraconych.

Wartości IRQ

IRQ_RX: int

Przekaż do argumentu trigger metody irq(), aby wyzwalać funkcję obsługi za każdym razem, gdy kontroler CAN odbierze kompletny komunikat do FIFO RX. Wewnątrz funkcji obsługi odczytaj komunikat za pomocą recv().

IRQ_TX: int

Przekaż do argumentu trigger metody irq(), aby wyzwalać funkcję obsługi za każdym razem, gdy kontroler CAN zakończy próbę nadawania (powodzenie lub niepowodzenie). Wewnątrz funkcji obsługi użyj dodatkowych bitów poniżej, aby ustalić, która skrzynka pocztowa (mailbox) zakończyła pracę i czy się nie powiodła – patrz Flagi IRQ.

IRQ_STATE: int

Przekaż do argumentu trigger metody irq(), aby wyzwalać funkcję obsługi za każdym razem, gdy kontroler przejdzie między wartościami STATE_* (active / warning / passive / bus-off). Użyj state() wewnątrz funkcji obsługi, aby odczytać nowy stan.

IRQ_TX_FAILED: int

Flaga statusu, która może być ustawiona w irq().flags(), gdy wyzwalane jest zdarzenie IRQ_TX. Wskazuje, że próba nadawania się nie powiodła (zwykle dlatego, że wywołano cancel_send() lub kontroler wszedł w stan błędu).

IRQ_TX_IDX_SHIFT: int

Pozycja bitowa pola indeksu skrzynki nadawczej (transmit-mailbox-index) w wartości irq().flags() podczas zdarzenia IRQ_TX. Indeks skrzynki pocztowej jest wyodrębniany jako (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.

IRQ_TX_IDX_MASK: int

Maska bitowa pola indeksu skrzynki nadawczej (transmit-mailbox-index) w wartości irq().flags() podczas zdarzenia IRQ_TX. Wyodrębniony indeks odpowiada liczbie całkowitej zwróconej przez odpowiednie wywołanie send() (int z zakresu od 0 do TX_QUEUE_LEN).

Flagi IRQ

Wywołanie CAN.irq() rejestruje funkcję obsługi przerwań z jednym lub więcej wyzwalaczami CAN.IRQ_RX, CAN.IRQ_TX i CAN.IRQ_STATE.

Funkcja zwraca obiekt IRQ, a wywołanie funkcji flags() na tym obiekcie zwraca liczbę całkowitą wskazującą, które zdarzenia wyzwalające wywołały przerwanie. Funkcja obsługi IRQ CAN powinna wywoływać funkcję flags() wielokrotnie, aż zwróci 0.

Gdy funkcja flags() zwróci wynik z ustawionym bitem CAN.IRQ_TX, funkcja obsługi może również sprawdzić w wyniku następujące bity flag, aby uzyskać dodatkowe informacje o zdarzeniu TX:

  • Bit CAN.IRQ_TX_FAILED jest ustawiony, jeśli nadawanie się nie powiodło. Zwykle zdarza się to tylko wtedy, gdy wywołano CAN.cancel_send(), choć może się to również zdarzyć, jeśli kontroler wejdzie w stan błędu.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT to zamaskowany bitowo obszar wartości flag, który przechowuje indeks bufora nadawczego, który wygenerował zdarzenie. Będzie to liczba całkowita z zakresu od 0 do CAN.TX_QUEUE_LEN (wyłącznie) i będzie zgodna z wynikiem poprzedniego wywołania CAN.send().

Przykład 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)

Ważne

Jeśli wyzwalacz CAN.IRQ_TX jest ustawiony, funkcja obsługi musi wywoływać flags() wielokrotnie, aż zwróci 0, jak pokazano w tym przykładzie. W przeciwnym razie przerwania CAN mogą nie zostać poprawnie ponownie włączone.