classe CAN – barramento de comunicação controller area network

A CAN implementa suporte tanto para o CAN clássico (bxCAN, usado nas OpenMV Cam M4 e M7) quanto para o CAN FD (FDCAN, usado nas OpenMV Cam H7, H7 Plus e Pure Thermal). No nível físico, o barramento CAN consiste em duas linhas, RX e TX. Para conectar uma OpenMV Cam a um barramento CAN você deve usar um transceiver CAN para converter os sinais lógicos CAN do MCU para os níveis de tensão corretos no barramento.

CAN clássico em modo de loopback (sem transceiver):

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 com todos os recursos opcionais habilitados (quadro FD, comutação de taxa de bits, IDs de quadro estendidos; fase de arbitragem de 500 kbit/s, fase de dados 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)

As seguintes funções do módulo CAN e seus argumentos estão disponíveis tanto para controladores CAN clássicos quanto FD, salvo indicação em contrário.

Construtores

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

Constrói um objeto CAN no bus fornecido (um índice inteiro de periférico, por exemplo 1 para CAN1, 2 para CAN2). Sem parâmetros adicionais, o objeto é criado mas não inicializado (ele mantém as configurações anteriores do barramento, se houver); se argumentos extras forem fornecidos, o barramento é inicializado. Consulte CAN.init() para os parâmetros disponíveis.

CAN(2) está conectado aos mesmos pinos de header em todas as OpenMV Cam que expõem pyb.CAN (M4 / M7 / H7 / H7 Plus / Pure Thermal):

Sinal

Pino do header

Notas

RX

P3

TX

P2

O periférico CAN fornece apenas sinais em nível lógico; um transceiver CAN externo é necessário para acionar um barramento CAN real.

pyb.CAN não está disponível na 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 o barramento CAN com os parâmetros fornecidos:

  • mode é um dos seguintes: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK

  • prescaler é o valor pelo qual o clock de entrada do CAN é dividido para gerar os quanta de tempo do bit nominal. O prescaler pode ser um valor entre 1 e 1024 inclusive para o CAN clássico, e entre 1 e 512 inclusive para o CAN FD.

  • sjw é a largura do salto de ressincronização em unidades de quanta de tempo para bits nominais; pode ser um valor entre 1 e 4 inclusive para o CAN clássico, e entre 1 e 128 inclusive para o CAN FD.

  • bs1 define a localização do ponto de amostragem em unidades de quanta de tempo para bits nominais; pode ser um valor entre 1 e 16 inclusive para o CAN clássico, e entre 2 e 256 inclusive para o CAN FD.

  • bs2 define a localização do ponto de transmissão em unidades de quanta de tempo para bits nominais; pode ser um valor entre 1 e 8 inclusive para o CAN clássico, e entre 2 e 128 inclusive para o CAN FD.

  • auto_restart define se o controlador tentará reiniciar automaticamente as comunicações após entrar no estado bus-off; se isso estiver desabilitado, então restart() pode ser usado para sair do estado bus-off

  • baudrate se for fornecida uma baudrate diferente de 0, esta função tentará calcular automaticamente o tempo de bit nominal do CAN (sobrescrevendo prescaler, bs1 e bs2) que satisfaça tanto a baudrate (com precisão de 0,1%) quanto o sample_point desejado (até o 1% mais próximo). Para um controle mais preciso sobre a temporização do CAN, defina os parâmetros prescaler, bs1 e bs2 diretamente.

  • sample_point especifica a posição da amostra de bit em relação a todo o tempo de bit nominal, expressa como uma porcentagem inteira do tempo de bit nominal. O sample_point padrão é 75%. Este parâmetro é ignorado a menos que baudrate esteja definido.

  • num_filter_banks para o CAN clássico, este é o número de bancos que serão atribuídos ao CAN(1), o restante dos 28 é atribuído ao CAN(2).

Os parâmetros restantes estão presentes apenas em placas com suporte a CAN FD, e configuram o recurso opcional de comutação de taxa de bits (BRS) do CAN FD:

  • brs_prescaler é o valor pelo qual o clock de entrada do CAN FD é dividido para gerar os quanta de tempo do bit de dados. O prescaler pode ser um valor entre 1 e 32 inclusive.

  • brs_sjw é a largura do salto de ressincronização em unidades de quanta de tempo para bits de dados; pode ser um valor entre 1 e 16 inclusive

  • brs_bs1 define a localização do ponto de amostragem em unidades de quanta de tempo para bits de dados; pode ser um valor entre 1 e 32 inclusive

  • brs_bs2 define a localização do ponto de transmissão em unidades de quanta de tempo para bits de dados; pode ser um valor entre 1 e 16 inclusive

  • brs_baudrate se for fornecida uma baudrate diferente de 0, esta função tentará calcular automaticamente o tempo de bit de dados do CAN (sobrescrevendo brs_prescaler, brs_bs1 e brs_bs2) que satisfaça tanto a brs_baudrate (com precisão de 0,1%) quanto o brs_sample_point desejado (até o 1% mais próximo). Para um controle mais preciso sobre a temporização do BRS, defina os parâmetros brs_prescaler, brs_bs1 e brs_bs2 diretamente.

  • brs_sample_point especifica a posição da amostra de bit em relação a todo o tempo de bit nominal, expressa como uma porcentagem inteira do tempo de bit nominal. O brs_sample_point padrão é 75%. Este parâmetro é ignorado a menos que brs_baudrate esteja definido.

O quantum de tempo tq é a unidade básica de tempo para o barramento CAN. tq é o valor do prescaler do CAN dividido por PCLK1 (a frequência do barramento de periférico interno 1); consulte pyb.freq() para determinar o PCLK1.

Um único bit é composto pelo segmento de sincronização, que é sempre 1 tq. Em seguida vem o segmento de bit 1, depois o segmento de bit 2. O ponto de amostragem é após o término do segmento de bit 1. O ponto de transmissão é após o término do segmento de bit 2. A baud rate será 1/bittime, onde bittime é 1 + BS1 + BS2 multiplicado pelo quantum de tempo tq.

Por exemplo, na OpenMV Cam H7 (PCLK1 = 100 MHz), o CAN de 250 kbps com ponto de amostragem de 75% pode ser configurado como prescaler=25, sjw=1, bs1=11, bs2=4: tq = 25 / 100 MHz = 250 ns, bittime = (1 + 11 + 4) × 250 ns = 4 µs, ponto de amostragem = (1 + 11) / 16 = 75%, e a baudrate é 1 / 4 µs = 250 kHz.

Consulte a seção bxCAN / FDCAN do manual de referência do STM32 para o MCU da OpenMV Cam para mais detalhes.

deinit() None

Desliga o barramento CAN.

restart() None

Força um reinício por software do controlador CAN sem redefinir sua configuração.

Se o controlador entrar no estado bus-off, então ele não participará mais da atividade do barramento. Se o controlador não estiver configurado para reiniciar automaticamente (consulte init()), então este método pode ser usado para acionar um reinício, e o controlador seguirá o protocolo CAN para sair do estado bus-off e entrar no estado error active.

state() int

Retorna o estado do controlador. O valor de retorno pode ser um dos seguintes:

  • CAN.STOPPED – o controlador está completamente desligado e redefinido;

  • CAN.ERROR_ACTIVE – o controlador está ligado e no estado Error Active (tanto TEC quanto REC são menores que 96);

  • CAN.ERROR_WARNING – o controlador está ligado e no estado Error Warning (pelo menos um entre TEC ou REC é 96 ou maior);

  • CAN.ERROR_PASSIVE – o controlador está ligado e no estado Error Passive (pelo menos um entre TEC ou REC é 128 ou maior);

  • CAN.BUS_OFF – o controlador está ligado mas não participa da atividade do barramento (TEC ultrapassou 255).

info(list: list | None = None) list

Obtém informações sobre os estados de erro do controlador e os buffers de TX e RX. Se list for fornecido, então deve ser um objeto lista com pelo menos 8 entradas, que serão preenchidas com as informações. Caso contrário, uma nova lista será criada e preenchida. Em ambos os casos, o valor de retorno do método é a lista preenchida.

Os valores na lista são:

  • valor do TEC

  • valor do REC

  • número de vezes que o controlador entrou no estado Error Warning (reinicia em 0 após 65535)

  • número de vezes que o controlador entrou no estado Error Passive (reinicia em 0 após 65535)

  • número de vezes que o controlador entrou no estado Bus Off (reinicia em 0 após 65535)

  • número de mensagens TX pendentes

  • número de mensagens RX pendentes na fifo 0

  • número de mensagens RX pendentes na fifo 1

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

Configura um banco de filtros:

  • bank é o banco de filtros do controlador CAN clássico, ou o índice de filtro do CAN FD, a configurar.

  • mode é o modo em que o filtro deve operar, consulte as tabelas abaixo.

  • fifo é em qual fifo (0 ou 1) uma mensagem deve ser armazenada, se for aceita por este filtro.

  • params é um array de valores que define o filtro. O conteúdo do array depende do argumento mode.

Conteúdo do array params para controladores CAN clássico (OpenMV Cam M4 / M7):

mode

Conteúdo de params

CAN.LIST16

Quatro IDs de 16 bits que serão aceitos.

CAN.LIST32

Dois IDs de 32 bits que serão aceitos.

CAN.MASK16

Dois pares id/máscara de 16 bits, por exemplo (1, 3, 4, 4). O primeiro par (1, 3) aceita todos os IDs com o bit 0 = 1 e o bit 1 = 0; o segundo par (4, 4) aceita todos os IDs com o bit 2 = 1.

CAN.MASK32

Um par id/máscara de 32 bits (de resto, igual ao CAN.MASK16).

Conteúdo do array params para controladores CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):

mode

Conteúdo de params

CAN.RANGE

Dois IDs formando uma faixa de IDs aceitos.

CAN.DUAL

Dois IDs que serão aceitos (por exemplo (1, 2)).

CAN.MASK

Um par (id, mask) (por exemplo (0x111, 0x7FF)).

  • rtr Para controladores CAN clássicos, este é um array de booleanos que indica se um filtro deve aceitar uma mensagem de requisição de transmissão remota. Se este argumento não for fornecido, o padrão é False para todas as entradas. O comprimento depende de mode:

    mode

    len(rtr)

    Notas

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    Para o CAN FD este argumento é ignorado.

  • extframe Se True, o quadro terá um identificador estendido (29 bits), caso contrário é usado um identificador padrão (11 bits).

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

Limpa e desabilita um banco de filtros:

  • bank é o banco de filtros do controlador CAN clássico, ou o índice de filtro do CAN FD, a limpar.

  • extframe Para controladores CAN FD, se True, limpa um filtro estendido (configurado com extframe=True), caso contrário limpa um identificador padrão (configurado com extframe=False).

any(fifo: int) bool

Retorna True se houver alguma mensagem aguardando na FIFO, caso contrário False.

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

Recebe dados no barramento:

  • fifo é um inteiro, que é a FIFO na qual receber

  • list é um objeto lista opcional a ser usado como valor de retorno

  • timeout é o timeout em milissegundos a aguardar pelo recebimento.

Valor de retorno: Uma lista contendo cinco valores.

  • O id da mensagem.

  • Um booleano que indica se o ID da mensagem é padrão ou estendido.

  • Um booleano que indica se a mensagem é uma mensagem RTR.

  • O valor FMI (Filter Match Index).

  • Um array contendo os dados.

Se list for None, então uma nova lista será alocada, assim como um novo objeto bytes para conter os dados (como o quinto elemento da lista).

Se list não for None, então deve ser um objeto lista com pelo menos cinco elementos. O quinto elemento deve ser um objeto memoryview criado a partir de um bytearray ou de um array do tipo ‘B’ ou ‘b’, e este array deve ter espaço suficiente para pelo menos 8 bytes. O objeto lista será então preenchido com os primeiros quatro valores de retorno acima, e o objeto memoryview será redimensionado inplace para o tamanho dos dados e preenchido com esses dados. Os mesmos objetos lista e memoryview podem ser reutilizados em chamadas subsequentes a este método, fornecendo uma maneira de receber dados sem usar o heap. Por exemplo:

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

Envia uma mensagem no barramento:

  • data são os dados a enviar (um inteiro a enviar, ou um objeto buffer).

  • id é o id da mensagem a ser enviada.

  • timeout é o timeout em milissegundos a aguardar pelo envio.

  • rtr é um booleano que especifica se a mensagem deve ser enviada como uma requisição de transmissão remota. Se rtr for True, então apenas o comprimento de data é usado para preencher o campo DLC do quadro; os bytes reais em data não são usados.

  • extframe se True, o quadro terá um identificador estendido (29 bits), caso contrário é usado um identificador padrão (11 bits).

  • fdf para controladores CAN FD, se definido como True, o quadro terá um formato de quadro FD, que suporta payloads de dados de até 64 bytes.

  • brs para controladores CAN FD, se definido como True, o modo de comutação de taxa de bits é habilitado, no qual a fase de dados é transmitida a uma taxa de bits diferente. Consulte CAN.init() para os parâmetros de configuração da temporização do bit de dados.

Se o timeout for 0, a mensagem é colocada em um buffer em um dos três buffers de hardware e o método retorna imediatamente. Se todos os três buffers estiverem em uso, uma exceção é lançada. Se o timeout não for 0, o método aguarda até que a mensagem seja transmitida. Se a mensagem não puder ser transmitida dentro do tempo especificado, uma exceção é lançada.

Valor de retorno: None.

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

Registra uma função a ser chamada quando uma mensagem é aceita em uma FIFO vazia:

  • fifo é a FIFO receptora.

  • fun é a função a ser chamada quando a FIFO se torna não vazia.

A função de callback recebe dois argumentos: o primeiro é o próprio objeto CAN; o segundo é um inteiro que indica o motivo do callback:

Motivo

Significado

0

Uma mensagem foi aceita em uma FIFO vazia.

1

A FIFO está cheia.

2

Uma mensagem foi perdida devido a uma FIFO cheia.

Exemplo de uso do 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 barramento (argumento mode de init()):

NORMAL: int

O controlador participa normalmente no barramento – transmite seus próprios quadros e confirma os quadros recebidos válidos.

LOOPBACK: int

Modo de loopback interno: o controlador é desconectado dos pinos e roteia os quadros transmitidos diretamente de volta para o caminho de recebimento. Útil para auto-testes sem um transceiver.

SILENT: int

Modo somente escuta: o controlador recebe quadros mas nunca aciona o barramento (sem ACK, sem transmissões). Útil para sniffing de barramento.

SILENT_LOOPBACK: int

Combina SILENT e LOOPBACK: nenhuma atividade nos pinos e nenhuma confirmação, com loopback interno de TX para RX.

Constantes de estado do controlador (retornadas por state()):

STOPPED: int

O controlador está completamente desligado e redefinido.

ERROR_ACTIVE: int

O controlador está ligado e no estado Error Active (tanto TEC quanto REC são menores que 96).

ERROR_WARNING: int

O controlador está ligado e no estado Error Warning (pelo menos um entre TEC ou REC é 96 ou maior).

ERROR_PASSIVE: int

O controlador está ligado e no estado Error Passive (pelo menos um entre TEC ou REC é 128 ou maior).

BUS_OFF: int

O controlador está ligado mas não participa da atividade do barramento (TEC ultrapassou 255).

Modos de filtro do CAN clássico (argumento mode de setfilter() na OpenMV Cam M4 / M7):

LIST16: int

O array params do filtro contém quatro IDs de 16 bits que serão aceitos.

LIST32: int

O array params do filtro contém dois IDs de 32 bits que serão aceitos.

MASK16: int

O array params do filtro contém dois pares (id, mask) de 16 bits.

MASK32: int

O array params do filtro contém um par (id, mask) de 32 bits.

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

RANGE: int

O array params do filtro contém dois IDs formando uma faixa de IDs aceitos.

DUAL: int

O array params do filtro contém dois IDs específicos a aceitar.

MASK: int

O array params do filtro contém um par (id, mask).