classe CAN – protocolo Controller Area Network¶
CAN é um protocolo série de dois fios utilizado para entrega fiável de mensagens em tempo real entre um ou mais nós ligados a um barramento comum. O CAN 2.0 foi normalizado na ISO-11898 e é também conhecido como CAN Classic.
Existe também um protocolo mais recente e retrocompatível denominado CAN FD (CAN com Taxa de Dados Flexível). O controlador machine.CAN não suporta atualmente as funcionalidades CAN FD; utilize pyb.CAN em STM32 se necessitar de CAN FD.
O suporte a CAN requer um controlador (frequentemente um periférico interno do microcontrolador) e um transcetor externo para adaptar os sinais ao nível do barramento CAN.
Disponível nas câmaras OpenMV STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, incluindo as variantes de marca Arduino que ligam um transcetor). Ainda não suportado na OpenMV Cam RT1062 (porta mimxrt) nem na OpenMV Cam AE3 (porta alif).
A interface machine.CAN é uma interface de mensagens CAN básica de baixo nível que abstrai um controlador CAN como uma fila de prioridade de saída para envio de mensagens, uma fila de entrada para receção de mensagens e mecanismos para reportar erros.
Nota
Os módulos can e aiocan da micropython-lib, previstos para o futuro, serão a forma recomendada de utilizar CAN com MicroPython.
Construtor¶
- class machine.CAN(id: int, *args, **kwargs)¶
Constrói um objeto controlador CAN com o id fornecido:
ididentifica um objeto controlador CAN específico; é específico da placa e da porta.Todos os outros argumentos são passados para
CAN.init(). Deve ser fornecido pelo menos um argumento (bitrate).
Versões futuras desta classe poderão também aceitar aqui argumentos de palavra-chave específicos da porta que configuram o hardware. Atualmente não estão implementados quaisquer argumentos de palavra-chave dessa natureza.
Exemplo¶
Constrói e inicializa o controlador CAN 1 com uma taxa de bits 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 o barramento CAN com os parâmetros fornecidos:
bitrate é a taxa de bits pretendida para o barramento, em bits por segundo.
mode é um dos valores indicados em Modos, que especifica o modo de operação pretendido. O valor predefinido é a operação «normal» no barramento.
Os próximos parâmetros são opcionais e dizem respeito aos timings de bits CAN. Na maioria dos casos pode deixar estes parâmetros com os valores predefinidos:
sample_point é uma percentagem inteira do tempo de bit de dados. Especifica a posição da amostragem do bit em relação ao tempo nominal total de bit. O controlador CAN calculará os parâmetros em conformidade. Este parâmetro é ignorado se tseg1 e tseg2 estiverem definidos.
sjw é a largura do salto de ressincronização em unidades de quanta de tempo para bits nominais; pode ter um valor entre 1 e 4 inclusive para CAN Classic.
tseg1 define a localização do ponto de amostragem em unidades de quanta de tempo para bits nominais; pode ter um valor entre 1 e 16 inclusive para CAN Classic. É a soma das fases
Prop_SegePhase_Seg1conforme definido na norma ISO-11898. Se este valor for definido, então tseg2 também deve ser definido e sample_point é ignorado.tseg2 define a localização do ponto de transmissão em unidades de quanta de tempo para bits nominais; pode ter um valor entre 1 e 8 inclusive para CAN Classic. Corresponde a
Phase_Seg2na norma ISO-11898. Se este valor for definido, então tseg1 também deve ser definido.
Se estes argumentos forem especificados, o controlador CAN é configurado corretamente para o bitrate pretendido e o número total especificado de quanta de tempo por bit. Os valores tseg1 e tseg2 substituem o argumento sample_point se todos eles forem fornecidos.
Nota
O hardware de cada controlador pode ter restrições adicionais sobre os valores válidos para estes parâmetros e irá lançar um
ValueErrorse um determinado valor não for suportado.Nota
Hardware de controlador específico pode aceitar parâmetros de palavra-chave opcionais adicionais para funcionalidades específicas do hardware, como a sobreamostragem.
- set_filters(filters: list | tuple | None) None¶
Define filtros de receção no controlador CAN. filters pode ser:
Nonepara aceitar todas as mensagens recebidas, ou[]ou()para desativar toda a receção de mensagens, ouUm iterável com um ou mais elementos que definem os critérios de filtragem. Cada elemento deve ser um tuplo ou lista com três elementos:
identifieré um identificador CAN (int).bit_maské uma máscara de bits para os bits no campo de identificador CAN (int).flagsé um inteiro com zero ou mais dos bits definidos em Flags de Mensagem ativados. Especifica as propriedades que a mensagem recebida precisa de corresponder. Nem todos os controladores suportam filtragem em todos os flags; é lançado umValueErrorse for solicitado um flag não suportado.
As mensagens recebidas são aceites se os bits mascarados em
bit_maskcorresponderem entre o identificador da mensagem e o valoridentifierdo filtro, e se os flags definidos no filtro corresponderem à mensagem recebida.Se o bit
CAN.FLAG_EXT_IDestiver definido nos flags, o filtro corresponde apenas a IDs CAN Estendidos. Se o bitCAN.FLAG_EXT_IDnão estiver definido, o filtro corresponde apenas a IDs CAN Standard.Todos os filtros são ORed conjuntamente no controlador. Passar uma lista ou tuplo vazio para o argumento filters significa que não serão recebidas mensagens.
Alguns controladores CAN requerem que cada filtro esteja associado a apenas um FIFO de receção. Nestes casos, os elementos do filtro no argumento são alocados em round-robin aos FIFOs disponíveis. Este controlador não distingue entre FIFOs no IRQ de receção.
Nota
Se o chamador passar um iterável com mais elementos do que
CAN.FILTERS_MAX, será lançado umValueError.Nota
Se o
identifierou abit_maskestiver fora do intervalo para o tipo de ID especificado, será lançado umValueErrorcom a razão «invalid id».Exemplos¶
Receber todas as mensagens recebidas:
can.set_filters(None)Receber apenas mensagens com valores de ID Standard 0x301 e 0x700:
can.set_filters(((0x301, 0x7FF, 0), (0x700, 0x7FF, 0)))
Receber apenas mensagens com valores de ID Standard no intervalo 0x300-0x3FF e o valor de ID Estendido 0x50700:
can.set_filters(((0x300, 0x700, 0), (0x50700, 0x1FFF_FFFF, CAN.FLAG_EXT_ID)))
- FILTERS_MAX: int¶
Valor constante que indica o número máximo de filtros de receção suportados por este controlador de hardware.
Note que alguns controladores podem ter restrições de hardware mais complexas sobre o número de filtros em uso (por exemplo, contando filtros de ID Standard e Estendido de forma independente). Nestes casos,
CAN.set_filterspode lançar umValueErrormesmo quando o limiteFILTERS_MAXnão é excedido.
- send(id: int, data: bytes, flags: int = 0) int | None¶
Copia uma nova mensagem CAN para a fila de transmissão de hardware do controlador para ser enviada no barramento. A fila de transmissão é uma fila de prioridade ordenada pela prioridade do identificador CAN (identificadores numéricos menores têm maior prioridade).
id é um valor inteiro de identificador CAN.
data é um objeto de bytes (ou similar) que contém os dados da mensagem CAN, ou que descreve um Remote Transmission Request (ver abaixo).
flags é um inteiro com zero ou mais dos bits definidos em Flags de Mensagem ativados, especificando propriedades da mensagem CAN de saída (ID Estendido, Remote Transmission Request, etc.)
Se a mensagem for colocada com sucesso na fila para transmissão no barramento, a função devolve um inteiro no intervalo
0aCAN.TX_QUEUE_LEN(exclusivo). Este valor é o índice do buffer de transmissão onde a mensagem está na fila para envio e pode ser utilizado pela funçãoCAN.cancel_sende em eventosCAN.IRQ_TX.Se a fila estiver cheia, o envio falha e é devolvido
None.O envio também pode falhar e devolver
Nonese o valor id fornecido tiver a mesma prioridade que uma mensagem existente na fila de transmissão e o hardware do controlador CAN não conseguir garantir que as mensagens com o mesmo ID sejam enviadas no barramento pela mesma ordem em que foram adicionadas à fila. Para colocar a mensagem na fila de qualquer forma, passe o flagCAN.FLAG_UNORDEREDno argumento flags. Este flag indica que é aceitável enviar mensagens com o mesmo ID CAN no barramento em qualquer ordem.Se o controlador estiver no estado de erro «Bus Off» ou desativado, chamar esta função irá lançar um
OSError.Nota
Esta implementação intencionalmente de baixo nível foi concebida para que o chamador possa estabelecer uma fila de software de mensagens de saída.
Importante
A «fila de transmissão» CAN não é uma fila FIFO, é ordenada por prioridade e, embora possa conter até
CAN.TX_QUEUE_LENelementos, podem existir outras restrições de hardware sobre as mensagens que podem ser colocadas em fila ao mesmo tempo.Remote Transmission Requests¶
Se o bit
CAN.FLAG_RTRestiver definido no argumento flags, o controlador enviará um Remote Transmission Request em vez de uma mensagem. Neste caso, o conteúdo do argumento data é ignorado. O controlador enviará um pedido em que o campo de comprimentoDLCé igual ao comprimento do argumento data.Exemplos¶
Tentativa de enviar uma mensagem com payload de três bytes
0a0b0ce ID Standard 0x200:can.send(0x200, b"\x0a\x0b\x0c", 0)Tentativa de enviar uma mensagem com payload vazio e ID Estendido 0x180008. Indica que o controlador pode enviar mensagens com este ID em qualquer ordem, caso outras mensagens já estejam na fila para envio com o mesmo ID:
can.send(0x180008, b"", can.FLAG_EXT_ID | can.FLAG_UNORDERED)Tentativa de enviar um Remote Transmission Request com comprimento de 8 bytes e ID Standard 0x555:
can.send(0x555, b" " * 8, can.FLAG_RTR)
- recv(arg: list | None = None) list | None¶
Devolve uma mensagem CAN que foi recebida pelo controlador, de acordo com os filtros definidos por
CAN.set_filters().Esta função aceita um único argumento opcional; se fornecido, deve ser uma lista com pelo menos 4 elementos onde o segundo elemento é um objeto
memoryviewque se refere a umbytearrayou objeto similar com capacidade suficiente para conter qualquer mensagem CAN recebida (8 bytes para CAN Classic, 64 bytes para CAN FD). A lista fornecida será devolvida como resultado bem-sucedido, evitando alocação de memória dentro da função.Se não tiverem sido recebidas mensagens pelo controlador CAN, esta função devolve
None.Nota
CAN.set_filtersdeve ser chamada antes de quaisquer mensagens poderem ser recebidas pelo controlador. Para receber todas as mensagens, chameset_filters(None).Se uma mensagem tiver sido recebida pelo controlador CAN, esta função devolve uma lista com 4 elementos:
O índice 0 é o ID CAN da mensagem recebida, como inteiro.
O índice 1 é um memoryview que fornece acesso aos dados da mensagem recebida.
Se arg não for fornecido, trata-se de um
memoryviewcom os bytes que foram recebidos. Estememoryviewé suportado por umbytearrayrecentemente alocado com tamanho suficiente para conter qualquer mensagem CAN recebida. Isto permite reutilizar o resultado com segurança como um futuro arg, para poupar alocações de memória.Se arg for fornecido, o
memoryviewfornecido será redimensionado para conter exatamente os bytes que foram recebidos. O chamador é responsável por garantir que o objeto de suporte para omemoryviewpode conter uma mensagem CAN de qualquer comprimento.
O índice 2 é um inteiro com zero ou mais dos bits definidos em Flags de Mensagem ativados. Indica metadados sobre a mensagem recebida.
O índice 3 é um inteiro com zero ou mais dos bits definidos em Flags de Erro de Receção ativados. Qualquer valor diferente de zero indica potenciais problemas ao receber mensagens CAN. Estes flags são reiniciados dentro do controlador cada vez que esta função é chamada.
Remote Transmission Requests¶
Se um Remote Transmission Request for recebido, o bit
CAN.FLAG_RTRserá definido no índice 2 e o memoryview no índice 1 conterá todos os zeros, com um comprimento igual ao campoDLCdo pedido recebido.Exemplo¶
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¶
Define uma função handler de interrupção a ser chamada quando um ou mais dos eventos sinalizados em trigger tiverem ocorrido.
handler é uma função a ser chamada quando o evento de interrupção é disparado. O handler deve aceitar exatamente um argumento que é a instância
CAN.trigger configura o(s) evento(s) que podem gerar uma interrupção. Os valores possíveis são uma máscara de um ou mais dos seguintes:
O evento
CAN.IRQ_RXocorre após o controlador CAN ter recebido pelo menos uma mensagem no seu FIFO RX (o que significa queCAN.recv()retornará com sucesso).O evento
CAN.IRQ_TXocorre após o controlador CAN ter enviado com sucesso uma mensagem no barramento CAN ou falhado no envio. Este gatilho tem requisitos adicionais para o handler; consulte Flags de IRQ para mais detalhes.O evento
CAN.IRQ_STATEocorre quando o controlador CAN transita para um estado de erro mais grave. ChameCAN.state()para obter o estado atualizado.
hard se for True, é utilizada uma interrupção hard. Isto reduz o atraso entre o evento do controlador CAN e a chamada do handler. Os handlers de interrupção hard não podem alocar memória; consulte Escrita de tratadores de interrupções.
Devolve um objeto irq. Se chamado sem argumentos, devolve um objeto irq configurado anteriormente.
Consulte Flags de IRQ para um exemplo.
- cancel_send(index: int) bool¶
Solicita ao controlador CAN que cancele o envio de uma mensagem no barramento.
O argumento index identifica um único buffer de transmissão. Deve ser um inteiro no intervalo
0aCAN.TX_QUEUE_LEN(exclusivo). Geralmente será um valor previamente devolvido porCAN.send().O resultado é
Truese uma mensagem estava pendente de transmissão neste buffer e a transmissão foi cancelada.O resultado é
Falsecaso contrário (ou não havia mensagem pendente de transmissão neste buffer, ou a transmissão já foi concluída com sucesso).O evento IRQ
CAN.IRQ_TXdeve ser utilizado para determinar se uma mensagem foi definitivamente enviada ou não, mas note que existem potenciais condições de corrida se uma transmissão for cancelada e o mesmo buffer for utilizado para enviar outra mensagem (especialmente se o IRQ do controlador CAN não for «hard»).
- state() int¶
Devolve um valor inteiro que indica o estado atual do controlador. O valor será um dos valores definidos em Estados.
Estados de erro de menor gravidade podem ser limpos automaticamente se o barramento se recuperar, mas o estado
CAN.STATE_BUS_OFFsó pode ser recuperado chamandoCAN.restart().
- get_counters(list: list | None = None, /) list¶
Devolve os valores dos contadores de erros do controlador. O resultado é uma lista de oito valores. Se o parâmetro opcional list for especificado, o objeto lista fornecido é atualizado e devolvido como resultado, para evitar uma alocação.
Os elementos da lista são:
Valor de TEC (Transmit Error Counter)
Valor de REC (Receive Error Counter)
Número de vezes que o controlador entrou no estado Warning a partir do estado Active.
Número de vezes que o controlador entrou no estado Error Passive a partir do estado Warning.
Número de vezes que o controlador entrou no estado Bus Off a partir do estado Error Passive.
Número total de mensagens TX pendentes na fila de hardware.
Número total de mensagens RX pendentes na fila de hardware.
Número de vezes que ocorreu um overrun de RX.
Nota
Dependendo do controlador, estes valores podem transbordar de volta para 0 após um determinado valor.
Nota
Se um controlador não suportar um determinado contador, devolverá
Nonepara esse elemento da lista.
- get_timings(list: list | None = None, /) list¶
Devolve uma lista de elementos que indica os timings atuais configurados no controlador CAN. Pode ser utilizado para verificar os timings para fins de depuração. O resultado é uma lista de seis valores. Se o parâmetro opcional list for especificado, o objeto lista fornecido é atualizado e devolvido como resultado, para evitar uma alocação.
Os elementos da lista são:
Taxa de bits exata utilizada pelo controlador. Pode diferir do argumento bitrate passado para
CAN.init()devido à quantização para satisfazer as restrições de hardware.Largura do salto de ressincronização (SJW) em unidades de quanta de tempo para bits nominais. Tem o mesmo significado que o parâmetro sjw de
CAN.init().Localização do ponto de amostragem em unidades de quanta de tempo para bits nominais. Tem o mesmo significado que o parâmetro tseg1 de
CAN.init().Localização do ponto de transmissão em unidades de quanta de tempo para bits nominais. Tem o mesmo significado que o parâmetro tseg2 de
CAN.init().Informação de timing CAN FD.
Nonepara controladores que não suportam CAN FD, ou se CAN FD não estiver inicializado. Caso contrário, uma lista aninhada de quatro elementos correspondentes aos elementos acima, mas aplicáveis à funcionalidade CAN FD BRS.Informação de timing opcional específica do controlador. Dependendo do controlador, será
Nonese o controlador não reportar nenhuma, ou será uma lista de comprimento constante cujos elementos são específicos de um determinado controlador de hardware.
Nota
Se
CAN.init()não tiver sido chamada, esta função devolve mesmo assim um resultado, mas o resultado depende dos internos do controlador e pode não ser preciso.
- restart() None¶
Faz com que o controlador saia do estado
STATE_BUS_OFFsem limpar qualquer outro estado interno. Também limpa alguns contadores de erros (sempre o número de vezes que cada estado de erro foi ativado, possivelmente TEC e REC dependendo do controlador.)Chamar esta função também cancela quaisquer mensagens a aguardar envio. Não são entregues interrupções
IRQ_TXpara estas mensagens.Note que esta função pode ou não fazer o controlador sair do estado «Error Passive», dependendo se o hardware do controlador zera ou não TEC e REC.
- deinit() None¶
Desinicializa uma instância CAN previamente ativa. Todas as mensagens pendentes (de transmissão e receção) são descartadas e o controlador deixa de interagir no barramento. Para usar esta instância novamente, chame
CAN.init().Não são chamadas interrupções
IRQ_TXouIRQ_RXem resposta à chamada desta função.Consulte também
CAN.restart().
Constantes¶
- TX_QUEUE_LEN: int¶
Número máximo de mensagens CAN que podem ser colocadas em fila na fila de mensagens de hardware de saída do controlador. Os «índices de buffer de transmissão» utilizados por
CAN.send(),CAN.cancel_send()e Flags de IRQ estarão neste intervalo.
Modos¶
Estes valores representam modos de operação do controlador, conforme passados para
CAN.init(). Nem todos os controladores podem suportar todos os modos.Alterar o modo de um controlador em funcionamento requer chamar
CAN.deinit()e depois chamarCAN.init()novamente com o novo modo.- MODE_NORMAL: int¶
O controlador está ativo como um nó de rede CAN padrão (irá reconhecer mensagens válidas e pode transmitir erros dependendo do seu Estado atual).
- MODE_SLEEP: int¶
O controlador CAN está em modo de baixo consumo. Dependendo do controlador, pode suportar o despertar do controlador e a transição para
CAN.MODE_NORMALse for recebido tráfego CAN.
- MODE_LOOPBACK: int¶
Um modo de teste. O controlador CAN ainda está ligado ao barramento externo, mas também receberá as suas próprias mensagens transmitidas e ignorará quaisquer erros ACK.
Estados¶
Estes valores são devolvidos por
CAN.state()e refletem o estado de erro do controlador CAN:- STATE_ACTIVE: int¶
O controlador está ativo e os contadores de erros
TECeRECestão ambos abaixo do limiar de aviso de 96. ConsulteCAN.get_counters().
- STATE_WARNING: int¶
O controlador está ativo mas pelo menos um dos contadores de erros
TECeRECestá entre 96 e 127. ConsulteCAN.get_counters().
- STATE_PASSIVE: int¶
O controlador está no estado «Error Passive», o que significa que já não transmite erros ativos para o barramento, mas é de outra forma funcional. Este estado é ativado quando pelo menos um dos contadores de erros
TECeRECé 128 ou superior, masTECé inferior a 255. ConsulteCAN.get_counters().
- STATE_BUS_OFF: int¶
O controlador está no estado Bus-Off, o que significa que o contador de erros
TECé superior a 255. O controlador CAN não irá interagir com o barramento neste estado e precisa de ser reiniciado viaCAN.restart()para continuar.
Flags de Mensagem¶
Estes valores representam metadados sobre uma mensagem CAN. As funções
CAN.send(),CAN.recv()eCAN.set_filters()aceitam ou devolvem um valor inteiro composto por zero ou mais destes flags combinados por OR bit a bit.- FLAG_EXT_ID: int¶
Se definido, indica que um identificador de mensagem é Estendido (29 bits). Se não definido, indica que um identificador de mensagem é Standard (11 bits).
- FLAG_UNORDERED: int¶
Se definido no argumento
flagsdeCAN.send(), indica que é aceitável enviar mensagens com o mesmo ID CAN em qualquer ordem no barramento.Caso contrário, tentar colocar em fila várias mensagens com o mesmo ID pode resultar em
CAN.send()a falhar se o hardware do controlador não conseguir impor a ordenação.Este flag nunca é definido em mensagens recebidas e é ignorado por
CAN.set_filters().
Flags de Erro de Receção¶
O resultado de
CAN.recv()inclui um valor inteiro composto por zero ou mais destes flags combinados por OR bit a bit. Se definidos, estes flags indicam potenciais problemas gerais na receção de mensagens CAN.Valores de IRQ¶
- IRQ_RX: int¶
Passe ao argumento
triggerdeirq()para disparar o handler cada vez que o controlador CAN recebe uma mensagem completa no FIFO RX. Dentro do handler, leia a mensagem comrecv().
- IRQ_TX: int¶
Passe ao argumento
triggerdeirq()para disparar o handler cada vez que o controlador CAN termina uma tentativa de transmissão (com sucesso ou falha). Dentro do handler, utilize os bits adicionais abaixo para recuperar qual mailbox foi concluído e se falhou – consulte Flags de IRQ.
- IRQ_STATE: int¶
Passe ao argumento
triggerdeirq()para disparar o handler cada vez que o controlador transita entre os valoresSTATE_*(ativo / aviso / passivo / bus-off). Utilizestate()dentro do handler para ler o novo estado.
- IRQ_TX_FAILED: int¶
Flag de estado que pode ser definido em
irq().flags()quando um eventoIRQ_TXé disparado. Indica que a tentativa de transmissão falhou (normalmente porquecancel_send()foi chamado, ou o controlador entrou num estado de erro).
- IRQ_TX_IDX_SHIFT: int¶
Posição de bit do campo de índice do mailbox de transmissão dentro do valor
irq().flags()durante um eventoIRQ_TX. O índice do mailbox é extraído como(flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.
- IRQ_TX_IDX_MASK: int¶
Máscara de bits do campo de índice do mailbox de transmissão dentro do valor
irq().flags()durante um eventoIRQ_TX. O índice extraído corresponde ao inteiro devolvido pela chamada correspondente desend()(um int no intervalo0aTX_QUEUE_LEN).
Flags de IRQ¶
Chamar CAN.irq() regista um handler de interrupção com um ou mais dos gatilhos CAN.IRQ_RX, CAN.IRQ_TX e CAN.IRQ_STATE.
A função devolve um objeto IRQ, e chamar a função flags() neste objeto devolve um inteiro que indica qual(ais) o(s) evento(s) de gatilho que dispararam a interrupção. Um handler de IRQ CAN deve chamar a função flags() repetidamente até devolver 0.
Quando a função flags() devolve com o bit CAN.IRQ_TX definido, o handler pode também verificar os seguintes bits de flag no resultado para obter informações adicionais sobre o evento TX:
O bit
CAN.IRQ_TX_FAILEDestá definido se a transmissão falhou. Normalmente isto só acontecerá seCAN.cancel_send()foi chamado, embora também possa acontecer se o controlador entrar num estado de erro.CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFTé uma região mascarada por bits do valor de flags que contém o índice do buffer de transmissão que gerou o evento. Será um inteiro no intervalo0aCAN.TX_QUEUE_LEN(exclusivo), e corresponderá ao resultado de uma chamada anterior aCAN.send().
Exemplo 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
Se o gatilho CAN.IRQ_TX estiver definido, o handler deve chamar flags() repetidamente até devolver 0, conforme mostrado neste exemplo. Caso contrário, as interrupções CAN podem não ser corretamente reativadas.