classe CAN – protocole Controller Area Network

CAN est un protocole série à deux fils utilisé pour la transmission fiable de messages en temps réel entre un ou plusieurs nœuds connectés à un bus commun. CAN 2.0 a été normalisé dans la norme ISO-11898 et est désormais également connu sous le nom de CAN Classic.

Il existe également un protocole plus récent et rétrocompatible nommé CAN FD (CAN with Flexible Data-Rate). Le pilote machine.CAN ne prend actuellement pas en charge les fonctionnalités CAN FD ; utilisez pyb.CAN sur STM32 si vous avez besoin de CAN FD.

La prise en charge de CAN nécessite un contrôleur (souvent un périphérique interne du microcontrôleur) et un émetteur-récepteur externe pour adapter le niveau des signaux sur le bus CAN.

Disponible sur les OpenMV cams STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, ainsi que les variantes de marque Arduino qui câblent un émetteur-récepteur). Pas encore pris en charge sur l’OpenMV Cam RT1062 (port mimxrt) ni sur l’OpenMV Cam AE3 (port alif).

L’interface machine.CAN est une interface de messagerie CAN de bas niveau et basique qui présente un contrôleur CAN sous la forme d’une file d’attente de priorité sortante pour l’envoi des messages, d’une file d’attente entrante pour la réception des messages, et de mécanismes de signalement des erreurs.

Note

Les modules micropython-lib can et aiocan prévus seront la méthode recommandée pour utiliser CAN avec MicroPython.

Constructeur

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

Construit un objet contrôleur CAN avec l’identifiant donné :

  • id identifie un objet contrôleur CAN particulier ; il est spécifique à la carte et au port.

  • Tous les autres arguments sont passés à CAN.init(). Au moins un argument (bitrate) doit être fourni.

Les versions futures de cette classe pourront également accepter ici des arguments nommés spécifiques au port qui configurent le matériel. Actuellement, aucun argument nommé de ce type n’est implémenté.

Exemple

Construire et initialiser le contrôleur CAN 1 avec un débit de 500 kbit/s

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

Méthodes

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

Initialise le bus CAN avec les paramètres donnés :

  • bitrate est le débit binaire souhaité du bus en bits par seconde.

  • mode est l’une des valeurs indiquées sous Modes, désignant le mode de fonctionnement souhaité. La valeur par défaut est le fonctionnement « normal » sur le bus.

Les paramètres suivants sont facultatifs et concernent les temporisations des bits CAN. Dans la plupart des cas, vous pouvez laisser ces paramètres aux valeurs par défaut :

  • sample_point est un pourcentage entier du temps d’un bit de données. Il spécifie la position de l’échantillonnage du bit par rapport au temps nominal total du bit. Le pilote CAN calculera les paramètres en conséquence. Ce paramètre est ignoré si tseg1 et tseg2 sont définis.

  • sjw est la largeur de saut de resynchronisation en unités de quanta de temps pour les bits nominaux ; il peut prendre une valeur comprise entre 1 et 4 inclus pour le CAN classique.

  • tseg1 définit l’emplacement du point d’échantillonnage en unités de quanta de temps pour les bits nominaux ; il peut prendre une valeur comprise entre 1 et 16 inclus pour le CAN classique. Il s’agit de la somme des phases Prop_Seg et Phase_Seg1 telles que définies dans la norme ISO-11898. Si cette valeur est définie, alors tseg2 doit également l’être et sample_point est ignoré.

  • tseg2 définit l’emplacement du point de transmission en unités de quanta de temps pour les bits nominaux ; il peut prendre une valeur comprise entre 1 et 8 inclus pour le CAN classique. Cela correspond à Phase_Seg2 dans la norme ISO-11898. Si cette valeur est définie, alors tseg1 doit également l’être.

Si ces arguments sont spécifiés, le contrôleur CAN est configuré correctement pour le bitrate souhaité et le nombre total de quanta de temps par bit spécifié. Les valeurs tseg1 et tseg2 prévalent sur l’argument sample_point si tous ces éléments sont fournis.

Note

Le matériel de certains contrôleurs peut imposer des restrictions supplémentaires sur les valeurs valides de ces paramètres, et lèvera une ValueError si une valeur donnée n’est pas prise en charge.

Note

Le matériel de certains contrôleurs spécifiques peut accepter des arguments nommés facultatifs supplémentaires pour des fonctionnalités propres au matériel, telles que le suréchantillonnage.

set_filters(filters: list | tuple | None) None

Définit les filtres de réception dans le contrôleur CAN. filters peut être :

  • None pour accepter tous les messages entrants, ou

  • [] ou () pour désactiver toute réception de messages, ou

  • un itérable d’un ou plusieurs éléments définissant les critères de filtrage. Chaque élément doit être un tuple ou une liste de trois éléments :

    • identifier est un identifiant CAN (int).

    • bit_mask est un masque de bits pour les bits du champ d’identifiant CAN (int).

    • flags est un entier comportant zéro ou plusieurs des bits définis dans Drapeaux de message. Cela spécifie les propriétés auxquelles le message entrant doit correspondre. Tous les contrôleurs ne prennent pas en charge le filtrage sur tous les drapeaux ; une ValueError est levée si un drapeau non pris en charge est demandé.

Les messages entrants sont acceptés si les bits masqués dans bit_mask correspondent entre l’identifiant du message et la valeur identifier du filtre, et si les drapeaux définis dans le filtre correspondent au message entrant.

Si le bit CAN.FLAG_EXT_ID est défini dans les drapeaux, le filtre ne correspond qu’aux ID CAN étendus. Si le bit CAN.FLAG_EXT_ID n’est pas défini, le filtre ne correspond qu’aux ID CAN standard.

Tous les filtres sont combinés par OU dans le contrôleur. Passer une liste ou un tuple vide pour l’argument filters signifie qu’aucun message ne sera reçu.

Certains contrôleurs CAN exigent que chaque filtre soit associé à une seule FIFO de réception. Dans ces cas, les éléments de filtre de l’argument sont répartis à tour de rôle (round-robin) entre les FIFO disponibles. Ce pilote ne fait pas de distinction entre les FIFO dans l’IRQ de réception.

Note

Si l’appelant passe un itérable comportant plus d’éléments que CAN.FILTERS_MAX, une ValueError sera levée.

Note

Si soit l”identifier soit le bit_mask est hors plage pour le type d’ID spécifié, une ValueError avec le motif « invalid id » sera levée.

Exemples

Recevoir tous les messages entrants

can.set_filters(None)

Recevoir uniquement les messages avec les valeurs d’ID standard 0x301 et 0x700

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

Recevoir les messages avec des valeurs d’ID standard dans la plage 0x300-0x3FF, et uniquement la valeur d’ID étendu 0x50700

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

Constante dont la valeur renseigne le nombre maximal de filtres de réception pris en charge par ce contrôleur matériel.

Notez que certains contrôleurs peuvent imposer des restrictions matérielles plus complexes sur le nombre de filtres utilisés (par exemple, en comptant indépendamment les filtres d’ID standard et étendu). Dans ces cas, CAN.set_filters peut lever une ValueError même lorsque la limite FILTERS_MAX n’est pas dépassée.

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

Copie un nouveau message CAN dans la file d’attente de transmission matérielle du contrôleur pour l’envoyer sur le bus. La file d’attente de transmission est une file de priorité triée selon la priorité de l’identifiant CAN (les identifiants numériquement plus bas ont une priorité plus élevée).

  • id est une valeur entière d’identifiant CAN.

  • data est un objet bytes (ou similaire) contenant les données du message CAN, ou décrivant une requête de transmission distante (Remote Transmission Request, voir ci-dessous).

  • flags est un entier comportant zéro ou plusieurs des bits définis dans Drapeaux de message, spécifiant les propriétés du message CAN sortant (ID étendu, requête de transmission distante, etc.).

Si le message est mis en file d’attente avec succès pour transmission sur le bus, la fonction renvoie un entier dans la plage 0 à CAN.TX_QUEUE_LEN (exclu). Cette valeur est l’index du tampon de transmission où le message est mis en file d’attente pour envoi, et peut être utilisée par la fonction CAN.cancel_send et dans les événements CAN.IRQ_TX.

Si la file d’attente est pleine, l’envoi échouera et None sera renvoyé.

L’envoi peut également échouer et renvoyer None si la valeur id fournie a une priorité égale à celle d’un message existant dans la file d’attente de transmission et que le matériel du contrôleur CAN ne peut pas garantir que les messages ayant le même ID seront envoyés sur le bus dans le même ordre que celui où ils ont été ajoutés à la file. Pour mettre le message en file d’attente malgré tout, passez le drapeau CAN.FLAG_UNORDERED dans l’argument flags. Ce drapeau indique qu’il est acceptable d’envoyer sur le bus des messages ayant le même ID CAN dans n’importe quel ordre.

Si le contrôleur est dans l’état d’erreur « Bus Off » ou désactivé, l’appel de cette fonction lèvera une OSError.

Note

Cette implémentation volontairement de bas niveau est conçue pour que l’appelant puisse établir une file d’attente logicielle de messages sortants.

Important

La « file d’attente de transmission » CAN n’est pas une file FIFO, elle est ordonnée par priorité, et bien qu’elle puisse contenir jusqu’à CAN.TX_QUEUE_LEN éléments, il peut exister d’autres restrictions matérielles sur les messages pouvant être mis en file d’attente simultanément.

Requêtes de transmission distante

Si le bit CAN.FLAG_RTR est défini dans l’argument flags, le contrôleur enverra une requête de transmission distante au lieu d’un message. Dans ce cas, le contenu de l’argument data est ignoré. Le contrôleur enverra une requête dont le champ de longueur DLC est égal à la longueur de l’argument data.

Exemples

Tenter d’envoyer un message avec une charge utile de trois octets 0a0b0c et un ID standard 0x200

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

Tenter d’envoyer un message avec une charge utile vide et un ID étendu 0x180008. Indiquer que le contrôleur peut envoyer des messages avec cet ID dans n’importe quel ordre, au cas où d’autres messages seraient déjà en file d’attente pour envoi avec le même ID

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

Tenter d’envoyer une requête de transmission distante d’une longueur de 8 octets et avec un ID standard 0x555

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

Renvoie un message CAN qui a été reçu par le contrôleur, conformément aux filtres définis par CAN.set_filters().

Cette fonction prend un seul argument facultatif ; s’il est fourni, ce doit être une liste d’au moins 4 éléments où le deuxième élément est un objet memoryview faisant référence à un bytearray ou un objet similaire dont la capacité est suffisante pour contenir n’importe quel message CAN reçu (8 octets pour le CAN Classic, 64 octets pour le CAN FD). La liste fournie sera renvoyée en tant que résultat valide, et évite l’allocation de mémoire à l’intérieur de la fonction.

Si aucun message n’a été reçu par le contrôleur CAN, cette fonction renvoie None.

Note

CAN.set_filters doit être appelée avant qu’aucun message ne puisse être reçu par le contrôleur. Pour recevoir tous les messages, appelez set_filters(None).

Si un message a été reçu par le contrôleur CAN, cette fonction renvoie une liste de 4 éléments :

  • L’index 0 est l’ID CAN du message reçu, sous forme d’entier.

  • L’index 1 est un memoryview qui donne accès aux données du message reçu.

    • Si arg n’est pas fourni, il s’agit d’un memoryview contenant les octets qui ont été reçus. Ce memoryview est adossé à un bytearray nouvellement alloué, suffisamment grand pour contenir n’importe quel message CAN reçu. Cela permet de réutiliser le résultat en toute sécurité comme un futur arg, afin d’économiser des allocations de mémoire.

    • Si arg est fourni, le memoryview fourni sera redimensionné pour contenir exactement les octets qui ont été reçus. Il incombe à l’appelant de s’assurer que l’objet adossé au memoryview peut contenir un message CAN de n’importe quelle longueur.

  • L’index 2 est un entier comportant zéro ou plusieurs des bits définis dans Drapeaux de message. Il indique des métadonnées sur le message reçu.

  • L’index 3 est un entier comportant zéro ou plusieurs des bits définis dans Drapeaux d’erreur de réception. Toute valeur non nulle indique des problèmes potentiels lors de la réception de messages CAN. Ces drapeaux sont réinitialisés à l’intérieur du contrôleur à chaque retour de cette fonction.

Requêtes de transmission distante

Si une requête de transmission distante est reçue, le bit CAN.FLAG_RTR sera défini à l’index 2 et le memoryview à l’index 1 contiendra uniquement des zéros, avec une longueur égale au champ DLC de la requête reçue.

Exemple
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

Définit une fonction de traitement d’interruption handler à appeler lorsqu’un ou plusieurs des événements signalés dans trigger se sont produits.

  • handler est une fonction à appeler lorsque l’événement d’interruption se déclenche. Le gestionnaire doit prendre exactement un argument, qui est l’instance CAN.

  • trigger configure le ou les événements pouvant générer une interruption. Les valeurs possibles sont un masque d’un ou plusieurs des éléments suivants :

    • L’événement CAN.IRQ_RX se produit après que le contrôleur CAN a reçu au moins un message dans sa FIFO RX (ce qui signifie que CAN.recv() retournera avec succès).

    • L’événement CAN.IRQ_TX se produit après que le contrôleur CAN a soit envoyé avec succès un message sur le bus CAN, soit échoué à envoyer un message. Ce déclencheur impose des exigences supplémentaires au gestionnaire, voir Drapeaux d’IRQ pour plus de détails.

    • L’événement CAN.IRQ_STATE se produit lorsque le contrôleur CAN est passé dans un état d’erreur plus grave. Appelez CAN.state() pour obtenir l’état mis à jour.

  • hard si True, une interruption matérielle est utilisée. Cela réduit le délai entre l’événement du contrôleur CAN et l’appel du gestionnaire. Les gestionnaires d’interruption matérielle ne peuvent pas allouer de mémoire ; voir Écriture de gestionnaires d’interruption.

Renvoie un objet irq. Si appelée sans argument, un objet irq précédemment configuré est renvoyé.

Voir Drapeaux d’IRQ pour un exemple.

cancel_send(index: int) bool

Demande au contrôleur CAN d’annuler l’envoi d’un message sur le bus.

L’argument index identifie un seul tampon de transmission. Ce doit être un entier dans la plage 0 à CAN.TX_QUEUE_LEN (exclu). En général, il s’agira d’une valeur précédemment renvoyée par CAN.send().

Le résultat est True si un message était en attente de transmission dans ce tampon et que la transmission a été annulée.

Le résultat est False sinon (soit aucun message n’était en attente de transmission dans ce tampon, soit la transmission a déjà réussi).

L’événement IRQ CAN.IRQ_TX doit être utilisé pour déterminer si un message a été ou non effectivement envoyé, mais notez qu’il existe des conditions de concurrence potentielles si une transmission est annulée puis que le même tampon est utilisé pour envoyer un autre message (surtout si l’IRQ du contrôleur CAN n’est pas « matérielle »).

state() int

Renvoie une valeur entière indiquant l’état actuel du contrôleur. La valeur sera l’une des valeurs définies dans États.

Les états d’erreur de moindre gravité peuvent se résorber automatiquement si le bus se rétablit, mais l’état CAN.STATE_BUS_OFF ne peut être récupéré qu’en appelant CAN.restart().

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

Renvoie les valeurs des compteurs d’erreurs du contrôleur. Le résultat est une liste de huit valeurs. Si le paramètre facultatif list est spécifié, l’objet liste fourni est mis à jour et renvoyé comme résultat, afin d’éviter une allocation.

Les éléments de la liste sont :

  • valeur du TEC (Transmit Error Counter)

  • valeur du REC (Receive Error Counter)

  • Nombre de fois où le contrôleur est passé de l’état Active à l’état Warning.

  • Nombre de fois où le contrôleur est passé de l’état Warning à l’état Error Passive.

  • Nombre de fois où le contrôleur est passé de l’état Error Passive à l’état Bus Off.

  • Nombre total de messages TX en attente dans la file d’attente matérielle.

  • Nombre total de messages RX en attente dans la file d’attente matérielle.

  • Nombre de fois où un débordement (overrun) RX s’est produit.

Note

Selon le contrôleur, ces valeurs peuvent revenir par débordement à 0 après une certaine valeur.

Note

Si un contrôleur ne prend pas en charge un compteur particulier, il renverra None pour cet élément de la liste.

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

Renvoie une liste d’éléments indiquant les temporisations actuellement configurées dans le contrôleur CAN. Cela peut être utilisé pour vérifier les temporisations à des fins de débogage. Le résultat est une liste de six valeurs. Si le paramètre facultatif list est spécifié, l’objet liste fourni est mis à jour et renvoyé comme résultat, afin d’éviter une allocation.

Les éléments de la liste sont :

  • Débit binaire exact utilisé par le contrôleur. Peut différer de l’argument bitrate passé à CAN.init() en raison de la quantification nécessaire pour respecter les contraintes matérielles.

  • Largeur de saut de resynchronisation (SJW) en unités de quanta de temps pour les bits nominaux. A la même signification que le paramètre sjw de CAN.init().

  • Emplacement du point d’échantillonnage en unités de quanta de temps pour les bits nominaux. A la même signification que le paramètre tseg1 de CAN.init().

  • Emplacement du point de transmission en unités de quanta de temps pour les bits nominaux. A la même signification que le paramètre tseg2 de CAN.init().

  • Informations de temporisation CAN FD. None pour les contrôleurs qui ne prennent pas en charge le CAN FD, ou si le CAN FD n’est pas initialisé. Sinon, une liste imbriquée de quatre éléments correspondant aux éléments ci-dessus mais applicables à la fonctionnalité BRS du CAN FD.

  • Informations de temporisation facultatives propres au contrôleur. Selon le contrôleur, ce sera soit None si le contrôleur n’en signale aucune, soit une liste de longueur constante dont les éléments sont spécifiques à un contrôleur matériel particulier.

Note

Si CAN.init() n’a pas été appelée, cette fonction renvoie tout de même un résultat, mais celui-ci dépend des éléments internes du contrôleur et peut ne pas être précis.

restart() None

Fait sortir le contrôleur de l’état STATE_BUS_OFF sans effacer aucun autre état interne. Réinitialise également certains des compteurs d’erreurs (toujours le nombre de fois où chaque état d’erreur a été atteint, et éventuellement le TEC et le REC selon le contrôleur).

L’appel de cette fonction annule également tous les messages en attente d’envoi. Aucune interruption IRQ_TX n’est délivrée pour ces messages.

Notez que cette fonction peut ou non faire sortir le contrôleur de l’état « Error Passive », selon que le matériel du contrôleur remet ou non à zéro le TEC et le REC.

deinit() None

Désinitialise une instance CAN précédemment active. Tous les messages en attente (transmission et réception) sont abandonnés et le contrôleur cesse d’interagir sur le bus. Pour réutiliser cette instance, appelez CAN.init().

Aucune interruption IRQ_TX ou IRQ_RX n’est appelée en réponse à l’appel de cette fonction.

Voir aussi CAN.restart().

Constantes

TX_QUEUE_LEN: int

Nombre maximal de messages CAN pouvant être mis en file d’attente dans la file d’attente de messages matérielle sortante du contrôleur. Les « index de tampon de transmission » utilisés par CAN.send(), CAN.cancel_send() et Drapeaux d’IRQ seront dans cette plage.

Modes

Ces valeurs représentent les modes de fonctionnement du contrôleur, tels que passés à CAN.init(). Tous les contrôleurs ne prennent pas nécessairement en charge tous les modes.

Changer le mode d’un contrôleur en cours d’exécution nécessite d’appeler CAN.deinit() puis d’appeler à nouveau CAN.init() avec le nouveau mode.

MODE_NORMAL: int

Le contrôleur est actif en tant que nœud standard d’un réseau CAN (il accusera réception des messages valides et pourra transmettre des erreurs selon son État actuel).

MODE_SLEEP: int

Le contrôleur CAN est en veille dans un mode basse consommation. Selon le contrôleur, cela peut permettre de réveiller le contrôleur et de le faire passer en CAN.MODE_NORMAL si du trafic CAN est reçu.

MODE_LOOPBACK: int

Un mode de test. Le contrôleur CAN est toujours connecté au bus externe, mais il recevra également ses propres messages transmis et ignorera toute erreur d’ACK.

MODE_SILENT: int

Le contrôleur CAN reçoit des messages mais n’interagit pas avec le bus CAN (y compris l’envoi d’ACK, d’erreurs, etc.).

MODE_SILENT_LOOPBACK: int

Un mode de test qui ne nécessite aucun émetteur-récepteur CAN connecté. Le contrôleur CAN reçoit ses propres messages transmis sans interagir du tout avec le bus CAN. Les broches TX et RX du CAN restent inactives.

États

Ces valeurs sont renvoyées par CAN.state() et reflètent l’état d’erreur du contrôleur CAN :

STATE_STOPPED: int

Le contrôleur n’a pas été initialisé.

STATE_ACTIVE: int

Le contrôleur est actif et les compteurs d’erreurs TEC et REC sont tous deux en dessous du seuil d’avertissement de 96. Voir CAN.get_counters().

STATE_WARNING: int

Le contrôleur est actif mais au moins l’un des compteurs d’erreurs TEC et REC est compris entre 96 et 127. Voir CAN.get_counters().

STATE_PASSIVE: int

Le contrôleur est dans l’état « Error Passive », ce qui signifie qu’il ne transmet plus d’erreurs actives sur le bus, mais qu’il reste par ailleurs fonctionnel. Cet état est atteint lorsqu’au moins l’un des compteurs d’erreurs TEC et REC est supérieur ou égal à 128, mais que TEC est inférieur à 255. Voir CAN.get_counters().

STATE_BUS_OFF: int

Le contrôleur est dans l’état Bus-Off, ce qui signifie que le compteur d’erreurs TEC est supérieur à 255. Le contrôleur CAN n’interagira pas avec le bus dans cet état, et doit être redémarré via CAN.restart() pour continuer.

Drapeaux de message

Ces valeurs représentent des métadonnées sur un message CAN. Les fonctions CAN.send(), CAN.recv() et CAN.set_filters() acceptent ou renvoient une valeur entière composée de zéro ou plusieurs de ces drapeaux combinés par OU bit à bit.

FLAG_RTR: int

Indique qu’un message est une requête de transmission distante.

FLAG_EXT_ID: int

Si défini, indique qu’un identifiant de message est étendu (29 bits). Si non défini, indique qu’un identifiant de message est standard (11 bits).

FLAG_UNORDERED: int

Si défini dans l’argument flags de CAN.send(), indique qu’il est acceptable que les messages ayant le même ID CAN soient envoyés sur le bus dans n’importe quel ordre.

Sinon, tenter de mettre en file d’attente plusieurs messages ayant le même ID peut entraîner l’échec de CAN.send() si le matériel du contrôleur ne peut pas garantir l’ordre.

Ce drapeau n’est jamais défini sur les messages reçus, et est ignoré par CAN.set_filters().

Drapeaux d’erreur de réception

Le résultat de CAN.recv() comprend une valeur entière composée de zéro ou plusieurs de ces drapeaux combinés par OU bit à bit. S’ils sont définis, ces drapeaux indiquent des problèmes généraux potentiels lors de la réception de messages CAN.

RECV_ERR_FULL: int

La FIFO matérielle où ce message a été reçu est pleine, et des messages entrants supplémentaires pourraient être perdus.

RECV_ERR_OVERRUN: int

La FIFO matérielle où ce message a été reçu est pleine, et un ou plusieurs messages entrants ont été perdus.

Valeurs d’IRQ

IRQ_RX: int

À passer à l’argument trigger de irq() pour déclencher le gestionnaire chaque fois que le contrôleur CAN a reçu un message complet dans la FIFO RX. À l’intérieur du gestionnaire, lisez le message avec recv().

IRQ_TX: int

À passer à l’argument trigger de irq() pour déclencher le gestionnaire chaque fois que le contrôleur CAN termine une tentative de transmission (réussite ou échec). À l’intérieur du gestionnaire, utilisez les bits supplémentaires ci-dessous pour déterminer quelle boîte aux lettres s’est terminée et si elle a échoué – voir Drapeaux d’IRQ.

IRQ_STATE: int

À passer à l’argument trigger de irq() pour déclencher le gestionnaire chaque fois que le contrôleur passe d’une valeur STATE_* à une autre (active / warning / passive / bus-off). Utilisez state() à l’intérieur du gestionnaire pour lire le nouvel état.

IRQ_TX_FAILED: int

Drapeau d’état qui peut être défini dans irq().flags() lorsqu’un événement IRQ_TX se déclenche. Indique que la tentative de transmission a échoué (généralement parce que cancel_send() a été appelée, ou que le contrôleur est entré dans un état d’erreur).

IRQ_TX_IDX_SHIFT: int

Position du bit du champ d’index de la boîte aux lettres de transmission au sein de la valeur irq().flags() lors d’un événement IRQ_TX. L’index de la boîte aux lettres est extrait par (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.

IRQ_TX_IDX_MASK: int

Masque de bits du champ d’index de la boîte aux lettres de transmission au sein de la valeur irq().flags() lors d’un événement IRQ_TX. L’index extrait correspond à l’entier renvoyé par l’appel send() correspondant (un int dans la plage 0 à TX_QUEUE_LEN).

Drapeaux d’IRQ

L’appel de CAN.irq() enregistre un gestionnaire d’interruption avec un ou plusieurs des déclencheurs CAN.IRQ_RX, CAN.IRQ_TX et CAN.IRQ_STATE.

La fonction renvoie un objet IRQ, et l’appel de la fonction flags() sur cet objet renvoie un entier indiquant quel(s) événement(s) déclencheur(s) ont déclenché l’interruption. Un gestionnaire d’IRQ CAN doit appeler la fonction flags() de manière répétée jusqu’à ce qu’elle renvoie 0.

Lorsque la fonction flags() retourne avec le bit CAN.IRQ_TX défini, le gestionnaire peut également vérifier les bits de drapeau suivants dans le résultat pour obtenir des informations supplémentaires sur l’événement TX :

  • Le bit CAN.IRQ_TX_FAILED est défini si la transmission a échoué. Habituellement, cela ne se produira que si CAN.cancel_send() a été appelée, bien que cela puisse également se produire si le contrôleur entre dans un état d’erreur.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT est une région masquée par bits de la valeur des drapeaux qui contient l’index du tampon de transmission ayant généré l’événement. Ce sera un entier dans la plage 0 à CAN.TX_QUEUE_LEN (exclu), et correspondra au résultat d’un appel précédent à CAN.send().

Exemple d’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)

Important

Si le déclencheur CAN.IRQ_TX est défini, le gestionnaire doit appeler flags() de manière répétée jusqu’à ce qu’elle renvoie 0, comme indiqué dans cet exemple. Sinon, les interruptions CAN pourraient ne pas être correctement réactivées.