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
busfornecido (um índice inteiro de periférico, por exemplo1paraCAN1,2paraCAN2). 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. ConsulteCAN.init()para os parâmetros disponíveis.CAN(2)está conectado aos mesmos pinos de header em todas as OpenMV Cam que expõempyb.CAN(M4 / M7 / H7 / H7 Plus / Pure Thermal):Sinal
Pino do header
Notas
RXP3TXP2O periférico CAN fornece apenas sinais em nível lógico; um transceiver CAN externo é necessário para acionar um barramento CAN real.
pyb.CANnã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-offbaudrate 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.
- 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.LIST16Quatro IDs de 16 bits que serão aceitos.
CAN.LIST32Dois IDs de 32 bits que serão aceitos.
CAN.MASK16Dois 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.MASK32Um 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.RANGEDois IDs formando uma faixa de IDs aceitos.
CAN.DUALDois IDs que serão aceitos (por exemplo
(1, 2)).CAN.MASKUm 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 é
Falsepara todas as entradas. O comprimento depende de mode:mode
len(rtr)Notas
CAN.LIST164
CAN.LIST322
CAN.MASK162
CAN.MASK321
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
Truese houver alguma mensagem aguardando na FIFO, caso contrárioFalse.
- 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
0Uma mensagem foi aceita em uma FIFO vazia.
1A FIFO está cheia.
2Uma 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
modedeinit()):- 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
SILENTeLOOPBACK: nenhuma atividade nos pinos e nenhuma confirmação, com loopback interno de TX para RX.
Constantes de estado do controlador (retornadas por
state()):- 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
modedesetfilter()na OpenMV Cam M4 / M7):Modos de filtro do CAN FD (argumento
modedesetfilter()na OpenMV Cam H7 / H7 Plus / Pure Thermal):