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:
ididentyfikuje 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_SegiPhase_Seg1zdefiniowanych 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_Seg2w 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, lubobiektem iterowalnym zawierającym jeden lub więcej elementów definiujących kryteria filtrowania. Każdy element powinien być krotką lub listą z trzema elementami:
identifierto identyfikator CAN (int).bit_maskto maska bitów dla bitów w polu identyfikatora CAN (int).flagsto 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 jestValueError.
Przychodzące komunikaty są akceptowane, jeśli bity zamaskowane w
bit_masksą zgodne pomiędzy identyfikatorem komunikatu a wartościąidentifierfiltra, a flagi ustawione w filtrze pasują do przychodzącego komunikatu.Jeśli bit
CAN.FLAG_EXT_IDjest ustawiony we flagach, filtr dopasowuje wyłącznie rozszerzone identyfikatory CAN (Extended). Jeśli bitCAN.FLAG_EXT_IDnie 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 zostanieValueError.Informacja
Jeśli
identifierlubbit_maskjest poza zakresem dla określonego typu ID, zgłoszony zostanieValueErrorz 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_filtersmoże zgłosićValueErrornawet wtedy, gdy limitFILTERS_MAXnie 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
0doCAN.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_sendoraz w zdarzeniachCAN.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_UNORDEREDw 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_LENelementó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_RTRjest 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ściDLCjest równe długości argumentu data.Przykłady¶
Próba wysłania komunikatu z trzybajtową zawartością
0a0b0ci 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
memoryviewodwołujący się do obiektubytearraylub 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_filtersmusi zostać wywołana, zanim kontroler będzie mógł odebrać jakiekolwiek komunikaty. Aby odbierać wszystkie komunikaty, wywołajset_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
memoryviewprzechowujący odebrane bajty. Tenmemoryviewjest oparty na nowo zaalokowanym obiekciebytearray, 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
memoryviewzostanie zmieniony tak, aby pomieścił dokładnie odebrane bajty. Wywołujący jest odpowiedzialny za upewnienie się, że obiekt bazowy dlamemoryviewmoż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_RTRzostanie ustawiony w indeksie 2, a memoryview w indeksie 1 będzie zawierać same zera, o długości równej poluDLCodebranego żą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_RXwystępuje po tym, jak kontroler CAN odebrał co najmniej jeden komunikat do swojego FIFO RX (co oznacza, żeCAN.recv()zwróci wynik pomyślnie).Zdarzenie
CAN.IRQ_TXwystę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_STATEwystępuje, gdy kontroler CAN przeszedł do poważniejszego stanu błędu. WywołajCAN.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
0doCAN.TX_QUEUE_LEN(wyłącznie). Zwykle będzie to wartość zwrócona wcześniej przezCAN.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_TXpowinno 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_OFFmożna wyjść tylko przez wywołanieCAN.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.
Nonedla 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_OFFbez 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_TXaniIRQ_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łaniaCAN.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_NORMALpo 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.
Stany¶
Te wartości są zwracane przez
CAN.state()i odzwierciedlają stan błędu kontrolera CAN:- STATE_ACTIVE: int¶
Kontroler jest aktywny, a liczniki błędów
TECiRECsą oba poniżej progu ostrzeżenia wynoszącego 96. PatrzCAN.get_counters().
- STATE_WARNING: int¶
Kontroler jest aktywny, ale co najmniej jeden z liczników błędów
TECiRECma wartość między 96 a 127. PatrzCAN.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
TECiRECma wartość 128 lub większą, aleTECjest mniejszy niż 255. PatrzCAN.get_counters().
- STATE_BUS_OFF: int¶
Kontroler jest w stanie Bus-Off, co oznacza, że licznik błędów
TECjest 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()iCAN.set_filters()przyjmują lub zwracają wartość całkowitą złożoną z zera lub więcej tych flag połączonych bitową operacją OR.- 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
flagsfunkcjiCAN.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.Wartości IRQ¶
- IRQ_RX: int¶
Przekaż do argumentu
triggermetodyirq(), 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
triggermetodyirq(), 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
triggermetodyirq(), aby wyzwalać funkcję obsługi za każdym razem, gdy kontroler przejdzie między wartościamiSTATE_*(active / warning / passive / bus-off). Użyjstate()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 zdarzenieIRQ_TX. Wskazuje, że próba nadawania się nie powiodła (zwykle dlatego, że wywołanocancel_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 zdarzeniaIRQ_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 zdarzeniaIRQ_TX. Wyodrębniony indeks odpowiada liczbie całkowitej zwróconej przez odpowiednie wywołaniesend()(int z zakresu od0doTX_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_FAILEDjest ustawiony, jeśli nadawanie się nie powiodło. Zwykle zdarza się to tylko wtedy, gdy wywołanoCAN.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_SHIFTto zamaskowany bitowo obszar wartości flag, który przechowuje indeks bufora nadawczego, który wygenerował zdarzenie. Będzie to liczba całkowita z zakresu od0doCAN.TX_QUEUE_LEN(wyłącznie) i będzie zgodna z wynikiem poprzedniego wywołaniaCAN.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.