class CAN – Controller Area Network Kommunikationsbus

CAN bietet Unterstützung sowohl für klassisches CAN (bxCAN, verwendet auf der OpenMV Cam M4 und M7) als auch für CAN FD (FDCAN, verwendet auf der OpenMV Cam H7, H7 Plus und Pure Thermal). Auf der physikalischen Ebene besteht der CAN-Bus aus zwei Leitungen, RX und TX. Um eine OpenMV Cam mit einem CAN-Bus zu verbinden, müssen Sie einen CAN-Transceiver verwenden, der die logischen CAN-Signale des MCU in die korrekten Spannungspegel auf dem Bus umwandelt.

Klassisches CAN im Loopback-Modus (ohne Transceiver):

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 mit allen aktivierten optionalen Funktionen (FD-Frame, Bitratenumschaltung, erweiterte Frame-IDs; 500 kbit/s Arbitrierungsphase, 1 Mbit/s Datenphase):

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)

Die folgenden CAN-Modulfunktionen und ihre Argumente sind sowohl für klassische als auch für FD-CAN-Controller verfügbar, sofern nicht anders angegeben.

Konstruktoren

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

Erstellt ein CAN-Objekt auf dem angegebenen bus (ein ganzzahliger Peripherie-Index, z. B. 1 für CAN1, 2 für CAN2). Ohne zusätzliche Parameter wird das Objekt erstellt, aber nicht initialisiert (es behält die vorherigen Bus-Einstellungen bei, falls vorhanden); werden zusätzliche Argumente angegeben, wird der Bus initialisiert. Siehe CAN.init() für die verfügbaren Parameter.

CAN(2) ist auf jeder OpenMV Cam, die pyb.CAN bereitstellt (M4 / M7 / H7 / H7 Plus / Pure Thermal), mit denselben Header-Pins verdrahtet:

Signal

Header-Pin

Hinweise

RX

P3

TX

P2

Das CAN-Peripheriegerät liefert nur Signale auf Logikpegel; ein externer CAN-Transceiver ist erforderlich, um einen echten CAN-Bus anzusteuern.

pyb.CAN ist auf der OpenMV Cam N6 nicht verfügbar.

Methoden

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

Initialisiert den CAN-Bus mit den angegebenen Parametern:

  • mode ist einer von: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK

  • prescaler ist der Wert, durch den der CAN-Eingangstakt geteilt wird, um die nominalen Bitzeit-Quanten zu erzeugen. Der Prescaler kann für klassisches CAN ein Wert zwischen 1 und 1024 einschließlich sein und für CAN FD zwischen 1 und 512 einschließlich.

  • sjw ist die Resynchronisations-Sprungweite in Einheiten von Zeitquanten für nominale Bits; sie kann für klassisches CAN ein Wert zwischen 1 und 4 einschließlich sein und für CAN FD zwischen 1 und 128 einschließlich.

  • bs1 legt die Position des Abtastpunkts in Einheiten der Zeitquanten für nominale Bits fest; es kann für klassisches CAN ein Wert zwischen 1 und 16 einschließlich sein und für CAN FD zwischen 2 und 256 einschließlich.

  • bs2 legt die Position des Sendepunkts in Einheiten der Zeitquanten für nominale Bits fest; es kann für klassisches CAN ein Wert zwischen 1 und 8 einschließlich sein und für CAN FD zwischen 2 und 128 einschließlich.

  • auto_restart legt fest, ob der Controller nach dem Eintritt in den Bus-Off-Zustand automatisch versucht, die Kommunikation neu zu starten; ist dies deaktiviert, kann restart() verwendet werden, um den Bus-Off-Zustand zu verlassen

  • baudrate wenn eine andere Baudrate als 0 angegeben wird, versucht diese Funktion automatisch die nominale CAN-Bitzeit zu berechnen (wobei prescaler, bs1 und bs2 überschrieben werden), die sowohl die baudrate (innerhalb von 0,1 %) als auch den gewünschten sample_point (auf das nächste 1 %) erfüllt. Für eine genauere Kontrolle über das CAN-Timing setzen Sie die Parameter prescaler, bs1 und bs2 direkt.

  • sample_point gibt die Position der Bit-Abtastung in Bezug auf die gesamte nominale Bitzeit an, ausgedrückt als ganzzahliger Prozentsatz der nominalen Bitzeit. Der Standardwert für sample_point ist 75 %. Dieser Parameter wird ignoriert, sofern baudrate nicht gesetzt ist.

  • num_filter_banks für klassisches CAN ist dies die Anzahl der Bänke, die CAN(1) zugewiesen werden; die übrigen der 28 werden CAN(2) zugewiesen.

Die übrigen Parameter sind nur auf Boards mit CAN-FD-Unterstützung vorhanden und konfigurieren die optionale CAN-FD-Bitratenumschaltung (Bit Rate Switch, BRS):

  • brs_prescaler ist der Wert, durch den der CAN-FD-Eingangstakt geteilt wird, um die Datenbitzeit-Quanten zu erzeugen. Der Prescaler kann ein Wert zwischen 1 und 32 einschließlich sein.

  • brs_sjw ist die Resynchronisations-Sprungweite in Einheiten von Zeitquanten für Datenbits; sie kann ein Wert zwischen 1 und 16 einschließlich sein

  • brs_bs1 legt die Position des Abtastpunkts in Einheiten der Zeitquanten für Datenbits fest; es kann ein Wert zwischen 1 und 32 einschließlich sein

  • brs_bs2 legt die Position des Sendepunkts in Einheiten der Zeitquanten für Datenbits fest; es kann ein Wert zwischen 1 und 16 einschließlich sein

  • brs_baudrate wenn eine andere Baudrate als 0 angegeben wird, versucht diese Funktion automatisch die CAN-Datenbitzeit zu berechnen (wobei brs_prescaler, brs_bs1 und brs_bs2 überschrieben werden), die sowohl die brs_baudrate (innerhalb von 0,1 %) als auch den gewünschten brs_sample_point (auf das nächste 1 %) erfüllt. Für eine genauere Kontrolle über das BRS-Timing setzen Sie die Parameter brs_prescaler, brs_bs1 und brs_bs2 direkt.

  • brs_sample_point gibt die Position der Bit-Abtastung in Bezug auf die gesamte nominale Bitzeit an, ausgedrückt als ganzzahliger Prozentsatz der nominalen Bitzeit. Der Standardwert für brs_sample_point ist 75 %. Dieser Parameter wird ignoriert, sofern brs_baudrate nicht gesetzt ist.

Das Zeitquantum tq ist die grundlegende Zeiteinheit für den CAN-Bus. tq ist der CAN-Prescaler-Wert geteilt durch PCLK1 (die Frequenz des internen Peripheriebusses 1); siehe pyb.freq(), um PCLK1 zu bestimmen.

Ein einzelnes Bit besteht aus dem Synchronisationssegment, das immer 1 tq beträgt. Es folgt Bitsegment 1, dann Bitsegment 2. Der Abtastpunkt liegt nach dem Ende von Bitsegment 1. Der Sendepunkt liegt nach dem Ende von Bitsegment 2. Die Baudrate ist 1/bittime, wobei die bittime gleich 1 + BS1 + BS2 multipliziert mit dem Zeitquantum tq ist.

Zum Beispiel kann auf der OpenMV Cam H7 (PCLK1 = 100 MHz) 250 kbps CAN mit einem Abtastpunkt von 75 % als prescaler=25, sjw=1, bs1=11, bs2=4 konfiguriert werden: tq = 25 / 100 MHz = 250 ns, bittime = (1 + 11 + 4) × 250 ns = 4 µs, Abtastpunkt = (1 + 11) / 16 = 75%, und die Baudrate ist 1 / 4 µs = 250 kHz.

Weitere Einzelheiten finden Sie im Abschnitt bxCAN / FDCAN des STM32-Referenzhandbuchs für den MCU der OpenMV Cam.

deinit() None

Schaltet den CAN-Bus aus.

restart() None

Erzwingt einen Software-Neustart des CAN-Controllers, ohne dessen Konfiguration zurückzusetzen.

Wenn der Controller in den Bus-Off-Zustand eintritt, nimmt er nicht mehr an der Bus-Aktivität teil. Ist der Controller nicht für einen automatischen Neustart konfiguriert (siehe init()), kann diese Methode verwendet werden, um einen Neustart auszulösen; der Controller folgt dann dem CAN-Protokoll, um den Bus-Off-Zustand zu verlassen und in den Error-Active-Zustand überzugehen.

state() int

Gibt den Zustand des Controllers zurück. Der Rückgabewert kann einer der folgenden sein:

  • CAN.STOPPED – der Controller ist vollständig ausgeschaltet und zurückgesetzt;

  • CAN.ERROR_ACTIVE – der Controller ist eingeschaltet und im Error-Active-Zustand (sowohl TEC als auch REC sind kleiner als 96);

  • CAN.ERROR_WARNING – der Controller ist eingeschaltet und im Error-Warning-Zustand (mindestens einer von TEC oder REC ist 96 oder größer);

  • CAN.ERROR_PASSIVE – der Controller ist eingeschaltet und im Error-Passive-Zustand (mindestens einer von TEC oder REC ist 128 oder größer);

  • CAN.BUS_OFF – der Controller ist eingeschaltet, nimmt aber nicht an der Bus-Aktivität teil (TEC ist über 255 hinaus übergelaufen).

info(list: list | None = None) list

Ruft Informationen über die Fehlerzustände des Controllers sowie die TX- und RX-Puffer ab. Wird list angegeben, sollte es ein Listenobjekt mit mindestens 8 Einträgen sein, das mit den Informationen gefüllt wird. Andernfalls wird eine neue Liste erstellt und gefüllt. In beiden Fällen ist der Rückgabewert der Methode die gefüllte Liste.

Die Werte in der Liste sind:

  • TEC-Wert

  • REC-Wert

  • Anzahl der Male, die der Controller in den Error-Warning-Zustand eingetreten ist (nach 65535 auf 0 zurückgesetzt)

  • Anzahl der Male, die der Controller in den Error-Passive-Zustand eingetreten ist (nach 65535 auf 0 zurückgesetzt)

  • Anzahl der Male, die der Controller in den Bus-Off-Zustand eingetreten ist (nach 65535 auf 0 zurückgesetzt)

  • Anzahl der ausstehenden TX-Nachrichten

  • Anzahl der ausstehenden RX-Nachrichten in FIFO 0

  • Anzahl der ausstehenden RX-Nachrichten in FIFO 1

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

Konfiguriert eine Filterbank:

  • bank ist die zu konfigurierende Filterbank des klassischen CAN-Controllers bzw. der CAN-FD-Filterindex.

  • mode ist der Modus, in dem der Filter arbeiten soll, siehe die Tabellen unten.

  • fifo gibt an, in welchem FIFO (0 oder 1) eine Nachricht gespeichert werden soll, wenn sie von diesem Filter akzeptiert wird.

  • params ist ein Array von Werten, die den Filter definieren. Der Inhalt des Arrays hängt vom Argument mode ab.

Inhalt des params-Arrays für klassische CAN-Controller (OpenMV Cam M4 / M7):

mode

Inhalt von params

CAN.LIST16

Vier 16-Bit-IDs, die akzeptiert werden.

CAN.LIST32

Zwei 32-Bit-IDs, die akzeptiert werden.

CAN.MASK16

Zwei 16-Bit-id/mask-Paare, z. B. (1, 3, 4, 4). Das erste Paar (1, 3) akzeptiert alle IDs mit Bit 0 = 1 und Bit 1 = 0; das zweite Paar (4, 4) akzeptiert alle IDs mit Bit 2 = 1.

CAN.MASK32

Ein 32-Bit-id/mask-Paar (ansonsten identisch mit CAN.MASK16).

Inhalt des params-Arrays für CAN FD-Controller (OpenMV Cam H7 / H7 Plus / Pure Thermal):

mode

Inhalt von params

CAN.RANGE

Zwei IDs, die einen Bereich akzeptierter IDs bilden.

CAN.DUAL

Zwei IDs, die akzeptiert werden (z. B. (1, 2)).

CAN.MASK

Ein (id, mask)-Paar (z. B. (0x111, 0x7FF)).

  • rtr Für klassische CAN-Controller ist dies ein Array von Booleschen Werten, das angibt, ob ein Filter eine Remote-Transmission-Request-Nachricht akzeptieren soll. Wird dieses Argument nicht angegeben, ist es für alle Einträge standardmäßig False. Die Länge hängt von mode ab:

    mode

    len(rtr)

    Hinweise

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    Für CAN FD wird dieses Argument ignoriert.

  • extframe Wenn True, hat der Frame einen erweiterten Identifier (29 Bit), andernfalls wird ein Standard-Identifier (11 Bit) verwendet.

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

Löscht und deaktiviert eine Filterbank:

  • bank ist die zu löschende Filterbank des klassischen CAN-Controllers bzw. der CAN-FD-Filterindex.

  • extframe Für CAN-FD-Controller: wenn True, wird ein erweiterter Filter gelöscht (konfiguriert mit extframe=True), andernfalls wird ein Standard-Identifier gelöscht (konfiguriert mit extframe=False).

any(fifo: int) bool

Gibt True zurück, wenn eine Nachricht im FIFO wartet, andernfalls False.

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

Empfängt Daten auf dem Bus:

  • fifo ist eine Ganzzahl, die das FIFO angibt, auf dem empfangen werden soll

  • list ist ein optionales Listenobjekt, das als Rückgabewert verwendet wird

  • timeout ist die Wartezeit in Millisekunden für den Empfang.

Rückgabewert: Eine Liste mit fünf Werten.

  • Die ID der Nachricht.

  • Ein Boolescher Wert, der angibt, ob die Nachrichten-ID Standard oder erweitert ist.

  • Ein Boolescher Wert, der angibt, ob die Nachricht eine RTR-Nachricht ist.

  • Der FMI-Wert (Filter Match Index).

  • Ein Array, das die Daten enthält.

Wenn list None ist, wird eine neue Liste sowie ein neues bytes-Objekt zur Aufnahme der Daten (als fünftes Element der Liste) angelegt.

Wenn list nicht None ist, sollte es ein Listenobjekt mit mindestens fünf Elementen sein. Das fünfte Element sollte ein memoryview-Objekt sein, das aus einem bytearray oder einem Array vom Typ ‚B‘ oder ‚b‘ erstellt wurde, und dieses Array muss Platz für mindestens 8 Bytes haben. Das Listenobjekt wird dann mit den ersten vier oben genannten Rückgabewerten gefüllt, und das memoryview-Objekt wird an Ort und Stelle auf die Größe der Daten angepasst und mit diesen Daten gefüllt. Dieselben list- und memoryview-Objekte können bei späteren Aufrufen dieser Methode wiederverwendet werden, was eine Möglichkeit bietet, Daten zu empfangen, ohne den Heap zu nutzen. Zum Beispiel:

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

Sendet eine Nachricht auf dem Bus:

  • data sind die zu sendenden Daten (eine zu sendende Ganzzahl oder ein Pufferobjekt).

  • id ist die ID der zu sendenden Nachricht.

  • timeout ist die Wartezeit in Millisekunden für das Senden.

  • rtr ist ein Boolescher Wert, der angibt, ob die Nachricht als Remote-Transmission-Request gesendet werden soll. Ist rtr True, wird nur die Länge von data verwendet, um den DLC-Slot des Frames zu füllen; die eigentlichen Bytes in data werden nicht verwendet.

  • extframe wenn True, hat der Frame einen erweiterten Identifier (29 Bit), andernfalls wird ein Standard-Identifier (11 Bit) verwendet.

  • fdf für CAN-FD-Controller: wenn auf True gesetzt, hat der Frame ein FD-Frame-Format, das Datennutzlasten von bis zu 64 Bytes unterstützt.

  • brs für CAN-FD-Controller: wenn auf True gesetzt, ist der Bitratenumschaltungsmodus aktiviert, bei dem die Datenphase mit einer anderen Bitrate übertragen wird. Siehe CAN.init() für die Konfigurationsparameter des Datenbit-Timings.

Ist timeout 0, wird die Nachricht in einen der drei Hardware-Puffer gelegt und die Methode kehrt sofort zurück. Sind alle drei Puffer belegt, wird eine Ausnahme ausgelöst. Ist timeout nicht 0, wartet die Methode, bis die Nachricht übertragen wurde. Kann die Nachricht nicht innerhalb der angegebenen Zeit übertragen werden, wird eine Ausnahme ausgelöst.

Rückgabewert: None.

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

Registriert eine Funktion, die aufgerufen wird, wenn eine Nachricht in ein leeres FIFO aufgenommen wird:

  • fifo ist das empfangende FIFO.

  • fun ist die Funktion, die aufgerufen wird, wenn das FIFO nicht mehr leer ist.

Die Callback-Funktion nimmt zwei Argumente entgegen: das erste ist das CAN-Objekt selbst; das zweite ist eine Ganzzahl, die den Grund für den Callback angibt:

Grund

Bedeutung

0

Eine Nachricht wurde in ein leeres FIFO aufgenommen.

1

Das FIFO ist voll.

2

Eine Nachricht ging aufgrund eines vollen FIFOs verloren.

Beispiel für die Verwendung von 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)

Konstanten

Bus-Modus-Konstanten (mode-Argument von init()):

NORMAL: int

Der Controller nimmt normal am Bus teil – sendet seine eigenen Frames und bestätigt gültige empfangene Frames.

LOOPBACK: int

Interner Loopback-Modus: der Controller ist von den Pins getrennt und leitet gesendete Frames direkt zurück auf den Empfangspfad. Nützlich für Selbsttests ohne Transceiver.

SILENT: int

Listen-only-Modus: der Controller empfängt Frames, treibt aber niemals den Bus an (kein ACK, keine Übertragungen). Nützlich zum Mitlesen des Busses.

SILENT_LOOPBACK: int

Kombiniert SILENT und LOOPBACK: keine Pin-Aktivität und keine Bestätigungen, mit internem Loopback von TX nach RX.

Controller-Zustands-Konstanten (zurückgegeben von state()):

STOPPED: int

Der Controller ist vollständig ausgeschaltet und zurückgesetzt.

ERROR_ACTIVE: int

Der Controller ist eingeschaltet und im Error-Active-Zustand (sowohl TEC als auch REC sind kleiner als 96).

ERROR_WARNING: int

Der Controller ist eingeschaltet und im Error-Warning-Zustand (mindestens einer von TEC oder REC ist 96 oder größer).

ERROR_PASSIVE: int

Der Controller ist eingeschaltet und im Error-Passive-Zustand (mindestens einer von TEC oder REC ist 128 oder größer).

BUS_OFF: int

Der Controller ist eingeschaltet, nimmt aber nicht an der Bus-Aktivität teil (TEC ist über 255 hinaus übergelaufen).

Klassische CAN-Filtermodi (mode-Argument von setfilter() auf der OpenMV Cam M4 / M7):

LIST16: int

Das Filter-params-Array enthält vier 16-Bit-IDs, die akzeptiert werden.

LIST32: int

Das Filter-params-Array enthält zwei 32-Bit-IDs, die akzeptiert werden.

MASK16: int

Das Filter-params-Array enthält zwei 16-Bit-(id, mask)-Paare.

MASK32: int

Das Filter-params-Array enthält ein 32-Bit-(id, mask)-Paar.

CAN-FD-Filtermodi (mode-Argument von setfilter() auf der OpenMV Cam H7 / H7 Plus / Pure Thermal):

RANGE: int

Das Filter-params-Array enthält zwei IDs, die einen Bereich akzeptierter IDs bilden.

DUAL: int

Das Filter-params-Array enthält zwei spezifische zu akzeptierende IDs.

MASK: int

Das Filter-params-Array enthält ein (id, mask)-Paar.