klasa CAN – magistrala komunikacyjna controller area network

CAN zapewnia obsługę zarówno klasycznego CAN (bxCAN, używanego w OpenMV Cam M4 i M7), jak i CAN FD (FDCAN, używanego w OpenMV Cam H7, H7 Plus i Pure Thermal). Na poziomie fizycznym magistrala CAN składa się z dwóch linii, RX i TX. Aby podłączyć OpenMV Cam do magistrali CAN, należy użyć transceivera CAN, który przekształca logiczne sygnały CAN z MCU na właściwe poziomy napięć na magistrali.

Klasyczny CAN w trybie pętli zwrotnej (loopback, bez transceivera):

from pyb import CAN

can = CAN(1, CAN.LOOPBACK)

# Accept messages with id 123, 124, 125 or 126.
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))

can.send("message!", 123)   # send a message with id 123
can.recv(0)                 # receive a message on FIFO 0

CAN FD ze wszystkimi opcjonalnymi funkcjami włączonymi (ramka FD, przełączanie szybkości transmisji, rozszerzone identyfikatory ramek; faza arbitrażu 500 kbit/s, faza danych 1 Mbit/s):

from pyb import CAN

can = CAN(
    1,
    CAN.NORMAL,
    baudrate=500_000,
    brs_baudrate=1_000_000,
    sample_point=80,
)

# Accept any id in the range 0xFFF0 .. 0xFFFF.
can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF))

can.send(b"a" * 64, 0xFFFF, fdf=True, brs=True, extframe=True)
can.recv(0)

Następujące funkcje modułu CAN oraz ich argumenty są dostępne zarówno dla klasycznych kontrolerów CAN, jak i FD CAN, o ile nie zaznaczono inaczej.

Konstruktory

class pyb.CAN(bus: int | str, *args, **kwargs)

Tworzy obiekt CAN na danej magistrali bus (całkowity indeks urządzenia peryferyjnego, np. 1 dla CAN1, 2 dla CAN2). Bez dodatkowych parametrów obiekt jest tworzony, ale nie inicjalizowany (zachowuje poprzednie ustawienia magistrali, jeśli istnieją); jeśli podano dodatkowe argumenty, magistrala jest inicjalizowana. Dostępne parametry opisuje CAN.init().

CAN(2) jest podłączony do tych samych pinów złącza w każdym OpenMV Cam, który udostępnia pyb.CAN (M4 / M7 / H7 / H7 Plus / Pure Thermal):

Sygnał

Pin złącza

Uwagi

RX

P3

TX

P2

Urządzenie peryferyjne CAN dostarcza wyłącznie sygnały na poziomie logicznym; do sterowania rzeczywistą magistralą CAN wymagany jest zewnętrzny transceiver CAN.

pyb.CAN nie jest dostępny w OpenMV Cam N6.

Metody

init(mode: int, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, baudrate: int = 0, sample_point: int = 75, num_filter_banks: int = 14, brs_sjw: int = 1, brs_bs1: int = 8, brs_bs2: int = 3, brs_baudrate: int = 0, brs_sample_point: int = 75) None

Inicjalizuje magistralę CAN z podanymi parametrami:

  • mode przyjmuje jedną z wartości: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK

  • prescaler to wartość, przez którą dzielony jest zegar wejściowy CAN w celu wygenerowania nominalnych kwantów czasu bitu. Preskaler może przyjmować wartość od 1 do 1024 włącznie dla klasycznego CAN oraz od 1 do 512 włącznie dla CAN FD.

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

  • bs1 określa położenie punktu próbkowania w jednostkach kwantów czasu dla bitów nominalnych; może przyjmować wartość od 1 do 16 włącznie dla klasycznego CAN oraz od 2 do 256 włącznie dla CAN FD.

  • bs2 określa położenie punktu transmisji w jednostkach kwantów czasu dla bitów nominalnych; może przyjmować wartość od 1 do 8 włącznie dla klasycznego CAN oraz od 2 do 128 włącznie dla CAN FD.

  • auto_restart ustala, czy kontroler będzie automatycznie próbował wznowić komunikację po wejściu w stan bus-off; jeśli jest to wyłączone, do opuszczenia stanu bus-off można użyć metody restart()

  • baudrate jeśli podana zostanie szybkość transmisji inna niż 0, funkcja spróbuje automatycznie obliczyć nominalny czas bitu CAN (nadpisując prescaler, bs1 i bs2), który spełnia jednocześnie baudrate (z dokładnością do 0,1%) oraz pożądany sample_point (z dokładnością do najbliższego 1%). Aby uzyskać dokładniejszą kontrolę nad taktowaniem CAN, ustaw bezpośrednio parametry prescaler, bs1 i bs2.

  • sample_point określa położenie próbkowania bitu względem całego nominalnego czasu bitu, wyrażone jako całkowita wartość procentowa nominalnego czasu bitu. Domyślny sample_point wynosi 75%. Ten parametr jest ignorowany, chyba że ustawiono baudrate.

  • num_filter_banks dla klasycznego CAN to liczba banków, które zostaną przypisane do CAN(1), a pozostałe z 28 zostaną przypisane do CAN(2).

Pozostałe parametry występują tylko na płytkach z obsługą CAN FD i konfigurują opcjonalną funkcję przełączania szybkości transmisji CAN FD (Bit Rate Switch, BRS):

  • brs_prescaler to wartość, przez którą dzielony jest zegar wejściowy CAN FD w celu wygenerowania kwantów czasu bitu danych. Preskaler może przyjmować wartość od 1 do 32 włącznie.

  • brs_sjw to szerokość skoku resynchronizacji w jednostkach kwantów czasu dla bitów danych; może przyjmować wartość od 1 do 16 włącznie

  • brs_bs1 określa położenie punktu próbkowania w jednostkach kwantów czasu dla bitów danych; może przyjmować wartość od 1 do 32 włącznie

  • brs_bs2 określa położenie punktu transmisji w jednostkach kwantów czasu dla bitów danych; może przyjmować wartość od 1 do 16 włącznie

  • brs_baudrate jeśli podana zostanie szybkość transmisji inna niż 0, funkcja spróbuje automatycznie obliczyć czas bitu danych CAN (nadpisując brs_prescaler, brs_bs1 i brs_bs2), który spełnia jednocześnie brs_baudrate (z dokładnością do 0,1%) oraz pożądany brs_sample_point (z dokładnością do najbliższego 1%). Aby uzyskać dokładniejszą kontrolę nad taktowaniem BRS, ustaw bezpośrednio parametry brs_prescaler, brs_bs1 i brs_bs2.

  • brs_sample_point określa położenie próbkowania bitu względem całego nominalnego czasu bitu, wyrażone jako całkowita wartość procentowa nominalnego czasu bitu. Domyślny brs_sample_point wynosi 75%. Ten parametr jest ignorowany, chyba że ustawiono brs_baudrate.

Kwant czasu tq jest podstawową jednostką czasu dla magistrali CAN. tq to wartość preskalera CAN podzielona przez PCLK1 (częstotliwość wewnętrznej magistrali peryferyjnej 1); zobacz pyb.freq(), aby ustalić PCLK1.

Pojedynczy bit składa się z segmentu synchronizacji, który zawsze wynosi 1 tq. Następnie występuje segment bitu 1, a po nim segment bitu 2. Punkt próbkowania znajduje się po zakończeniu segmentu bitu 1. Punkt transmisji znajduje się po zakończeniu segmentu bitu 2. Szybkość transmisji będzie wynosić 1/bittime, gdzie bittime to 1 + BS1 + BS2 pomnożone przez kwant czasu tq.

Na przykład w OpenMV Cam H7 (PCLK1 = 100 MHz) CAN 250 kbps z punktem próbkowania 75% można skonfigurować jako prescaler=25, sjw=1, bs1=11, bs2=4: tq = 25 / 100 MHz = 250 ns, bittime = (1 + 11 + 4) × 250 ns = 4 µs, punkt próbkowania = (1 + 11) / 16 = 75%, a szybkość transmisji wynosi 1 / 4 µs = 250 kHz.

Więcej szczegółów znajduje się w sekcji bxCAN / FDCAN w podręczniku referencyjnym STM32 dla MCU danego OpenMV Cam.

deinit() None

Wyłącza magistralę CAN.

restart() None

Wymusza programowe ponowne uruchomienie kontrolera CAN bez resetowania jego konfiguracji.

Jeśli kontroler wejdzie w stan bus-off, nie będzie już uczestniczył w aktywności magistrali. Jeśli kontroler nie jest skonfigurowany do automatycznego restartu (zobacz init()), tej metody można użyć do wyzwolenia ponownego uruchomienia, a kontroler będzie postępował zgodnie z protokołem CAN, aby opuścić stan bus-off i przejść w stan error active.

state() int

Zwraca stan kontrolera. Zwracana wartość może być jedną z:

  • CAN.STOPPED – kontroler jest całkowicie wyłączony i zresetowany;

  • CAN.ERROR_ACTIVE – kontroler jest włączony i w stanie Error Active (zarówno TEC, jak i REC są mniejsze niż 96);

  • CAN.ERROR_WARNING – kontroler jest włączony i w stanie Error Warning (przynajmniej jeden z TEC lub REC wynosi 96 lub więcej);

  • CAN.ERROR_PASSIVE – kontroler jest włączony i w stanie Error Passive (przynajmniej jeden z TEC lub REC wynosi 128 lub więcej);

  • CAN.BUS_OFF – kontroler jest włączony, ale nie uczestniczy w aktywności magistrali (TEC przekroczył 255).

info(list: list | None = None) list

Pobiera informacje o stanach błędów kontrolera oraz buforach TX i RX. Jeśli podano list, powinien to być obiekt listy z co najmniej 8 elementami, które zostaną wypełnione tymi informacjami. W przeciwnym razie zostanie utworzona i wypełniona nowa lista. W obu przypadkach wartością zwracaną przez metodę jest wypełniona lista.

Wartości na liście to:

  • wartość TEC

  • wartość REC

  • liczba przypadków wejścia kontrolera w stan Error Warning (przewija się do 0 po 65535)

  • liczba przypadków wejścia kontrolera w stan Error Passive (przewija się do 0 po 65535)

  • liczba przypadków wejścia kontrolera w stan Bus Off (przewija się do 0 po 65535)

  • liczba oczekujących wiadomości TX

  • liczba oczekujących wiadomości RX w fifo 0

  • liczba oczekujących wiadomości RX w fifo 1

setfilter(bank: int, mode: int, fifo: int, params: Tuple[int, ...], *, rtr: Tuple[bool, ...] | None = None, extframe: bool = False) None

Konfiguruje bank filtrów:

  • bank to bank filtrów klasycznego kontrolera CAN lub indeks filtra CAN FD, który ma zostać skonfigurowany.

  • mode to tryb, w którym filtr powinien działać, zobacz tabele poniżej.

  • fifo to fifo (0 lub 1), w którym wiadomość powinna zostać zapisana, jeśli zostanie zaakceptowana przez ten filtr.

  • params to tablica wartości definiujących filtr. Zawartość tablicy zależy od argumentu mode.

Zawartość tablicy params dla kontrolerów klasycznego CAN (OpenMV Cam M4 / M7):

mode

Zawartość params

CAN.LIST16

Cztery 16-bitowe identyfikatory, które będą akceptowane.

CAN.LIST32

Dwa 32-bitowe identyfikatory, które będą akceptowane.

CAN.MASK16

Dwie pary 16-bitowy id/maska, np. (1, 3, 4, 4). Pierwsza para (1, 3) akceptuje wszystkie identyfikatory z bitem 0 = 1 i bitem 1 = 0; druga para (4, 4) akceptuje wszystkie identyfikatory z bitem 2 = 1.

CAN.MASK32

Jedna 32-bitowa para id/maska (poza tym tak samo jak CAN.MASK16).

Zawartość tablicy params dla kontrolerów CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):

mode

Zawartość params

CAN.RANGE

Dwa identyfikatory tworzące zakres akceptowanych identyfikatorów.

CAN.DUAL

Dwa identyfikatory, które będą akceptowane (np. (1, 2)).

CAN.MASK

Jedna para (id, mask) (np. (0x111, 0x7FF)).

  • rtr W przypadku klasycznych kontrolerów CAN jest to tablica wartości logicznych określająca, czy filtr powinien akceptować wiadomość remote transmission request. Jeśli ten argument nie zostanie podany, domyślnie przyjmuje wartość False dla wszystkich elementów. Długość zależy od mode:

    mode

    len(rtr)

    Uwagi

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    W przypadku CAN FD ten argument jest ignorowany.

  • extframe Jeśli True, ramka będzie miała rozszerzony identyfikator (29 bitów), w przeciwnym razie używany jest standardowy identyfikator (11 bitów).

clearfilter(bank: int, extframe: bool = False) None

Czyści i wyłącza bank filtrów:

  • bank to bank filtrów klasycznego kontrolera CAN lub indeks filtra CAN FD, który ma zostać wyczyszczony.

  • extframe W przypadku kontrolerów CAN FD, jeśli True, czyści filtr rozszerzony (skonfigurowany z extframe=True), w przeciwnym razie czyści standardowy identyfikator (skonfigurowany z extframe=False).

any(fifo: int) bool

Zwraca True, jeśli na FIFO oczekuje jakakolwiek wiadomość, w przeciwnym razie False.

recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list

Odbiera dane z magistrali:

  • fifo to liczba całkowita określająca FIFO, na którym ma nastąpić odbiór

  • list to opcjonalny obiekt listy używany jako wartość zwracana

  • timeout to limit czasu w milisekundach na oczekiwanie na odbiór.

Wartość zwracana: lista zawierająca pięć wartości.

  • Identyfikator wiadomości.

  • Wartość logiczna wskazująca, czy identyfikator wiadomości jest standardowy, czy rozszerzony.

  • Wartość logiczna wskazująca, czy wiadomość jest wiadomością RTR.

  • Wartość FMI (Filter Match Index).

  • Tablica zawierająca dane.

Jeśli list ma wartość None, zostanie przydzielona nowa lista, a także nowy obiekt bytes do przechowywania danych (jako piąty element listy).

Jeśli list nie ma wartości None, powinien to być obiekt listy z co najmniej pięcioma elementami. Piąty element powinien być obiektem memoryview utworzonym z bytearray lub tablicy typu «B» albo «b», a tablica ta musi mieć miejsce na co najmniej 8 bajtów. Obiekt listy zostanie następnie wypełniony pierwszymi czterema wartościami zwracanymi powyżej, a obiekt memoryview zostanie zmieniony w miejscu do rozmiaru danych i wypełniony tymi danymi. Te same obiekty listy i memoryview mogą być ponownie wykorzystywane w kolejnych wywołaniach tej metody, co umożliwia odbieranie danych bez użycia sterty. Na przykład:

buf = bytearray(8)
lst = [0, 0, 0, 0, memoryview(buf)]
# No heap memory is allocated in the following call
can.recv(0, lst)
send(data: int | bytes | bytearray, id: int, *, timeout: int = 0, rtr: bool = False, extframe: bool = False, fdf: bool = False, brs: bool = False) None

Wysyła wiadomość na magistralę:

  • data to dane do wysłania (liczba całkowita do wysłania lub obiekt bufora).

  • id to identyfikator wiadomości, która ma zostać wysłana.

  • timeout to limit czasu w milisekundach na oczekiwanie na wysłanie.

  • rtr to wartość logiczna określająca, czy wiadomość ma zostać wysłana jako remote transmission request. Jeśli rtr ma wartość True, to do wypełnienia pola DLC ramki używana jest tylko długość data; rzeczywiste bajty w data nie są używane.

  • extframe jeśli True, ramka będzie miała rozszerzony identyfikator (29 bitów), w przeciwnym razie używany jest standardowy identyfikator (11 bitów).

  • fdf w przypadku kontrolerów CAN FD, jeśli ustawione na True, ramka będzie miała format ramki FD, który obsługuje ładunki danych do 64 bajtów.

  • brs w przypadku kontrolerów CAN FD, jeśli ustawione na True, włączany jest tryb przełączania szybkości transmisji, w którym faza danych jest transmitowana z inną szybkością transmisji. Parametry konfiguracji taktowania bitu danych opisuje CAN.init().

Jeśli timeout wynosi 0, wiadomość jest umieszczana w jednym z trzech buforów sprzętowych, a metoda zwraca wynik natychmiast. Jeśli wszystkie trzy bufory są zajęte, zgłaszany jest wyjątek. Jeśli timeout jest różny od 0, metoda czeka, aż wiadomość zostanie wysłana. Jeśli wiadomość nie może zostać wysłana w określonym czasie, zgłaszany jest wyjątek.

Wartość zwracana: None.

rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None

Rejestruje funkcję wywoływaną, gdy wiadomość zostaje zaakceptowana do pustego FIFO:

  • fifo to FIFO odbierające.

  • fun to funkcja wywoływana, gdy FIFO przestaje być puste.

Funkcja wywołania zwrotnego przyjmuje dwa argumenty: pierwszym jest sam obiekt CAN; drugim jest liczba całkowita wskazująca powód wywołania zwrotnego:

Powód

Znaczenie

0

Wiadomość została zaakceptowana do pustego FIFO.

1

FIFO jest pełne.

2

Wiadomość została utracona z powodu pełnego FIFO.

Przykład użycia rxcallback:

def cb0(bus, reason):
  print('cb0')
  if reason == 0:
      print('pending')
  if reason == 1:
      print('full')
  if reason == 2:
      print('overflow')

can = CAN(1, CAN.LOOPBACK)
can.rxcallback(0, cb0)

Stałe

Stałe trybu magistrali (argument mode metody init()):

NORMAL: int

Kontroler uczestniczy normalnie w komunikacji na magistrali – transmituje własne ramki i potwierdza prawidłowo odebrane ramki.

LOOPBACK: int

Tryb wewnętrznej pętli zwrotnej: kontroler jest odłączony od pinów i kieruje transmitowane ramki bezpośrednio z powrotem na ścieżkę odbioru. Przydatny do testów własnych bez transceivera.

SILENT: int

Tryb tylko nasłuchiwania: kontroler odbiera ramki, ale nigdy nie steruje magistralą (brak ACK, brak transmisji). Przydatny do podsłuchiwania magistrali.

SILENT_LOOPBACK: int

Łączy SILENT i LOOPBACK: brak aktywności na pinach i brak potwierdzeń, z wewnętrzną pętlą zwrotną TX do RX.

Stałe stanu kontrolera (zwracane przez state()):

STOPPED: int

Kontroler jest całkowicie wyłączony i zresetowany.

ERROR_ACTIVE: int

Kontroler jest włączony i w stanie Error Active (zarówno TEC, jak i REC są mniejsze niż 96).

ERROR_WARNING: int

Kontroler jest włączony i w stanie Error Warning (przynajmniej jeden z TEC lub REC wynosi 96 lub więcej).

ERROR_PASSIVE: int

Kontroler jest włączony i w stanie Error Passive (przynajmniej jeden z TEC lub REC wynosi 128 lub więcej).

BUS_OFF: int

Kontroler jest włączony, ale nie uczestniczy w aktywności magistrali (TEC przekroczył 255).

Tryby filtra klasycznego CAN (argument mode metody setfilter() w OpenMV Cam M4 / M7):

LIST16: int

Tablica filtra params zawiera cztery 16-bitowe identyfikatory, które będą akceptowane.

LIST32: int

Tablica filtra params zawiera dwa 32-bitowe identyfikatory, które będą akceptowane.

MASK16: int

Tablica filtra params zawiera dwie 16-bitowe pary (id, mask).

MASK32: int

Tablica filtra params zawiera jedną 32-bitową parę (id, mask).

Tryby filtra CAN FD (argument mode metody setfilter() w OpenMV Cam H7 / H7 Plus / Pure Thermal):

RANGE: int

Tablica filtra params zawiera dwa identyfikatory tworzące zakres akceptowanych identyfikatorów.

DUAL: int

Tablica filtra params zawiera dwa konkretne identyfikatory do zaakceptowania.

MASK: int

Tablica filtra params zawiera jedną parę (id, mask).