clase CAN – protocolo Controller Area Network¶
CAN es un protocolo serie de dos hilos utilizado para la entrega fiable de mensajes en tiempo real entre uno o varios nodos conectados a un bus común. CAN 2.0 se estandarizó en ISO-11898 y ahora también se conoce como CAN Classic.
También existe un protocolo más reciente y retrocompatible llamado CAN FD (CAN con velocidad de datos flexible). El controlador machine.CAN no admite actualmente las funciones de CAN FD; utilice pyb.CAN en STM32 si necesita CAN FD.
La compatibilidad con CAN requiere un controlador (a menudo un periférico interno del microcontrolador) y un transceptor externo para adaptar el nivel de las señales al bus CAN.
Disponible en las cámaras OpenMV con STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, además de las variantes de la marca Arduino que conectan un transceptor). Todavía no es compatible con la OpenMV Cam RT1062 (puerto mimxrt) ni con la OpenMV Cam AE3 (puerto alif).
La interfaz machine.CAN es una interfaz de mensajería CAN básica de bajo nivel que abstrae un controlador CAN como una cola de prioridad de salida para enviar mensajes, una cola de entrada para recibir mensajes y mecanismos para informar de errores.
Nota
Los módulos planificados can y aiocan de micropython-lib serán la forma recomendada de utilizar CAN con MicroPython.
Constructor¶
- class machine.CAN(id: int, *args, **kwargs)¶
Construye un objeto controlador CAN con el id dado:
ididentifica un objeto controlador CAN concreto; depende de la placa y del puerto.Todos los demás argumentos se pasan a
CAN.init(). Debe proporcionarse al menos un argumento (bitrate).
Las versiones futuras de esta clase también podrán aceptar aquí argumentos de palabra clave específicos del puerto que configuren el hardware. Actualmente no se ha implementado ninguno de estos argumentos.
Ejemplo¶
Construye e inicializa el controlador CAN 1 con una velocidad de 500 kbps:
from machine import CAN can = CAN(1, 500_000)
Métodos¶
- init(bitrate: int, mode: int = CAN.MODE_NORMAL, sample_point: int = 75, sjw: int = 1, tseg1: int | None = None, tseg2: int | None = None) None¶
Inicializa el bus CAN con los parámetros dados:
bitrate es la velocidad de bits deseada del bus en bits por segundo.
mode es uno de los valores mostrados en Modos, que indica el modo de operación deseado. El valor por defecto es la operación «normal» en el bus.
Los siguientes parámetros son opcionales y están relacionados con las temporizaciones de bit de CAN. En la mayoría de los casos puede dejar estos parámetros con sus valores por defecto:
sample_point es un porcentaje entero del tiempo de bit de datos. Especifica la posición del muestreo del bit respecto al tiempo de bit nominal completo. El controlador CAN calculará los parámetros en consecuencia. Este parámetro se ignora si se definen tseg1 y tseg2.
sjw es el ancho del salto de resincronización en unidades de cuantos de tiempo para bits nominales; puede tener un valor entre 1 y 4 inclusive para CAN clásico.
tseg1 define la ubicación del punto de muestreo en unidades de cuantos de tiempo para bits nominales; puede tener un valor entre 1 y 16 inclusive para CAN clásico. Es la suma de las fases
Prop_SegyPhase_Seg1tal como se definen en el estándar ISO-11898. Si se define este valor, también debe definirse tseg2 y se ignora sample_point.tseg2 define la ubicación del punto de transmisión en unidades de cuantos de tiempo para bits nominales; puede tener un valor entre 1 y 8 inclusive para CAN clásico. Corresponde a
Phase_Seg2en el estándar ISO-11898. Si se define este valor, también debe definirse tseg1.
Si se especifican estos argumentos, el controlador CAN se configura correctamente para la bitrate deseada y el número total especificado de cuantos de tiempo por bit. Los valores de tseg1 y tseg2 anulan el argumento sample_point si se proporcionan todos ellos.
Nota
El hardware de un controlador concreto puede tener restricciones adicionales sobre los valores válidos de estos parámetros, y lanzará un
ValueErrorsi un valor dado no es compatible.Nota
El hardware de un controlador concreto puede aceptar parámetros de palabra clave opcionales adicionales para funciones específicas del hardware, como el sobremuestreo.
- set_filters(filters: list | tuple | None) None¶
Establece los filtros de recepción en el controlador CAN. filters puede ser:
Nonepara aceptar todos los mensajes entrantes, o[]o()para deshabilitar la recepción de todos los mensajes, oUn iterable de uno o más elementos que definen los criterios de filtrado. Cada elemento debe ser una tupla o una lista con tres elementos:
identifieres un identificador CAN (int).bit_maskes una máscara de bits para los bits del campo identificador CAN (int).flagses un entero con cero o más de los bits definidos en Flags de mensaje. Especifica las propiedades que el mensaje entrante debe cumplir. No todos los controladores admiten el filtrado por todos los flags; se lanza unValueErrorsi se solicita un flag no compatible.
Los mensajes entrantes se aceptan si los bits enmascarados en
bit_maskcoinciden entre el identificador del mensaje y el valoridentifierdel filtro, y los flags definidos en el filtro coinciden con el mensaje entrante.Si el bit
CAN.FLAG_EXT_IDestá activado en los flags, el filtro coincide únicamente con los IDs CAN extendidos. Si el bitCAN.FLAG_EXT_IDno está activado, el filtro coincide únicamente con los IDs CAN estándar.Todos los filtros se combinan mediante OR en el controlador. Pasar una lista o tupla vacía como argumento de filtros significa que no se recibirá ningún mensaje.
Algunos controladores CAN requieren que cada filtro esté asociado a una única FIFO de recepción. En estos casos, los elementos de filtro del argumento se asignan por turnos (round-robin) a las FIFOs disponibles. Este controlador no distingue entre FIFOs en la IRQ de recepción.
Nota
Si el llamador pasa un iterable con más elementos que
CAN.FILTERS_MAX, se lanzará unValueError.Nota
Si el
identifiero labit_maskestá fuera de rango para el tipo de ID especificado, se lanzará unValueErrorcon el motivo «invalid id».Ejemplos¶
Recibir todos los mensajes entrantes:
can.set_filters(None)Recibir únicamente mensajes con los valores de ID estándar 0x301 y 0x700:
can.set_filters(((0x301, 0x7FF, 0), (0x700, 0x7FF, 0)))
Recibir únicamente mensajes con valores de ID estándar en el rango 0x300-0x3FF y el valor de ID extendido 0x50700:
can.set_filters(((0x300, 0x700, 0), (0x50700, 0x1FFF_FFFF, CAN.FLAG_EXT_ID)))
- FILTERS_MAX: int¶
Valor constante que indica el número máximo de filtros de recepción admitidos por este controlador de hardware.
Tenga en cuenta que algunos controladores pueden tener restricciones de hardware más complejas sobre el número de filtros en uso (por ejemplo, contando los filtros de ID estándar y extendido de forma independiente). En estos casos
CAN.set_filterspuede lanzar unValueErrorincluso cuando no se supera el límiteFILTERS_MAX.
- send(id: int, data: bytes, flags: int = 0) int | None¶
Copia un nuevo mensaje CAN en la cola de transmisión por hardware del controlador para enviarlo al bus. La cola de transmisión es una cola de prioridad ordenada según la prioridad del identificador CAN (los identificadores numéricos más bajos tienen mayor prioridad).
id es un valor entero de identificador CAN.
data es un objeto bytes (o similar) que contiene los datos del mensaje CAN, o que describe una solicitud de transmisión remota (Remote Transmission Request, ver más abajo).
flags es un entero con cero o más de los bits definidos en Flags de mensaje, que especifica las propiedades del mensaje CAN saliente (ID extendido, solicitud de transmisión remota, etc.).
Si el mensaje se pone correctamente en cola para su transmisión al bus, la función devuelve un entero en el rango de
0aCAN.TX_QUEUE_LEN(exclusivo). Este valor es el índice del búfer de transmisión donde el mensaje queda en cola para enviarse, y puede ser utilizado por la funciónCAN.cancel_sendy en los eventosCAN.IRQ_TX.Si la cola está llena, el envío fallará y se devuelve
None.El envío también puede fallar y devolver
Nonesi el valor id proporcionado tiene la misma prioridad que un mensaje existente en la cola de transmisión y el hardware del controlador CAN no puede garantizar que los mensajes con el mismo ID se envíen al bus en el mismo orden en que se añadieron a la cola. Para poner el mensaje en cola de todos modos, pase el flagCAN.FLAG_UNORDEREDen el argumento flags. Este flag indica que está bien enviar mensajes con el mismo ID CAN al bus en cualquier orden.Si el controlador está en el estado de error «Bus Off» o deshabilitado, llamar a esta función lanzará un
OSError.Nota
Esta implementación intencionadamente de bajo nivel está diseñada para que el llamador pueda establecer una cola de software de mensajes salientes.
Importante
La «cola de transmisión» CAN no es una cola FIFO, está ordenada por prioridad, y aunque puede contener hasta
CAN.TX_QUEUE_LENelementos, puede haber otras restricciones de hardware sobre los mensajes que se pueden poner en cola al mismo tiempo.Solicitudes de transmisión remota (Remote Transmission Requests)¶
Si el bit
CAN.FLAG_RTRestá activado en el argumento flags, el controlador enviará una solicitud de transmisión remota en lugar de un mensaje. En este caso se ignora el contenido del argumento data. El controlador enviará una solicitud en la que el campo de longitudDLCes igual a la longitud del argumento data.Ejemplos¶
Intenta enviar un mensaje con una carga útil de tres bytes
0a0b0ce ID estándar 0x200:can.send(0x200, b"\x0a\x0b\x0c", 0)Intenta enviar un mensaje con una carga útil vacía e ID extendido 0x180008. Indica que el controlador puede enviar mensajes con este ID en cualquier orden, por si ya hay otros mensajes en cola para enviarse con el mismo ID:
can.send(0x180008, b"", can.FLAG_EXT_ID | can.FLAG_UNORDERED)Intenta enviar una solicitud de transmisión remota con una longitud de 8 bytes e ID estándar 0x555:
can.send(0x555, b" " * 8, can.FLAG_RTR)
- recv(arg: list | None = None) list | None¶
Devuelve un mensaje CAN que ha sido recibido por el controlador, de acuerdo con los filtros establecidos por
CAN.set_filters().Esta función acepta un único argumento opcional; si se proporciona, debe ser una lista de al menos 4 elementos en la que el segundo elemento sea un objeto
memoryviewque haga referencia a unbytearrayu objeto similar con capacidad suficiente para contener cualquier mensaje CAN recibido (8 bytes para CAN Classic, 64 bytes para CAN FD). La lista proporcionada se devolverá como resultado correcto, lo que evita la asignación de memoria dentro de la función.Si el controlador CAN no ha recibido ningún mensaje, esta función devuelve
None.Nota
Debe llamarse a
CAN.set_filtersantes de que el controlador pueda recibir cualquier mensaje. Para recibir todos los mensajes, llame aset_filters(None).Si el controlador CAN ha recibido un mensaje, esta función devuelve una lista con 4 elementos:
El índice 0 es el ID CAN del mensaje recibido, como entero.
El índice 1 es un memoryview que proporciona acceso a los datos del mensaje recibido.
Si no se proporciona arg, este es un
memoryviewque contiene los bytes recibidos. Estememoryviewestá respaldado por unbytearrayrecién asignado lo suficientemente grande para contener cualquier mensaje CAN recibido. Esto permite reutilizar el resultado de forma segura como un futuro arg, para ahorrar asignaciones de memoria.Si se proporciona arg, el
memoryviewproporcionado se redimensionará para contener exactamente los bytes recibidos. El llamador es responsable de asegurarse de que el objeto de respaldo delmemoryviewpueda contener un mensaje CAN de cualquier longitud.
El índice 2 es un entero con cero o más de los bits definidos en Flags de mensaje. Indica metadatos sobre el mensaje recibido.
El índice 3 es un entero con cero o más de los bits definidos en Flags de error de recepción. Cualquier valor distinto de cero indica posibles problemas al recibir mensajes CAN. Estos flags se restablecen dentro del controlador cada vez que esta función retorna.
Solicitudes de transmisión remota (Remote Transmission Requests)¶
Si se recibe una solicitud de transmisión remota, el bit
CAN.FLAG_RTRse activará en el índice 2 y el memoryview del índice 1 contendrá solo ceros, con una longitud igual al campoDLCde la solicitud recibida.Ejemplo¶
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¶
Establece una función handler de interrupción que se llamará cuando haya ocurrido uno o más de los eventos señalados en trigger.
handler es una función que se llama cuando se dispara el evento de interrupción. El handler debe aceptar exactamente un argumento, que es la instancia de
CAN.trigger configura el evento o los eventos que pueden generar una interrupción. Los valores posibles son una máscara de uno o más de los siguientes:
El evento
CAN.IRQ_RXocurre después de que el controlador CAN haya recibido al menos un mensaje en su FIFO de RX (lo que significa queCAN.recv()retornará correctamente).El evento
CAN.IRQ_TXocurre después de que el controlador CAN haya enviado correctamente un mensaje al bus CAN o haya fallado al enviar un mensaje. Este disparador tiene requisitos adicionales para el handler; consulte Flags de IRQ para más detalles.El evento
CAN.IRQ_STATEocurre cuando el controlador CAN ha pasado a un estado de error más grave. Llame aCAN.state()para obtener el estado actualizado.
hard si es True, se utiliza una interrupción dura. Esto reduce el retardo entre el evento del controlador CAN y la llamada al handler. Los handlers de interrupción dura no pueden asignar memoria; consulte Escritura de gestores de interrupciones.
Devuelve un objeto irq. Si se llama sin argumentos, se devuelve un objeto irq configurado previamente.
Consulte Flags de IRQ para ver un ejemplo.
- cancel_send(index: int) bool¶
Solicita al controlador CAN que cancele el envío de un mensaje al bus.
El argumento index identifica un único búfer de transmisión. Debe ser un entero en el rango de
0aCAN.TX_QUEUE_LEN(exclusivo). Generalmente será un valor devuelto previamente porCAN.send().El resultado es
Truesi había un mensaje pendiente de transmisión en este búfer y la transmisión se canceló.El resultado es
Falseen caso contrario (o bien no había ningún mensaje pendiente de transmisión en este búfer, o bien la transmisión ya se realizó correctamente).El evento IRQ
CAN.IRQ_TXdebe usarse para determinar si un mensaje se envió definitivamente o no, pero tenga en cuenta que existen posibles condiciones de carrera si se cancela una transmisión y luego se usa el mismo búfer para enviar otro mensaje (especialmente si la IRQ del controlador CAN no es «dura»).
- state() int¶
Devuelve un valor entero que indica el estado actual del controlador. El valor será uno de los valores definidos en Estados.
Los estados de error de menor gravedad pueden borrarse automáticamente si el bus se recupera, pero el estado
CAN.STATE_BUS_OFFsolo puede recuperarse llamando aCAN.restart().
- get_counters(list: list | None = None, /) list¶
Devuelve los valores de los contadores de error del controlador. El resultado es una lista de ocho valores. Si se especifica el parámetro opcional list, el objeto lista proporcionado se actualiza y se devuelve como resultado, para evitar una asignación.
Los elementos de la lista son:
Valor TEC (Transmit Error Counter)
Valor REC (Receive Error Counter)
Número de veces que el controlador pasó al estado de Advertencia desde el estado Activo.
Número de veces que el controlador pasó al estado Error Passive desde el estado de Advertencia.
Número de veces que el controlador pasó al estado Bus Off desde el estado Error Passive.
Número total de mensajes de TX pendientes en la cola de hardware.
Número total de mensajes de RX pendientes en la cola de hardware.
Número de veces que se produjo un desbordamiento de RX.
Nota
Dependiendo del controlador, estos valores pueden desbordar y volver a 0 después de un cierto valor.
Nota
Si un controlador no admite un contador concreto, devolverá
Nonepara ese elemento de la lista.
- get_timings(list: list | None = None, /) list¶
Devuelve una lista de elementos que indican las temporizaciones actualmente configuradas en el controlador CAN. Esto puede usarse para verificar las temporizaciones con fines de depuración. El resultado es una lista de seis valores. Si se especifica el parámetro opcional list, el objeto lista proporcionado se actualiza y se devuelve como resultado, para evitar una asignación.
Los elementos de la lista son:
Velocidad de bits exacta utilizada por el controlador. Puede diferir del argumento bitrate pasado a
CAN.init()debido a la cuantización necesaria para cumplir las restricciones del hardware.Ancho del salto de resincronización (SJW) en unidades de cuantos de tiempo para bits nominales. Tiene el mismo significado que el parámetro sjw de
CAN.init().Ubicación del punto de muestreo en unidades de cuantos de tiempo para bits nominales. Tiene el mismo significado que el parámetro tseg1 de
CAN.init().Ubicación del punto de transmisión en unidades de cuantos de tiempo para bits nominales. Tiene el mismo significado que el parámetro tseg2 de
CAN.init().Información de temporización de CAN FD.
Nonepara los controladores que no admiten CAN FD, o si CAN FD no se ha inicializado. En caso contrario, una lista anidada de cuatro elementos correspondientes a los elementos anteriores pero aplicables a la función BRS de CAN FD.Información de temporización opcional específica del controlador. Dependiendo del controlador, será
Nonesi el controlador no informa de ninguna, o será una lista de longitud constante cuyos elementos son específicos de un controlador de hardware concreto.
Nota
Si no se ha llamado a
CAN.init(), esta función sigue devolviendo un resultado, pero este depende de las características internas del controlador y puede no ser preciso.
- restart() None¶
Hace que el controlador salga de
STATE_BUS_OFFsin borrar ningún otro estado interno. También borra algunos de los contadores de error (siempre el número de veces que se ha entrado en cada estado de error, y posiblemente TEC y REC según el controlador).Llamar a esta función también cancela cualquier mensaje pendiente de envío. No se entregan interrupciones
IRQ_TXpara estos mensajes.Tenga en cuenta que esta función puede hacer que el controlador salga o no del estado «Error Passive», dependiendo de si el hardware del controlador pone a cero TEC y REC o no.
- deinit() None¶
Desinicializa una instancia CAN previamente activa. Todos los mensajes pendientes (de transmisión y recepción) se descartan y el controlador deja de interactuar en el bus. Para volver a usar esta instancia, llame a
CAN.init().No se llama a ninguna interrupción
IRQ_TXniIRQ_RXen respuesta a la llamada a esta función.Consulte también
CAN.restart().
Constantes¶
- TX_QUEUE_LEN: int¶
Número máximo de mensajes CAN que se pueden poner en cola en la cola de mensajes de hardware de salida del controlador. Los «índices de búfer de transmisión» utilizados por
CAN.send(),CAN.cancel_send()y Flags de IRQ estarán en este rango.
Modos¶
Estos valores representan los modos de operación del controlador, tal como se pasan a
CAN.init(). No todos los controladores admiten todos los modos.Cambiar el modo de un controlador en funcionamiento requiere llamar a
CAN.deinit()y luego volver a llamar aCAN.init()con el nuevo modo.- MODE_NORMAL: int¶
El controlador está activo como un nodo estándar de la red CAN (confirmará los mensajes válidos y puede transmitir errores según su Estado actual).
- MODE_SLEEP: int¶
El controlador CAN está dormido en un modo de bajo consumo. Dependiendo del controlador, esto puede permitir despertar el controlador y pasar a
CAN.MODE_NORMALsi se recibe tráfico CAN.
- MODE_LOOPBACK: int¶
Un modo de prueba. El controlador CAN sigue conectado al bus externo, pero también recibirá sus propios mensajes transmitidos e ignorará cualquier error de ACK.
Estados¶
Estos valores son devueltos por
CAN.state()y reflejan el estado de error del controlador CAN:- STATE_ACTIVE: int¶
El controlador está activo y los contadores de error
TECyRECestán ambos por debajo del umbral de advertencia de 96. ConsulteCAN.get_counters().
- STATE_WARNING: int¶
El controlador está activo pero al menos uno de los contadores de error
TECyRECestá entre 96 y 127. ConsulteCAN.get_counters().
- STATE_PASSIVE: int¶
El controlador está en el estado «Error Passive», lo que significa que ya no transmite errores activos al bus, pero por lo demás es funcional. Se entra en este estado cuando al menos uno de los contadores de error
TECyRECes 128 o mayor, peroTECes menor que 255. ConsulteCAN.get_counters().
- STATE_BUS_OFF: int¶
El controlador está en el estado Bus-Off, lo que significa que el contador de error
TECes mayor que 255. El controlador CAN no interactuará con el bus en este estado, y necesita reiniciarse medianteCAN.restart()para continuar.
Flags de mensaje¶
Estos valores representan metadatos sobre un mensaje CAN. Las funciones
CAN.send(),CAN.recv()yCAN.set_filters()aceptan o devuelven un valor entero compuesto por cero o más de estos flags combinados con OR a nivel de bits.- FLAG_EXT_ID: int¶
Si está activado, indica que un identificador de mensaje es extendido (29 bits). Si no está activado, indica que un identificador de mensaje es estándar (11 bits).
- FLAG_UNORDERED: int¶
Si está activado en el argumento
flagsdeCAN.send(), indica que está bien que los mensajes con el mismo ID CAN se envíen en cualquier orden al bus.De lo contrario, intentar poner en cola varios mensajes con el mismo ID puede provocar que
CAN.send()falle si el hardware del controlador no puede garantizar el orden.Este flag nunca se establece en los mensajes recibidos y es ignorado por
CAN.set_filters().
Flags de error de recepción¶
El resultado de
CAN.recv()incluye un valor entero compuesto por cero o más de estos flags combinados con OR a nivel de bits. Si están activados, estos flags indican posibles problemas generales al recibir mensajes CAN.Valores de IRQ¶
- IRQ_RX: int¶
Pase al argumento
triggerdeirq()para disparar el handler cada vez que el controlador CAN haya recibido un mensaje completo en la FIFO de RX. Dentro del handler, lea el mensaje conrecv().
- IRQ_TX: int¶
Pase al argumento
triggerdeirq()para disparar el handler cada vez que el controlador CAN finalice un intento de transmisión (con éxito o con fallo). Dentro del handler, utilice los bits adicionales que se indican a continuación para recuperar qué buzón (mailbox) se completó y si falló; consulte Flags de IRQ.
- IRQ_STATE: int¶
Pase al argumento
triggerdeirq()para disparar el handler cada vez que el controlador realice una transición entre los valoresSTATE_*(active / warning / passive / bus-off). Utilicestate()dentro del handler para leer el nuevo estado.
- IRQ_TX_FAILED: int¶
Flag de estado que puede activarse en
irq().flags()cuando se dispara un eventoIRQ_TX. Indica que el intento de transmisión falló (normalmente porque se llamó acancel_send(), o porque el controlador pasó a un estado de error).
- IRQ_TX_IDX_SHIFT: int¶
Posición de bit del campo del índice del buzón de transmisión dentro del valor
irq().flags()durante un eventoIRQ_TX. El índice del buzón se extrae como(flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.
- IRQ_TX_IDX_MASK: int¶
Máscara de bits del campo del índice del buzón de transmisión dentro del valor
irq().flags()durante un eventoIRQ_TX. El índice extraído coincide con el entero devuelto por la llamada correspondiente asend()(un int en el rango de0aTX_QUEUE_LEN).
Flags de IRQ¶
Llamar a CAN.irq() registra un handler de interrupción con uno o más de los disparadores CAN.IRQ_RX, CAN.IRQ_TX y CAN.IRQ_STATE.
La función devuelve un objeto IRQ, y llamar a la función flags() sobre este objeto devuelve un entero que indica qué evento(s) disparador(es) provocó(aron) la interrupción. Un handler de IRQ de CAN debe llamar a la función flags() repetidamente hasta que devuelva 0.
Cuando la función flags() retorna con el bit CAN.IRQ_TX activado, el handler también puede comprobar los siguientes bits de flag en el resultado para obtener información adicional sobre el evento de TX:
El bit
CAN.IRQ_TX_FAILEDse activa si la transmisión falló. Normalmente esto solo ocurrirá si se llamó aCAN.cancel_send(), aunque también puede ocurrir si el controlador entra en un estado de error.CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFTes una región enmascarada por bits del valor de flags que contiene el índice del búfer de transmisión que generó el evento. Será un entero en el rango de0aCAN.TX_QUEUE_LEN(exclusivo), y coincidirá con el resultado de una llamada anterior aCAN.send().
Ejemplo de 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)
Importante
Si el disparador CAN.IRQ_TX está activado, el handler debe llamar a flags() repetidamente hasta que devuelva 0, como se muestra en este ejemplo. De lo contrario, las interrupciones CAN podrían no volver a habilitarse correctamente.