clase CAN – bus de comunicación de red de área de controladores (CAN)

CAN implementa compatibilidad tanto con CAN clásico (bxCAN, usado en la OpenMV Cam M4 y M7) como con CAN FD (FDCAN, usado en la OpenMV Cam H7, H7 Plus y Pure Thermal). A nivel físico, el bus CAN consta de dos líneas, RX y TX. Para conectar una OpenMV Cam a un bus CAN debes usar un transceptor CAN que convierta las señales lógicas CAN del MCU a los niveles de tensión correctos en el bus.

CAN clásico en modo de bucle de retorno (sin transceptor):

from pyb import CAN

can = CAN(1, CAN.LOOPBACK)

# Accept messages with id 123, 124, 125 or 126.
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))

can.send("message!", 123)   # send a message with id 123
can.recv(0)                 # receive a message on FIFO 0

CAN FD con todas las características opcionales habilitadas (trama FD, conmutación de velocidad de bits, IDs de trama extendidos; fase de arbitraje de 500 kbit/s, fase de datos de 1 Mbit/s):

from pyb import CAN

can = CAN(
    1,
    CAN.NORMAL,
    baudrate=500_000,
    brs_baudrate=1_000_000,
    sample_point=80,
)

# Accept any id in the range 0xFFF0 .. 0xFFFF.
can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF))

can.send(b"a" * 64, 0xFFFF, fdf=True, brs=True, extframe=True)
can.recv(0)

Las siguientes funciones del módulo CAN y sus argumentos están disponibles tanto para controladores CAN clásicos como FD, salvo que se indique lo contrario.

Constructores

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

Construye un objeto CAN en el bus indicado (un índice entero de periférico, p. ej. 1 para CAN1, 2 para CAN2). Sin parámetros adicionales, el objeto se crea pero no se inicializa (conserva la configuración previa del bus, si la hay); si se proporcionan argumentos adicionales, el bus se inicializa. Consulta CAN.init() para ver los parámetros disponibles.

CAN(2) está conectado a los mismos pines del conector en todas las OpenMV Cam que exponen pyb.CAN (M4 / M7 / H7 / H7 Plus / Pure Thermal):

Señal

Pin del conector

Notas

RX

P3

TX

P2

El periférico CAN proporciona únicamente señales a nivel lógico; se requiere un transceptor CAN externo para excitar un bus CAN real.

pyb.CAN no está disponible en la OpenMV Cam N6.

Métodos

init(mode: int, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, baudrate: int = 0, sample_point: int = 75, num_filter_banks: int = 14, brs_sjw: int = 1, brs_bs1: int = 8, brs_bs2: int = 3, brs_baudrate: int = 0, brs_sample_point: int = 75) None

Inicializa el bus CAN con los parámetros indicados:

  • mode es uno de: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK

  • prescaler es el valor por el que se divide el reloj de entrada de CAN para generar el cuanto de tiempo de bit nominal. El prescaler puede ser un valor entre 1 y 1024 inclusive para CAN clásico, y entre 1 y 512 inclusive para CAN FD.

  • sjw es el ancho de salto de resincronización en unidades de cuantos de tiempo para bits nominales; puede ser un valor entre 1 y 4 inclusive para CAN clásico, y entre 1 y 128 inclusive para CAN FD.

  • bs1 define la ubicación del punto de muestreo en unidades del cuanto de tiempo para bits nominales; puede ser un valor entre 1 y 16 inclusive para CAN clásico, y entre 2 y 256 inclusive para CAN FD.

  • bs2 define la ubicación del punto de transmisión en unidades del cuanto de tiempo para bits nominales; puede ser un valor entre 1 y 8 inclusive para CAN clásico, y entre 2 y 128 inclusive para CAN FD.

  • auto_restart establece si el controlador intentará reiniciar automáticamente las comunicaciones tras entrar en el estado bus-off; si está deshabilitado, se puede usar restart() para salir del estado bus-off

  • baudrate si se proporciona una velocidad en baudios distinta de 0, esta función intentará calcular automáticamente el tiempo de bit nominal de CAN (anulando prescaler, bs1 y bs2) que satisfaga tanto la baudrate (con un margen del .1%) como el sample_point deseado (al 1% más próximo). Para un control más preciso de la temporización de CAN, establece directamente los parámetros prescaler, bs1 y bs2.

  • sample_point especifica la posición de la muestra del bit respecto al tiempo de bit nominal completo, expresada como un porcentaje entero del tiempo de bit nominal. El sample_point predeterminado es 75%. Este parámetro se ignora salvo que se establezca baudrate.

  • num_filter_banks para CAN clásico, es el número de bancos que se asignarán a CAN(1); los 28 restantes se asignan a CAN(2).

Los parámetros restantes solo están presentes en placas con compatibilidad con CAN FD y configuran la característica opcional de conmutación de velocidad de bits (BRS) de CAN FD:

  • brs_prescaler es el valor por el que se divide el reloj de entrada de CAN FD para generar el cuanto de tiempo de bit de datos. El prescaler puede ser un valor entre 1 y 32 inclusive.

  • brs_sjw es el ancho de salto de resincronización en unidades de cuantos de tiempo para bits de datos; puede ser un valor entre 1 y 16 inclusive

  • brs_bs1 define la ubicación del punto de muestreo en unidades del cuanto de tiempo para bits de datos; puede ser un valor entre 1 y 32 inclusive

  • brs_bs2 define la ubicación del punto de transmisión en unidades del cuanto de tiempo para bits de datos; puede ser un valor entre 1 y 16 inclusive

  • brs_baudrate si se proporciona una velocidad en baudios distinta de 0, esta función intentará calcular automáticamente el tiempo de bit de datos de CAN (anulando brs_prescaler, brs_bs1 y brs_bs2) que satisfaga tanto la brs_baudrate (con un margen del .1%) como el brs_sample_point deseado (al 1% más próximo). Para un control más preciso de la temporización de BRS, establece directamente los parámetros brs_prescaler, brs_bs1 y brs_bs2.

  • brs_sample_point especifica la posición de la muestra del bit respecto al tiempo de bit nominal completo, expresada como un porcentaje entero del tiempo de bit nominal. El brs_sample_point predeterminado es 75%. Este parámetro se ignora salvo que se establezca brs_baudrate.

El cuanto de tiempo tq es la unidad básica de tiempo para el bus CAN. tq es el valor del prescaler de CAN dividido por PCLK1 (la frecuencia del bus de periféricos interno 1); consulta pyb.freq() para determinar PCLK1.

Un solo bit se compone del segmento de sincronización, que siempre es 1 tq. A continuación viene el segmento de bit 1, y luego el segmento de bit 2. El punto de muestreo se sitúa tras finalizar el segmento de bit 1. El punto de transmisión se sitúa tras finalizar el segmento de bit 2. La velocidad en baudios será 1/bittime, donde bittime es 1 + BS1 + BS2 multiplicado por el cuanto de tiempo tq.

Por ejemplo, en la OpenMV Cam H7 (PCLK1 = 100 MHz), un CAN de 250 kbps con un punto de muestreo del 75% puede configurarse como prescaler=25, sjw=1, bs1=11, bs2=4: tq = 25 / 100 MHz = 250 ns, bittime = (1 + 11 + 4) × 250 ns = 4 µs, punto de muestreo = (1 + 11) / 16 = 75%, y la velocidad en baudios es 1 / 4 µs = 250 kHz.

Consulta la sección bxCAN / FDCAN del manual de referencia STM32 del MCU de tu OpenMV Cam para más detalles.

deinit() None

Apaga el bus CAN.

restart() None

Fuerza un reinicio por software del controlador CAN sin restablecer su configuración.

Si el controlador entra en el estado bus-off, dejará de participar en la actividad del bus. Si el controlador no está configurado para reiniciarse automáticamente (consulta init()), este método se puede usar para activar un reinicio, y el controlador seguirá el protocolo CAN para salir del estado bus-off y pasar al estado error active.

state() int

Devuelve el estado del controlador. El valor de retorno puede ser uno de:

  • CAN.STOPPED – el controlador está completamente apagado y reiniciado;

  • CAN.ERROR_ACTIVE – el controlador está encendido y en el estado Error Active (tanto TEC como REC son menores que 96);

  • CAN.ERROR_WARNING – el controlador está encendido y en el estado Error Warning (al menos uno de TEC o REC es 96 o mayor);

  • CAN.ERROR_PASSIVE – el controlador está encendido y en el estado Error Passive (al menos uno de TEC o REC es 128 o mayor);

  • CAN.BUS_OFF – el controlador está encendido pero no participa en la actividad del bus (TEC se desbordó por encima de 255).

info(list: list | None = None) list

Obtiene información sobre los estados de error del controlador y sobre sus búferes TX y RX. Si se proporciona list, debe ser un objeto de lista con al menos 8 entradas, que se rellenarán con la información. En caso contrario, se creará una nueva lista y se rellenará. En ambos casos, el valor de retorno del método es la lista rellenada.

Los valores de la lista son:

  • valor TEC

  • valor REC

  • número de veces que el controlador entró en el estado Error Warning (vuelve a 0 tras 65535)

  • número de veces que el controlador entró en el estado Error Passive (vuelve a 0 tras 65535)

  • número de veces que el controlador entró en el estado Bus Off (vuelve a 0 tras 65535)

  • número de mensajes TX pendientes

  • número de mensajes RX pendientes en la fifo 0

  • número de mensajes RX pendientes en la fifo 1

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

Configura un banco de filtros:

  • bank es el banco de filtros del controlador CAN clásico, o el índice de filtro de CAN FD, que se va a configurar.

  • mode es el modo en el que debe operar el filtro; consulta las tablas a continuación.

  • fifo es la fifo (0 o 1) en la que se debe almacenar un mensaje, si lo acepta este filtro.

  • params es un array de valores que define el filtro. El contenido del array depende del argumento mode.

Contenido del array params para controladores CAN clásico (OpenMV Cam M4 / M7):

mode

Contenido de params

CAN.LIST16

Cuatro IDs de 16 bits que serán aceptados.

CAN.LIST32

Dos IDs de 32 bits que serán aceptados.

CAN.MASK16

Dos pares id/máscara de 16 bits, p. ej. (1, 3, 4, 4). El primer par (1, 3) acepta todos los IDs con el bit 0 = 1 y el bit 1 = 0; el segundo par (4, 4) acepta todos los IDs con el bit 2 = 1.

CAN.MASK32

Un par id/máscara de 32 bits (por lo demás, igual que CAN.MASK16).

Contenido del array params para controladores CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):

mode

Contenido de params

CAN.RANGE

Dos IDs que forman un rango de IDs aceptados.

CAN.DUAL

Dos IDs que serán aceptados (p. ej. (1, 2)).

CAN.MASK

Un par (id, mask) (p. ej. (0x111, 0x7FF)).

  • rtr Para controladores CAN clásicos, es un array de booleanos que indica si un filtro debe aceptar un mensaje de solicitud de transmisión remota. Si no se proporciona este argumento, su valor predeterminado es False para todas las entradas. La longitud depende de mode:

    mode

    len(rtr)

    Notas

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    Para CAN FD este argumento se ignora.

  • extframe Si es True, la trama tendrá un identificador extendido (29 bits); en caso contrario se usa un identificador estándar (11 bits).

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

Borra y deshabilita un banco de filtros:

  • bank es el banco de filtros del controlador CAN clásico, o el índice de filtro de CAN FD, que se va a borrar.

  • extframe Para controladores CAN FD, si es True, borra un filtro extendido (configurado con extframe=True); en caso contrario, borra un identificador estándar (configurado con extframe=False).

any(fifo: int) bool

Devuelve True si hay algún mensaje esperando en la FIFO; en caso contrario, False.

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

Recibe datos en el bus:

  • fifo es un entero, que es la FIFO en la que se recibe

  • list es un objeto de lista opcional que se usará como valor de retorno

  • timeout es el tiempo de espera en milisegundos para la recepción.

Valor de retorno: una lista que contiene cinco valores.

  • El id del mensaje.

  • Un booleano que indica si el ID del mensaje es estándar o extendido.

  • Un booleano que indica si el mensaje es un mensaje RTR.

  • El valor FMI (Filter Match Index).

  • Un array que contiene los datos.

Si list es None, se asignará una nueva lista, así como un nuevo objeto bytes para contener los datos (como quinto elemento de la lista).

Si list no es None, debe ser un objeto de lista con al menos cinco elementos. El quinto elemento debe ser un objeto memoryview creado a partir de un bytearray o de un array de tipo “B” o “b”, y este array debe tener espacio suficiente para al menos 8 bytes. El objeto de lista se rellenará entonces con los primeros cuatro valores de retorno anteriores, y el objeto memoryview se redimensionará in situ al tamaño de los datos y se rellenará con esos datos. Los mismos objetos de lista y memoryview se pueden reutilizar en llamadas posteriores a este método, lo que proporciona una forma de recibir datos sin usar el heap. Por ejemplo:

buf = bytearray(8)
lst = [0, 0, 0, 0, memoryview(buf)]
# No heap memory is allocated in the following call
can.recv(0, lst)
send(data: int | bytes | bytearray, id: int, *, timeout: int = 0, rtr: bool = False, extframe: bool = False, fdf: bool = False, brs: bool = False) None

Envía un mensaje en el bus:

  • data son los datos a enviar (un entero a enviar, o un objeto búfer).

  • id es el id del mensaje que se va a enviar.

  • timeout es el tiempo de espera en milisegundos para el envío.

  • rtr es un booleano que especifica si el mensaje se debe enviar como una solicitud de transmisión remota. Si rtr es True, solo se usa la longitud de data para rellenar la ranura DLC de la trama; los bytes reales de data no se utilizan.

  • extframe si es True, la trama tendrá un identificador extendido (29 bits); en caso contrario se usa un identificador estándar (11 bits).

  • fdf para controladores CAN FD, si se establece en True, la trama tendrá un formato de trama FD, que admite cargas útiles de datos de hasta 64 bytes.

  • brs para controladores CAN FD, si se establece en True, se habilita el modo de conmutación de velocidad de bits, en el que la fase de datos se transmite a una velocidad de bits diferente. Consulta CAN.init() para los parámetros de configuración de la temporización de bits de datos.

Si timeout es 0, el mensaje se coloca en uno de los tres búferes de hardware y el método retorna de inmediato. Si los tres búferes están en uso, se lanza una excepción. Si timeout no es 0, el método espera hasta que el mensaje se transmita. Si el mensaje no se puede transmitir dentro del tiempo especificado, se lanza una excepción.

Valor de retorno: None.

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

Registra una función que se llamará cuando se acepte un mensaje en una FIFO vacía:

  • fifo es la FIFO de recepción.

  • fun es la función que se llamará cuando la FIFO deje de estar vacía.

La función de retorno (callback) toma dos argumentos: el primero es el propio objeto CAN; el segundo es un entero que indica el motivo de la llamada:

Motivo

Significado

0

Se ha aceptado un mensaje en una FIFO vacía.

1

La FIFO está llena.

2

Se ha perdido un mensaje debido a una FIFO llena.

Ejemplo de uso de rxcallback:

def cb0(bus, reason):
  print('cb0')
  if reason == 0:
      print('pending')
  if reason == 1:
      print('full')
  if reason == 2:
      print('overflow')

can = CAN(1, CAN.LOOPBACK)
can.rxcallback(0, cb0)

Constantes

Constantes de modo de bus (argumento mode de init()):

NORMAL: int

El controlador participa con normalidad en el bus – transmite sus propias tramas y confirma las tramas válidas recibidas.

LOOPBACK: int

Modo de bucle de retorno interno: el controlador se desconecta de los pines y enruta las tramas transmitidas directamente de vuelta a la ruta de recepción. Útil para autodiagnósticos sin un transceptor.

SILENT: int

Modo de solo escucha: el controlador recibe tramas pero nunca excita el bus (sin ACK, sin transmisiones). Útil para la captura de tráfico del bus.

SILENT_LOOPBACK: int

Combina SILENT y LOOPBACK: sin actividad en los pines y sin confirmaciones, con bucle de retorno interno de TX hacia RX.

Constantes de estado del controlador (devueltas por state()):

STOPPED: int

El controlador está completamente apagado y reiniciado.

ERROR_ACTIVE: int

El controlador está encendido y en el estado Error Active (tanto TEC como REC son menores que 96).

ERROR_WARNING: int

El controlador está encendido y en el estado Error Warning (al menos uno de TEC o REC es 96 o mayor).

ERROR_PASSIVE: int

El controlador está encendido y en el estado Error Passive (al menos uno de TEC o REC es 128 o mayor).

BUS_OFF: int

El controlador está encendido pero no participa en la actividad del bus (TEC se desbordó por encima de 255).

Modos de filtro de CAN clásico (argumento mode de setfilter() en la OpenMV Cam M4 / M7):

LIST16: int

El array params del filtro contiene cuatro IDs de 16 bits que serán aceptados.

LIST32: int

El array params del filtro contiene dos IDs de 32 bits que serán aceptados.

MASK16: int

El array params del filtro contiene dos pares (id, mask) de 16 bits.

MASK32: int

El array params del filtro contiene un par (id, mask) de 32 bits.

Modos de filtro de CAN FD (argumento mode de setfilter() en la OpenMV Cam H7 / H7 Plus / Pure Thermal):

RANGE: int

El array params del filtro contiene dos IDs que forman un rango de IDs aceptados.

DUAL: int

El array params del filtro contiene dos IDs específicos a aceptar.

MASK: int

El array params del filtro contiene un par (id, mask).