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:
ididentifiziert 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_SegundPhase_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_Seg2im 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
ValueErroraus, 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, oderein iterierbares Objekt mit einem oder mehreren Elementen, die die Filterkriterien definieren. Jedes Element sollte ein Tupel oder eine Liste mit drei Elementen sein:
identifierist ein CAN-Identifier (int).bit_maskist eine Bitmaske für Bits im CAN-Identifier-Feld (int).flagsist 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; einValueErrorwird ausgelöst, wenn ein nicht unterstütztes Flag angefordert wird.
Eingehende Nachrichten werden akzeptiert, wenn die in
bit_maskmaskierten Bits zwischen dem Nachrichten-Identifier und dem Filterwertidentifierübereinstimmen und die im Filter gesetzten Flags mit der eingehenden Nachricht übereinstimmen.Wenn das Bit
CAN.FLAG_EXT_IDin den Flags gesetzt ist, stimmt der Filter nur mit Extended-CAN-IDs überein. Wenn das BitCAN.FLAG_EXT_IDnicht 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 einValueErrorausgelöst.Bemerkung
Wenn entweder
identifieroderbit_maskaußerhalb des Bereichs für den angegebenen ID-Typ liegt, wird einValueErrormit 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_filterseinenValueErrorauslösen, selbst wenn das LimitFILTERS_MAXnicht ü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
0bisCAN.TX_QUEUE_LEN(exklusiv) zurück. Dieser Wert ist der Sendepuffer-Index, in den die Nachricht zum Senden eingereiht wurde, und kann von der FunktionCAN.cancel_sendsowie inCAN.IRQ_TX-Ereignissen verwendet werden.Wenn die Warteschlange voll ist, schlägt das Senden fehl und
Nonewird zurückgegeben.Das Senden kann auch fehlschlagen und
Nonezurü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 FlagCAN.FLAG_UNORDEREDim 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
OSErroraus.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_LENElemente 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_RTRim 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ängenfeldDLCgleich der Länge des Arguments data ist.Beispiele¶
Versuch, eine Nachricht mit drei Byte Nutzdaten
0a0b0cund 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 einbytearrayoder 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
Nonezurück.Bemerkung
CAN.set_filtersmuss aufgerufen werden, bevor der Controller Nachrichten empfangen kann. Um alle Nachrichten zu empfangen, rufen Sieset_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. Diesermemoryviewwird von einem neu alloziertenbytearraygestü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
memoryviewso angepasst, dass er genau die empfangenen Bytes aufnimmt. Der Aufrufer ist dafür verantwortlich, sicherzustellen, dass das stützende Objekt desmemoryvieweine 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_RTRin Index 2 gesetzt, und der memoryview an Index 1 enthält ausschließlich Nullen mit einer Länge gleich dem FeldDLCder 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_RXtritt auf, nachdem der CAN-Controller mindestens eine Nachricht in seinen RX-FIFO empfangen hat (was bedeutet, dassCAN.recv()erfolgreich zurückkehrt).Das Ereignis
CAN.IRQ_TXtritt 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_STATEtritt auf, wenn der CAN-Controller in einen schwerwiegenderen Fehlerzustand übergegangen ist. Rufen SieCAN.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
0bisCAN.TX_QUEUE_LEN(exklusiv) sein. Im Allgemeinen ist dies ein Wert, der zuvor vonCAN.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_TXsollte 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_OFFkann nur durch Aufruf vonCAN.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
Nonezurü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.
Nonefü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_OFFzu 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- oderIRQ_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 vonCAN.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_NORMALunterstü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.
Zustände¶
Diese Werte werden von
CAN.state()zurückgegeben und spiegeln den Fehlerzustand des CAN-Controllers wider:- STATE_ACTIVE: int¶
Der Controller ist aktiv, und die Fehlerzähler
TECundRECliegen beide unter dem Warnschwellenwert von 96. SieheCAN.get_counters().
- STATE_WARNING: int¶
Der Controller ist aktiv, aber mindestens einer der Fehlerzähler
TECundRECliegt zwischen 96 und 127. SieheCAN.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
TECundREC128 oder größer ist,TECjedoch kleiner als 255 ist. SieheCAN.get_counters().
- STATE_BUS_OFF: int¶
Der Controller befindet sich im Bus-Off-Zustand, das heißt, der Fehlerzähler
TECist größer als 255. Der CAN-Controller interagiert in diesem Zustand nicht mit dem Bus und muss überCAN.restart()neu gestartet werden, um fortzufahren.
Nachrichten-Flags¶
Diese Werte repräsentieren Metadaten über eine CAN-Nachricht. Die Funktionen
CAN.send(),CAN.recv()undCAN.set_filters()akzeptieren oder liefern einen ganzzahligen Wert, der aus null oder mehr dieser bitweise mit ODER verknüpften Flags besteht.- 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
flagsvonCAN.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.IRQ-Werte¶
- IRQ_RX: int¶
An das Argument
triggervonirq()ü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 mitrecv().
- IRQ_TX: int¶
An das Argument
triggervonirq()ü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
triggervonirq()übergeben, um den Handler jedes Mal auszulösen, wenn der Controller zwischen denSTATE_*-Werten wechselt (active / warning / passive / bus-off). Verwenden Siestate()innerhalb des Handlers, um den neuen Zustand zu lesen.
- IRQ_TX_FAILED: int¶
Statusflag, das in
irq().flags()gesetzt sein kann, wenn einIRQ_TX-Ereignis ausgelöst wird. Gibt an, dass der Sendeversuch fehlgeschlagen ist (typischerweise weilcancel_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 einesIRQ_TX-Ereignisses. Der Mailbox-Index wird als(flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASKextrahiert.
- IRQ_TX_IDX_MASK: int¶
Bitmaske des Sende-Mailbox-Index-Feldes innerhalb des Wertes
irq().flags()während einesIRQ_TX-Ereignisses. Der extrahierte Index entspricht der ganzen Zahl, die vom zugehörigensend()-Aufruf zurückgegeben wurde (eine ganze Zahl im Bereich von0bisTX_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_FAILEDist gesetzt, wenn das Senden fehlgeschlagen ist. Normalerweise geschieht dies nur, wennCAN.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_SHIFTist 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 von0bisCAN.TX_QUEUE_LEN(exklusiv) und entspricht dem Ergebnis eines vorherigen Aufrufs vonCAN.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.