Klasse CAN – Controller-Area-Network-Protokoll

CAN ist ein serielles Zweidraht-Protokoll, das für die zuverlässige Echtzeit-Nachrichtenübertragung zwischen einem oder mehreren an einen gemeinsamen Bus angeschlossenen Knoten verwendet wird. CAN 2.0 wurde in ISO-11898 standardisiert und ist heute auch als CAN Classic bekannt.

Es gibt außerdem ein neueres, rückwärtskompatibles Protokoll namens CAN FD (CAN with Flexible Data-Rate). Der Treiber machine.CAN unterstützt derzeit keine CAN-FD-Funktionen; verwenden Sie pyb.CAN auf STM32, wenn Sie CAN FD benötigen.

CAN-Unterstützung erfordert einen Controller (häufig ein internes Mikrocontroller-Peripheriegerät) sowie einen externen Transceiver, um die Signale pegelangepasst auf den CAN-Bus zu legen.

Verfügbar auf STM32-OpenMV-Kameras (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6 sowie die Arduino-Varianten, die einen Transceiver verdrahten). Noch nicht unterstützt auf der OpenMV Cam RT1062 (mimxrt-Port) oder der OpenMV Cam AE3 (alif-Port).

Die machine.CAN-Schnittstelle ist eine einfache CAN-Messaging-Schnittstelle auf niedriger Ebene, die einen CAN-Controller als ausgehende Prioritätswarteschlange zum Senden von Nachrichten, eine eingehende Warteschlange zum Empfangen von Nachrichten und Mechanismen zur Fehlermeldung abstrahiert.

Bemerkung

Die geplanten micropython-lib-Module can und aiocan werden die empfohlene Methode sein, um CAN mit MicroPython zu nutzen.

Konstruktor

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

Erzeugt ein CAN-Controller-Objekt mit der angegebenen ID:

  • id identifiziert ein bestimmtes CAN-Controller-Objekt; es ist board- und portspezifisch.

  • Alle weiteren Argumente werden an CAN.init() übergeben. Mindestens ein Argument (bitrate) muss angegeben werden.

Zukünftige Versionen dieser Klasse akzeptieren hier möglicherweise auch portspezifische Schlüsselwortargumente, die die Hardware konfigurieren. Derzeit sind keine solchen Schlüsselwortargumente implementiert.

Beispiel

Erzeugen und Initialisieren von CAN-Controller 1 mit einer Bitrate von 500 kbps:

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

Methoden

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

Initialisiert den CAN-Bus mit den angegebenen Parametern:

  • bitrate ist die gewünschte Busbitrate in Bit pro Sekunde.

  • mode ist einer der unter Modi aufgeführten Werte und gibt den gewünschten Betriebsmodus an. Standard ist der „normale“ Betrieb auf dem Bus.

Die nächsten Parameter sind optional und betreffen die CAN-Bit-Timings. In den meisten Fällen können Sie diese Parameter auf den Standardwerten belassen:

  • sample_point ist ein ganzzahliger Prozentsatz der Datenbitzeit. Er gibt die Position der Bitabtastung in Bezug auf die gesamte nominale Bitzeit an. Der CAN-Treiber berechnet die Parameter entsprechend. Dieser Parameter wird ignoriert, wenn tseg1 und tseg2 gesetzt sind.

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

  • tseg1 legt die Position des Abtastpunkts in Zeitquanten-Einheiten für nominale Bits fest; für klassisches CAN kann der Wert zwischen 1 und 16 einschließlich liegen. Dies ist die Summe der Phasen Prop_Seg und Phase_Seg1, wie im Standard ISO-11898 definiert. Wenn dieser Wert gesetzt ist, muss auch tseg2 gesetzt sein, und sample_point wird ignoriert.

  • tseg2 legt die Position des Sendepunkts in Zeitquanten-Einheiten für nominale Bits fest; für klassisches CAN kann der Wert zwischen 1 und 8 einschließlich liegen. Dies entspricht Phase_Seg2 im Standard ISO-11898. Wenn dieser Wert gesetzt ist, muss auch tseg1 gesetzt sein.

Wenn diese Argumente angegeben werden, wird der CAN-Controller korrekt für die gewünschte bitrate und die angegebene Gesamtzahl der Zeitquanten pro Bit konfiguriert. Die Werte tseg1 und tseg2 haben Vorrang vor dem Argument sample_point, wenn alle diese Werte angegeben werden.

Bemerkung

Einzelne Controller-Hardware kann zusätzliche Einschränkungen für gültige Werte dieser Parameter haben und löst einen ValueError aus, wenn ein angegebener Wert nicht unterstützt wird.

Bemerkung

Bestimmte Controller-Hardware akzeptiert möglicherweise zusätzliche optionale Schlüsselwortparameter für hardwarespezifische Funktionen wie Oversampling.

set_filters(filters: list | tuple | None) None

Setzt Empfangsfilter im CAN-Controller. filters kann sein:

  • None, um alle eingehenden Nachrichten zu akzeptieren, oder

  • [] oder (), um den gesamten Nachrichtenempfang zu deaktivieren, oder

  • ein iterierbares Objekt mit einem oder mehreren Elementen, die die Filterkriterien definieren. Jedes Element sollte ein Tupel oder eine Liste mit drei Elementen sein:

    • identifier ist ein CAN-Identifier (int).

    • bit_mask ist eine Bitmaske für Bits im CAN-Identifier-Feld (int).

    • flags ist eine ganze Zahl, bei der null oder mehr der in Nachrichten-Flags definierten Bits gesetzt sind. Dies gibt Eigenschaften an, mit denen die eingehende Nachricht übereinstimmen muss. Nicht alle Controller unterstützen das Filtern nach allen Flags; ein ValueError wird ausgelöst, wenn ein nicht unterstütztes Flag angefordert wird.

Eingehende Nachrichten werden akzeptiert, wenn die in bit_mask maskierten Bits zwischen dem Nachrichten-Identifier und dem Filterwert identifier übereinstimmen und die im Filter gesetzten Flags mit der eingehenden Nachricht übereinstimmen.

Wenn das Bit CAN.FLAG_EXT_ID in den Flags gesetzt ist, stimmt der Filter nur mit Extended-CAN-IDs überein. Wenn das Bit CAN.FLAG_EXT_ID nicht gesetzt ist, stimmt der Filter nur mit Standard-CAN-IDs überein.

Alle Filter werden im Controller durch ODER verknüpft. Die Übergabe einer leeren Liste oder eines leeren Tupels für das Argument filters bedeutet, dass keine Nachrichten empfangen werden.

Einige CAN-Controller erfordern, dass jeder Filter nur mit einem einzigen Empfangs-FIFO verknüpft ist. In diesen Fällen werden die Filterelemente im Argument im Round-Robin-Verfahren auf die verfügbaren FIFOs verteilt. Dieser Treiber unterscheidet im Empfangs-IRQ nicht zwischen FIFOs.

Bemerkung

Wenn der Aufrufer ein iterierbares Objekt mit mehr Elementen als CAN.FILTERS_MAX übergibt, wird ein ValueError ausgelöst.

Bemerkung

Wenn entweder identifier oder bit_mask außerhalb des Bereichs für den angegebenen ID-Typ liegt, wird ein ValueError mit dem Grund „invalid id“ ausgelöst.

Beispiele

Alle eingehenden Nachrichten empfangen:

can.set_filters(None)

Nur Nachrichten mit den Standard-ID-Werten 0x301 und 0x700 empfangen:

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

Nachrichten mit Standard-ID-Werten im Bereich 0x300-0x3FF und nur dem Extended-ID-Wert 0x50700 empfangen:

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

Konstanter Wert, der die maximale Anzahl der von diesem Hardware-Controller unterstützten Empfangsfilter liefert.

Beachten Sie, dass einige Controller komplexere Hardware-Einschränkungen für die Anzahl der verwendeten Filter haben können (zum Beispiel das unabhängige Zählen von Standard- und Extended-ID-Filtern). In diesen Fällen kann CAN.set_filters einen ValueError auslösen, selbst wenn das Limit FILTERS_MAX nicht überschritten wird.

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

Kopiert eine neue CAN-Nachricht in die Hardware-Sendewarteschlange des Controllers, um sie auf den Bus zu senden. Die Sendewarteschlange ist eine Prioritätswarteschlange, sortiert nach der Priorität des CAN-Identifiers (niedrigere numerische Identifier haben höhere Priorität).

  • id ist ein ganzzahliger CAN-Identifier-Wert.

  • data ist ein Bytes-Objekt (oder ähnlich), das die CAN-Nachrichtendaten enthält oder eine Remote Transmission Request beschreibt (siehe unten).

  • flags ist eine ganze Zahl, bei der null oder mehr der in Nachrichten-Flags definierten Bits gesetzt sind und die Eigenschaften der ausgehenden CAN-Nachricht angeben (Extended ID, Remote Transmission Request usw.).

Wenn die Nachricht erfolgreich zum Senden auf den Bus in die Warteschlange eingereiht wird, gibt die Funktion eine ganze Zahl im Bereich von 0 bis CAN.TX_QUEUE_LEN (exklusiv) zurück. Dieser Wert ist der Sendepuffer-Index, in den die Nachricht zum Senden eingereiht wurde, und kann von der Funktion CAN.cancel_send sowie in CAN.IRQ_TX-Ereignissen verwendet werden.

Wenn die Warteschlange voll ist, schlägt das Senden fehl und None wird zurückgegeben.

Das Senden kann auch fehlschlagen und None zurückgeben, wenn der angegebene id-Wert die gleiche Priorität wie eine bestehende Nachricht in der Sendewarteschlange hat und die CAN-Controller-Hardware nicht garantieren kann, dass Nachrichten mit derselben ID in derselben Reihenfolge auf den Bus gesendet werden, in der sie der Warteschlange hinzugefügt wurden. Um die Nachricht dennoch einzureihen, übergeben Sie das Flag CAN.FLAG_UNORDERED im Argument flags. Dieses Flag gibt an, dass es in Ordnung ist, Nachrichten mit derselben CAN-ID in beliebiger Reihenfolge auf den Bus zu senden.

Wenn sich der Controller im Fehlerzustand „Bus Off“ befindet oder deaktiviert ist, löst der Aufruf dieser Funktion einen OSError aus.

Bemerkung

Diese absichtlich auf niedriger Ebene gehaltene Implementierung ist so konzipiert, dass der Aufrufer eine Software-Warteschlange ausgehender Nachrichten einrichten kann.

Wichtig

Die CAN-„Sendewarteschlange“ ist keine FIFO-Warteschlange, sondern prioritätsgeordnet, und obwohl sie bis zu CAN.TX_QUEUE_LEN Elemente aufnehmen kann, gibt es möglicherweise weitere Hardware-Einschränkungen für Nachrichten, die gleichzeitig eingereiht werden können.

Remote Transmission Requests

Wenn das Bit CAN.FLAG_RTR im Argument flags gesetzt ist, sendet der Controller eine Remote Transmission Request anstelle einer Nachricht. In diesem Fall wird der Inhalt des Arguments data ignoriert. Der Controller sendet eine Anfrage, bei der das Längenfeld DLC gleich der Länge des Arguments data ist.

Beispiele

Versuch, eine Nachricht mit drei Byte Nutzdaten 0a0b0c und der Standard-ID 0x200 zu senden:

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

Versuch, eine Nachricht mit leeren Nutzdaten und der Extended-ID 0x180008 zu senden. Geben Sie an, dass der Controller Nachrichten mit dieser ID in beliebiger Reihenfolge senden kann, für den Fall, dass bereits andere Nachrichten mit derselben ID zum Senden in der Warteschlange stehen:

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

Versuch, eine Remote Transmission Request mit der Länge 8 Byte und der Standard-ID 0x555 zu senden:

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

Gibt eine CAN-Nachricht zurück, die vom Controller gemäß den mit CAN.set_filters() gesetzten Filtern empfangen wurde.

Diese Funktion nimmt ein einziges optionales Argument entgegen; wenn es angegeben wird, muss es eine Liste mit mindestens 4 Elementen sein, deren zweites Element ein memoryview-Objekt ist, das auf ein bytearray oder ein ähnliches Objekt verweist, das genügend Kapazität hat, um jede empfangene CAN-Nachricht aufzunehmen (8 Byte für CAN Classic, 64 Byte für CAN FD). Die bereitgestellte Liste wird als erfolgreiches Ergebnis zurückgegeben und vermeidet eine Speicherallokation innerhalb der Funktion.

Wenn der CAN-Controller keine Nachrichten empfangen hat, gibt diese Funktion None zurück.

Bemerkung

CAN.set_filters muss aufgerufen werden, bevor der Controller Nachrichten empfangen kann. Um alle Nachrichten zu empfangen, rufen Sie set_filters(None) auf.

Wenn der CAN-Controller eine Nachricht empfangen hat, gibt diese Funktion eine Liste mit 4 Elementen zurück:

  • Index 0 ist die CAN-ID der empfangenen Nachricht als ganze Zahl.

  • Index 1 ist ein memoryview, der Zugriff auf die empfangenen Nachrichtendaten bietet.

    • Wenn arg nicht angegeben wird, ist dies ein memoryview, der die empfangenen Bytes enthält. Dieser memoryview wird von einem neu allozierten bytearray gestützt, das groß genug ist, um jede empfangene CAN-Nachricht aufzunehmen. Dadurch kann das Ergebnis sicher als zukünftiges arg wiederverwendet werden, um Speicherallokationen einzusparen.

    • Wenn arg angegeben wird, wird der bereitgestellte memoryview so angepasst, dass er genau die empfangenen Bytes aufnimmt. Der Aufrufer ist dafür verantwortlich, sicherzustellen, dass das stützende Objekt des memoryview eine CAN-Nachricht beliebiger Länge aufnehmen kann.

  • Index 2 ist eine ganze Zahl, bei der null oder mehr der in Nachrichten-Flags definierten Bits gesetzt sind. Sie gibt Metadaten über die empfangene Nachricht an.

  • Index 3 ist eine ganze Zahl, bei der null oder mehr der in Empfangsfehler-Flags definierten Bits gesetzt sind. Jeder Wert ungleich null weist auf potenzielle Probleme beim Empfang von CAN-Nachrichten hin. Diese Flags werden im Controller bei jedem Rückgabewert dieser Funktion zurückgesetzt.

Remote Transmission Requests

Wenn eine Remote Transmission Request empfangen wird, wird das Bit CAN.FLAG_RTR in Index 2 gesetzt, und der memoryview an Index 1 enthält ausschließlich Nullen mit einer Länge gleich dem Feld DLC der empfangenen Anfrage.

Beispiel
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

Setzt eine Interrupt-Handler-Funktion handler, die aufgerufen wird, wenn eines oder mehrere der in trigger markierten Ereignisse eingetreten ist.

  • handler ist eine Funktion, die aufgerufen wird, wenn das Interrupt-Ereignis ausgelöst wird. Der Handler muss genau ein Argument entgegennehmen, nämlich die CAN-Instanz.

  • trigger konfiguriert die Ereignisse, die einen Interrupt erzeugen können. Mögliche Werte sind eine Maske aus einem oder mehreren der folgenden:

    • Das Ereignis CAN.IRQ_RX tritt auf, nachdem der CAN-Controller mindestens eine Nachricht in seinen RX-FIFO empfangen hat (was bedeutet, dass CAN.recv() erfolgreich zurückkehrt).

    • Das Ereignis CAN.IRQ_TX tritt auf, nachdem der CAN-Controller entweder erfolgreich eine Nachricht auf den CAN-Bus gesendet hat oder das Senden einer Nachricht fehlgeschlagen ist. Dieser Trigger stellt zusätzliche Anforderungen an den Handler, Einzelheiten siehe IRQ-Flags.

    • Das Ereignis CAN.IRQ_STATE tritt auf, wenn der CAN-Controller in einen schwerwiegenderen Fehlerzustand übergegangen ist. Rufen Sie CAN.state() auf, um den aktualisierten Zustand zu erhalten.

  • hard wenn True, wird ein Hard-Interrupt verwendet. Dies verringert die Verzögerung zwischen dem CAN-Controller-Ereignis und dem Aufruf des Handlers. Hard-Interrupt-Handler dürfen keinen Speicher allozieren; siehe Interrupt-Handler schreiben.

Gibt ein irq-Objekt zurück. Wird ohne Argumente aufgerufen, wird ein zuvor konfiguriertes irq-Objekt zurückgegeben.

Ein Beispiel finden Sie unter IRQ-Flags.

cancel_send(index: int) bool

Fordert den CAN-Controller auf, das Senden einer Nachricht auf den Bus abzubrechen.

Das Argument index identifiziert einen einzelnen Sendepuffer. Es sollte eine ganze Zahl im Bereich von 0 bis CAN.TX_QUEUE_LEN (exklusiv) sein. Im Allgemeinen ist dies ein Wert, der zuvor von CAN.send() zurückgegeben wurde.

Das Ergebnis ist True, wenn in diesem Puffer eine Nachricht zur Übertragung anstand und die Übertragung abgebrochen wurde.

Andernfalls ist das Ergebnis False (entweder stand keine Nachricht in diesem Puffer zur Übertragung an, oder die Übertragung war bereits erfolgreich).

Das IRQ-Ereignis CAN.IRQ_TX sollte verwendet werden, um festzustellen, ob eine Nachricht definitiv gesendet wurde oder nicht. Beachten Sie jedoch, dass es zu potenziellen Race Conditions kommen kann, wenn eine Übertragung abgebrochen und dann derselbe Puffer zum Senden einer anderen Nachricht verwendet wird (insbesondere, wenn der CAN-Controller-IRQ nicht „hard“ ist).

state() int

Gibt einen ganzzahligen Wert zurück, der den aktuellen Zustand des Controllers angibt. Der Wert ist einer der unter Zustände definierten Werte.

Fehlerzustände geringerer Schwere können sich automatisch löschen, wenn sich der Bus erholt, aber der Zustand CAN.STATE_BUS_OFF kann nur durch Aufruf von CAN.restart() behoben werden.

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

Gibt die Fehlerzählerwerte des Controllers zurück. Das Ergebnis ist eine Liste mit acht Werten. Wenn der optionale Parameter list angegeben wird, wird das bereitgestellte Listenobjekt aktualisiert und als Ergebnis zurückgegeben, um eine Allokation zu vermeiden.

Die Listeneinträge sind:

  • Wert des TEC (Transmit Error Counter)

  • Wert des REC (Receive Error Counter)

  • Anzahl der Übergänge des Controllers vom Active-Zustand in den Warning-Zustand.

  • Anzahl der Übergänge des Controllers vom Warning-Zustand in den Error-Passive-Zustand.

  • Anzahl der Übergänge des Controllers vom Error-Passive-Zustand in den Bus-Off-Zustand.

  • Gesamtzahl der ausstehenden TX-Nachrichten in der Hardware-Warteschlange.

  • Gesamtzahl der ausstehenden RX-Nachrichten in der Hardware-Warteschlange.

  • Anzahl der aufgetretenen RX-Überläufe.

Bemerkung

Je nach Controller können diese Werte nach einem bestimmten Wert wieder auf 0 überlaufen.

Bemerkung

Wenn ein Controller einen bestimmten Zähler nicht unterstützt, gibt er für dieses Listenelement None zurück.

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

Gibt eine Liste von Elementen zurück, die die aktuell im CAN-Controller konfigurierten Timings angeben. Dies kann zur Überprüfung der Timings zu Debugging-Zwecken verwendet werden. Das Ergebnis ist eine Liste mit sechs Werten. Wenn der optionale Parameter list angegeben wird, wird das bereitgestellte Listenobjekt aktualisiert und als Ergebnis zurückgegeben, um eine Allokation zu vermeiden.

Die Listeneinträge sind:

  • Die exakt vom Controller verwendete Bitrate. Kann aufgrund der Quantisierung zur Einhaltung von Hardware-Einschränkungen vom an CAN.init() übergebenen Argument bitrate abweichen.

  • Resynchronisations-Sprungweite (SJW) in Zeitquanten-Einheiten für nominale Bits. Hat dieselbe Bedeutung wie der Parameter sjw von CAN.init().

  • Position des Abtastpunkts in Zeitquanten-Einheiten für nominale Bits. Hat dieselbe Bedeutung wie der Parameter tseg1 von CAN.init().

  • Position des Sendepunkts in Zeitquanten-Einheiten für nominale Bits. Hat dieselbe Bedeutung wie der Parameter tseg2 von CAN.init().

  • CAN-FD-Timing-Informationen. None für Controller, die CAN FD nicht unterstützen, oder wenn CAN FD nicht initialisiert ist. Andernfalls eine verschachtelte Liste mit vier Elementen, die den obigen Einträgen entsprechen, aber auf die CAN-FD-BRS-Funktion anwendbar sind.

  • Optionale controllerspezifische Timing-Informationen. Je nach Controller ist dies entweder None, wenn der Controller keine meldet, oder eine Liste konstanter Länge, deren Elemente für einen bestimmten Hardware-Controller spezifisch sind.

Bemerkung

Wenn CAN.init() nicht aufgerufen wurde, gibt diese Funktion dennoch ein Ergebnis zurück, das Ergebnis hängt jedoch von den Controller-Interna ab und ist möglicherweise nicht genau.

restart() None

Veranlasst den Controller, den Zustand STATE_BUS_OFF zu verlassen, ohne andere interne Zustände zu löschen. Löscht außerdem einige der Fehlerzähler (immer die Anzahl der Übergänge in jeden Fehlerzustand, je nach Controller möglicherweise auch TEC und REC).

Der Aufruf dieser Funktion bricht außerdem alle Nachrichten ab, die auf das Senden warten. Für diese Nachrichten werden keine IRQ_TX-Interrupts zugestellt.

Beachten Sie, dass diese Funktion den Controller je nach dem, ob die Controller-Hardware TEC und REC auf null setzt oder nicht, den Zustand „Error Passive“ verlassen lässt oder nicht.

deinit() None

Deinitialisiert eine zuvor aktive CAN-Instanz. Alle ausstehenden Nachrichten (Senden und Empfangen) werden verworfen, und der Controller hört auf, mit dem Bus zu interagieren. Um diese Instanz erneut zu verwenden, rufen Sie CAN.init() auf.

Als Reaktion auf den Aufruf dieser Funktion werden keine IRQ_TX- oder IRQ_RX-Interrupts aufgerufen.

Siehe auch CAN.restart().

Konstanten

TX_QUEUE_LEN: int

Maximale Anzahl von CAN-Nachrichten, die in der ausgehenden Hardware-Nachrichtenwarteschlange des Controllers eingereiht werden können. Die von CAN.send(), CAN.cancel_send() und IRQ-Flags verwendeten „Sendepuffer-Indizes“ liegen in diesem Bereich.

Modi

Diese Werte repräsentieren die Betriebsmodi des Controllers, wie sie an CAN.init() übergeben werden. Möglicherweise unterstützen nicht alle Controller alle Modi.

Das Ändern des Modus eines laufenden Controllers erfordert den Aufruf von CAN.deinit() und anschließend den erneuten Aufruf von CAN.init() mit dem neuen Modus.

MODE_NORMAL: int

Der Controller ist als standardmäßiger CAN-Netzwerkknoten aktiv (er bestätigt gültige Nachrichten und überträgt je nach seinem aktuellen Zustand möglicherweise Fehler).

MODE_SLEEP: int

Der CAN-Controller befindet sich in einem stromsparenden Schlafmodus. Je nach Controller kann dies das Aufwecken des Controllers und den Übergang zu CAN.MODE_NORMAL unterstützen, wenn CAN-Verkehr empfangen wird.

MODE_LOOPBACK: int

Ein Testmodus. Der CAN-Controller ist weiterhin mit dem externen Bus verbunden, empfängt aber auch seine eigenen gesendeten Nachrichten und ignoriert etwaige ACK-Fehler.

MODE_SILENT: int

Der CAN-Controller empfängt Nachrichten, interagiert aber nicht mit dem CAN-Bus (einschließlich des Sendens von ACKs, Fehlern usw.).

MODE_SILENT_LOOPBACK: int

Ein Testmodus, der überhaupt keinen angeschlossenen CAN-Transceiver erfordert. Der CAN-Controller empfängt seine eigenen gesendeten Nachrichten, ohne überhaupt mit dem CAN-Bus zu interagieren. Die CAN-TX- und -RX-Pins bleiben im Leerlauf.

Zustände

Diese Werte werden von CAN.state() zurückgegeben und spiegeln den Fehlerzustand des CAN-Controllers wider:

STATE_STOPPED: int

Der Controller wurde nicht initialisiert.

STATE_ACTIVE: int

Der Controller ist aktiv, und die Fehlerzähler TEC und REC liegen beide unter dem Warnschwellenwert von 96. Siehe CAN.get_counters().

STATE_WARNING: int

Der Controller ist aktiv, aber mindestens einer der Fehlerzähler TEC und REC liegt zwischen 96 und 127. Siehe CAN.get_counters().

STATE_PASSIVE: int

Der Controller befindet sich im Zustand „Error Passive“, das heißt, er überträgt keine aktiven Fehler mehr auf den Bus, ist aber ansonsten funktionsfähig. Dieser Zustand wird betreten, wenn mindestens einer der Fehlerzähler TEC und REC 128 oder größer ist, TEC jedoch kleiner als 255 ist. Siehe CAN.get_counters().

STATE_BUS_OFF: int

Der Controller befindet sich im Bus-Off-Zustand, das heißt, der Fehlerzähler TEC ist größer als 255. Der CAN-Controller interagiert in diesem Zustand nicht mit dem Bus und muss über CAN.restart() neu gestartet werden, um fortzufahren.

Nachrichten-Flags

Diese Werte repräsentieren Metadaten über eine CAN-Nachricht. Die Funktionen CAN.send(), CAN.recv() und CAN.set_filters() akzeptieren oder liefern einen ganzzahligen Wert, der aus null oder mehr dieser bitweise mit ODER verknüpften Flags besteht.

FLAG_RTR: int

Gibt an, dass eine Nachricht eine Remote Transmission Request ist.

FLAG_EXT_ID: int

Wenn gesetzt, gibt es an, dass ein Nachrichten-Identifier erweitert ist (29-Bit). Wenn nicht gesetzt, gibt es an, dass ein Nachrichten-Identifier Standard ist (11-Bit).

FLAG_UNORDERED: int

Wenn im Argument flags von CAN.send() gesetzt, gibt es an, dass es in Ordnung ist, wenn Nachrichten mit derselben CAN-ID in beliebiger Reihenfolge auf den Bus gesendet werden.

Andernfalls kann der Versuch, mehrere Nachrichten mit derselben ID einzureihen, dazu führen, dass CAN.send() fehlschlägt, wenn die Controller-Hardware die Reihenfolge nicht erzwingen kann.

Dieses Flag wird bei empfangenen Nachrichten niemals gesetzt und von CAN.set_filters() ignoriert.

Empfangsfehler-Flags

Das Ergebnis von CAN.recv() enthält einen ganzzahligen Wert, der aus null oder mehr dieser bitweise mit ODER verknüpften Flags besteht. Wenn gesetzt, weisen diese Flags auf potenzielle allgemeine Probleme beim Empfang von CAN-Nachrichten hin.

RECV_ERR_FULL: int

Der Hardware-FIFO, in dem diese Nachricht empfangen wurde, ist voll, und zusätzliche eingehende Nachrichten können verloren gehen.

RECV_ERR_OVERRUN: int

Der Hardware-FIFO, in dem diese Nachricht empfangen wurde, ist voll, und eine oder mehrere eingehende Nachrichten sind verloren gegangen.

IRQ-Werte

IRQ_RX: int

An das Argument trigger von irq() übergeben, um den Handler jedes Mal auszulösen, wenn der CAN-Controller eine vollständige Nachricht in den RX-FIFO empfangen hat. Lesen Sie die Nachricht innerhalb des Handlers mit recv().

IRQ_TX: int

An das Argument trigger von irq() übergeben, um den Handler jedes Mal auszulösen, wenn der CAN-Controller einen Sendeversuch abschließt (Erfolg oder Fehlschlag). Verwenden Sie innerhalb des Handlers die zusätzlichen Bits unten, um zu ermitteln, welche Mailbox abgeschlossen wurde und ob sie fehlgeschlagen ist – siehe IRQ-Flags.

IRQ_STATE: int

An das Argument trigger von irq() übergeben, um den Handler jedes Mal auszulösen, wenn der Controller zwischen den STATE_*-Werten wechselt (active / warning / passive / bus-off). Verwenden Sie state() innerhalb des Handlers, um den neuen Zustand zu lesen.

IRQ_TX_FAILED: int

Statusflag, das in irq().flags() gesetzt sein kann, wenn ein IRQ_TX-Ereignis ausgelöst wird. Gibt an, dass der Sendeversuch fehlgeschlagen ist (typischerweise weil cancel_send() aufgerufen wurde oder der Controller in einen Fehlerzustand übergegangen ist).

IRQ_TX_IDX_SHIFT: int

Bitposition des Sende-Mailbox-Index-Feldes innerhalb des Wertes irq().flags() während eines IRQ_TX-Ereignisses. Der Mailbox-Index wird als (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK extrahiert.

IRQ_TX_IDX_MASK: int

Bitmaske des Sende-Mailbox-Index-Feldes innerhalb des Wertes irq().flags() während eines IRQ_TX-Ereignisses. Der extrahierte Index entspricht der ganzen Zahl, die vom zugehörigen send()-Aufruf zurückgegeben wurde (eine ganze Zahl im Bereich von 0 bis TX_QUEUE_LEN).

IRQ-Flags

Der Aufruf von CAN.irq() registriert einen Interrupt-Handler mit einem oder mehreren der Trigger CAN.IRQ_RX, CAN.IRQ_TX und CAN.IRQ_STATE.

Die Funktion gibt ein IRQ-Objekt zurück, und der Aufruf der Funktion flags() für dieses Objekt gibt eine ganze Zahl zurück, die angibt, welche Trigger-Ereignisse den Interrupt ausgelöst haben. Ein CAN-IRQ-Handler sollte die Funktion flags() wiederholt aufrufen, bis sie 0 zurückgibt.

Wenn die Funktion flags() mit gesetztem Bit CAN.IRQ_TX zurückkehrt, kann der Handler auch die folgenden Flag-Bits im Ergebnis auf zusätzliche Informationen über das TX-Ereignis prüfen:

  • Das Bit CAN.IRQ_TX_FAILED ist gesetzt, wenn das Senden fehlgeschlagen ist. Normalerweise geschieht dies nur, wenn CAN.cancel_send() aufgerufen wurde, es kann aber auch geschehen, wenn der Controller in einen Fehlerzustand übergeht.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT ist ein bitmaskierter Bereich des Flags-Wertes, der den Index des Sendepuffers enthält, der das Ereignis erzeugt hat. Dies ist eine ganze Zahl im Bereich von 0 bis CAN.TX_QUEUE_LEN (exklusiv) und entspricht dem Ergebnis eines vorherigen Aufrufs von CAN.send().

IRQ_TX-Beispiel

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)

Wichtig

Wenn der Trigger CAN.IRQ_TX gesetzt ist, muss der Handler flags() wiederholt aufrufen, bis es 0 zurückgibt, wie in diesem Beispiel gezeigt. Andernfalls werden CAN-Interrupts möglicherweise nicht korrekt wieder aktiviert.