class CAN – barramento de comunicação da rede de área de controlador

CAN implementa suporte tanto para CAN clássico (bxCAN, utilizado no OpenMV Cam M4 e M7) como para CAN FD (FDCAN, utilizado no OpenMV Cam H7, H7 Plus e Pure Thermal). Ao nível físico, o barramento CAN é composto por duas linhas, RX e TX. Para ligar uma OpenMV Cam a um barramento CAN é necessário utilizar um transcetor 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 transcetor):

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 todas as funcionalidades opcionais ativadas (trama FD, comutação de taxa de bits, IDs de trama expandidos; 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 respetivos argumentos estão disponíveis tanto para controladores CAN clássico como FD, salvo indicação em contrário.

Construtores

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

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

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

Sinal

Pino de cabeçalho

Notas

RX

P3

TX

P2

O periférico CAN fornece apenas sinais de nível lógico; é necessário um transcetor CAN externo para conduzir 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 indicados:

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

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

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

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

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

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

  • baudrate se for fornecida uma taxa de baud diferente de 0, esta função tentará calcular automaticamente o tempo de bit nominal CAN (substituindo prescaler, bs1 e bs2) que satisfaz tanto a baudrate (dentro de .1%) como o sample_point desejado (para o 1% mais próximo). Para um controlo mais preciso do temporizador CAN, defina os parâmetros prescaler, bs1 e bs2 diretamente.

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

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

Os parâmetros restantes estão presentes apenas em placas com suporte CAN FD e configuram a funcionalidade opcional CAN FD Bit Rate Switch (BRS):

  • brs_prescaler é o valor pelo qual o relógio de entrada CAN FD é dividido para gerar o quantum de tempo de bit de dados. O prescaler pode ser um valor entre 1 e 32, inclusive.

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

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

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

  • brs_baudrate se for fornecida uma taxa de baud diferente de 0, esta função tentará calcular automaticamente o tempo de bit de dados CAN (substituindo brs_prescaler, brs_bs1 e brs_bs2) que satisfaz tanto a brs_baudrate (dentro de .1%) como o brs_sample_point desejado (para o 1% mais próximo). Para um controlo mais preciso do temporizador 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 ao tempo de bit nominal total, expressa como uma percentagem inteira do tempo de bit nominal. O brs_sample_point predefinido é 75%. Este parâmetro é ignorado a menos que brs_baudrate esteja definido.

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

Um único bit é composto pelo segmento de sincronização, que tem sempre 1 tq. Segue-se o segmento de bit 1 e depois o segmento de bit 2. O ponto de amostragem é após o segmento de bit 1 terminar. O ponto de transmissão é após o segmento de bit 2 terminar. A taxa de baud será 1/bittime, onde bittime é 1 + BS1 + BS2 multiplicado pelo quantum de tempo tq.

Por exemplo, na OpenMV Cam H7 (PCLK1 = 100 MHz), CAN a 250 kbps com um 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 taxa de baud é 1 / 4 µs = 250 kHz.

Consulte a secção bxCAN / FDCAN do manual de referência 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 repor a sua configuração.

Se o controlador entrar no estado bus-off, deixará de participar na atividade do barramento. Se o controlador não estiver configurado para reiniciar automaticamente (consulte init()), então este método pode ser utilizado para desencadear um reinício, e o controlador seguirá o protocolo CAN para sair do estado bus-off e entrar no estado de erro ativo.

state() int

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

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

  • CAN.ERROR_ACTIVE – o controlador está ligado e no estado de Erro Ativo (tanto TEC como REC são inferiores a 96);

  • CAN.ERROR_WARNING – o controlador está ligado e no estado de Aviso de Erro (pelo menos um de TEC ou REC é 96 ou superior);

  • CAN.ERROR_PASSIVE – o controlador está ligado e no estado de Erro Passivo (pelo menos um de TEC ou REC é 128 ou superior);

  • CAN.BUS_OFF – o controlador está ligado mas não participa na 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 TX e RX. Se list for fornecida, deverá ser um objeto lista com pelo menos 8 entradas, que serão preenchidas com as informações. Caso contrário, será criada e preenchida uma nova lista. Em ambos os casos, o valor de retorno do método é a lista preenchida.

Os valores na lista são:

  • Valor TEC

  • Valor REC

  • número de vezes que o controlador entrou no estado de Aviso de Erro (reiniciado para 0 após 65535)

  • número de vezes que o controlador entrou no estado de Erro Passivo (reiniciado para 0 após 65535)

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

  • número de mensagens TX pendentes

  • número de mensagens RX pendentes no fifo 0

  • número de mensagens RX pendentes no 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 CAN FD, a configurar.

  • mode é o modo de funcionamento do filtro, consulte as tabelas abaixo.

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

  • params é uma matriz de valores que define o filtro. O conteúdo da matriz depende do argumento mode.

Conteúdo da matriz 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 aceites.

CAN.LIST32

Dois IDs de 32 bits que serão aceites.

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 bit 0 = 1 e bit 1 = 0; o segundo par (4, 4) aceita todos os IDs com bit 2 = 1.

CAN.MASK32

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

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

mode

Conteúdo de params

CAN.RANGE

Dois IDs que formam um intervalo de IDs aceites.

CAN.DUAL

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

CAN.MASK

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

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

    mode

    len(rtr)

    Notas

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    Para CAN FD este argumento é ignorado.

  • extframe Se True, a trama terá um identificador expandido (29 bits), caso contrário é utilizado um identificador padrão (11 bits).

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

Limpa e desativa um banco de filtros:

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

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

any(fifo: int) bool

Devolve True se houver alguma mensagem à espera no FIFO, caso contrário False.

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

Recebe dados no barramento:

  • fifo é um inteiro que indica o FIFO onde receber

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

  • timeout é o tempo limite em milissegundos para aguardar pela receção.

Valor de retorno: Uma lista com cinco valores.

  • O id da mensagem.

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

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

  • O valor FMI (Filter Match Index).

  • Um array com os dados.

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

Se list não for None, deverá ser um objeto lista com pelo menos cinco elementos. O quinto elemento deverá ser um objeto memoryview criado a partir de um bytearray ou de um array do tipo “B” ou “b”, e este array deverá 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 in-place 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, proporcionando uma forma de receber dados sem utilizar a 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 enviar.

  • timeout é o tempo limite em milissegundos para aguardar pelo envio.

  • rtr é um booleano que especifica se a mensagem deve ser enviada como um pedido de transmissão remota. Se rtr for True, apenas o comprimento de data é utilizado para preencher o campo DLC da trama; os bytes reais em data não são utilizados.

  • extframe se True, a trama terá um identificador expandido (29 bits), caso contrário é utilizado um identificador padrão (11 bits).

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

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

Se o timeout for 0, a mensagem é colocada num buffer em um dos três buffers de hardware e o método retorna imediatamente. Se os três buffers estiverem em uso, é lançada uma exceção. 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, é lançada uma exceção.

Valor de retorno: None.

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

Regista uma função a ser chamada quando uma mensagem é aceite num FIFO vazio:

  • fifo é o FIFO de receção.

  • fun é a função a ser chamada quando o FIFO fica não vazio.

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 aceite num FIFO vazio.

1

O FIFO está cheio.

2

Uma mensagem foi perdida devido a um FIFO cheio.

Exemplo de utilização 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 barramento (argumento mode de init()):

NORMAL: int

O controlador participa normalmente no barramento – transmite as suas próprias tramas e confirma as tramas recebidas válidas.

LOOPBACK: int

Modo de loopback interno: o controlador é desconectado dos pinos e encaminha as tramas transmitidas diretamente de volta para o caminho de receção. Útil para autotestes sem transcetor.

SILENT: int

Modo de escuta apenas: o controlador recebe tramas mas nunca conduz o barramento (sem ACK, sem transmissões). Útil para monitorização do barramento.

SILENT_LOOPBACK: int

Combina SILENT e LOOPBACK: sem atividade nos pinos e sem confirmações, com loopback interno de TX para RX.

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

STOPPED: int

O controlador está completamente desligado e reposto.

ERROR_ACTIVE: int

O controlador está ligado e no estado de Erro Ativo (tanto TEC como REC são inferiores a 96).

ERROR_WARNING: int

O controlador está ligado e no estado de Aviso de Erro (pelo menos um de TEC ou REC é 96 ou superior).

ERROR_PASSIVE: int

O controlador está ligado e no estado de Erro Passivo (pelo menos um de TEC ou REC é 128 ou superior).

BUS_OFF: int

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

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

LIST16: int

A matriz params do filtro contém quatro IDs de 16 bits que serão aceites.

LIST32: int

A matriz params do filtro contém dois IDs de 32 bits que serão aceites.

MASK16: int

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

MASK32: int

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

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

RANGE: int

A matriz params do filtro contém dois IDs que formam um intervalo de IDs aceites.

DUAL: int

A matriz params do filtro contém dois IDs específicos a aceitar.

MASK: int

A matriz params do filtro contém um par (id, mask).