class CAN – bus di comunicazione controller area network¶
CAN implementa il supporto sia per il CAN classico (bxCAN, usato sulle OpenMV Cam M4 e M7) sia per il CAN FD (FDCAN, usato sulle OpenMV Cam H7, H7 Plus e Pure Thermal). A livello fisico il bus CAN è costituito da due linee, RX e TX. Per collegare una OpenMV Cam a un bus CAN è necessario usare un transceiver CAN per convertire i segnali logici CAN dell’MCU ai corretti livelli di tensione sul bus.
CAN classico in modalità loopback (senza 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 con tutte le funzionalità opzionali abilitate (frame FD, commutazione del bit-rate, ID di frame estesi; fase di arbitraggio a 500 kbit/s, fase dati a 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)
Le seguenti funzioni del modulo CAN e i relativi argomenti sono disponibili sia per i controller CAN classici sia per quelli FD, salvo diversa indicazione.
Costruttori¶
- class pyb.CAN(bus: int | str, *args, **kwargs)¶
Costruisce un oggetto CAN sul
busindicato (un indice intero della periferica, ad es.1perCAN1,2perCAN2). Senza parametri aggiuntivi l’oggetto viene creato ma non inizializzato (mantiene le precedenti impostazioni del bus, se presenti); se vengono forniti argomenti aggiuntivi il bus viene inizializzato. VedereCAN.init()per i parametri disponibili.CAN(2)è collegato agli stessi pin del header su ogni OpenMV Cam che esponepyb.CAN(M4 / M7 / H7 / H7 Plus / Pure Thermal):Segnale
Pin del header
Note
RXP3TXP2La periferica CAN fornisce solo segnali a livello logico; è necessario un transceiver CAN esterno per pilotare un bus CAN reale.
pyb.CANnon è disponibile sulla OpenMV Cam N6.Metodi¶
- 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¶
Inizializza il bus CAN con i parametri indicati:
mode è uno tra: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
prescaler è il valore per cui viene divisa la frequenza di clock di ingresso del CAN per generare i quanti di tempo del bit nominale. Il prescaler può assumere un valore compreso tra 1 e 1024 inclusi per il CAN classico, e tra 1 e 512 inclusi per il CAN FD.
sjw è la larghezza del salto di risincronizzazione in unità di quanti di tempo per i bit nominali; può assumere un valore compreso tra 1 e 4 inclusi per il CAN classico, e tra 1 e 128 inclusi per il CAN FD.
bs1 definisce la posizione del punto di campionamento in unità di quanti di tempo per i bit nominali; può assumere un valore compreso tra 1 e 16 inclusi per il CAN classico, e tra 2 e 256 inclusi per il CAN FD.
bs2 definisce la posizione del punto di trasmissione in unità di quanti di tempo per i bit nominali; può assumere un valore compreso tra 1 e 8 inclusi per il CAN classico, e tra 2 e 128 inclusi per il CAN FD.
auto_restart imposta se il controller tenterà automaticamente di riavviare le comunicazioni dopo essere entrato nello stato bus-off; se questo è disabilitato, allora
restart()può essere usato per uscire dallo stato bus-offbaudrate se viene fornito un baudrate diverso da 0, questa funzione tenterà di calcolare automaticamente il tempo di bit nominale del CAN (sovrascrivendo prescaler, bs1 e bs2) che soddisfi sia il baudrate (entro lo .1%) sia il sample_point desiderato (al più vicino 1%). Per un controllo più preciso della temporizzazione CAN, impostare direttamente i parametri prescaler, bs1 e bs2.
sample_point specifica la posizione del campionamento del bit rispetto all’intero tempo di bit nominale, espressa come percentuale intera del tempo di bit nominale. Il valore predefinito di sample_point è 75%. Questo parametro viene ignorato a meno che baudrate non sia impostato.
num_filter_banks per il CAN classico, è il numero di banchi che verranno assegnati a CAN(1), i rimanenti dei 28 vengono assegnati a CAN(2).
I parametri rimanenti sono presenti solo sulle schede con supporto CAN FD, e configurano la funzionalità opzionale CAN FD Bit Rate Switch (BRS):
brs_prescaler è il valore per cui viene divisa la frequenza di clock di ingresso del CAN FD per generare i quanti di tempo del bit dati. Il prescaler può assumere un valore compreso tra 1 e 32 inclusi.
brs_sjw è la larghezza del salto di risincronizzazione in unità di quanti di tempo per i bit dati; può assumere un valore compreso tra 1 e 16 inclusi
brs_bs1 definisce la posizione del punto di campionamento in unità di quanti di tempo per i bit dati; può assumere un valore compreso tra 1 e 32 inclusi
brs_bs2 definisce la posizione del punto di trasmissione in unità di quanti di tempo per i bit dati; può assumere un valore compreso tra 1 e 16 inclusi
brs_baudrate se viene fornito un baudrate diverso da 0, questa funzione tenterà di calcolare automaticamente il tempo di bit dati del CAN (sovrascrivendo brs_prescaler, brs_bs1 e brs_bs2) che soddisfi sia il brs_baudrate (entro lo .1%) sia il brs_sample_point desiderato (al più vicino 1%). Per un controllo più preciso della temporizzazione BRS, impostare direttamente i parametri brs_prescaler, brs_bs1 e brs_bs2.
brs_sample_point specifica la posizione del campionamento del bit rispetto all’intero tempo di bit nominale, espressa come percentuale intera del tempo di bit nominale. Il valore predefinito di brs_sample_point è 75%. Questo parametro viene ignorato a meno che brs_baudrate non sia impostato.
Il quanto di tempo tq è l’unità di tempo di base per il bus CAN. tq è il valore del prescaler CAN diviso per PCLK1 (la frequenza del bus periferico interno 1); vedere
pyb.freq()per determinare PCLK1.Un singolo bit è composto dal segmento di sincronizzazione, che è sempre 1 tq. Seguono poi il segmento di bit 1, quindi il segmento di bit 2. Il punto di campionamento è dopo la fine del segmento di bit 1. Il punto di trasmissione è dopo la fine del segmento di bit 2. Il baud rate sarà 1/bittime, dove il bittime è 1 + BS1 + BS2 moltiplicato per il quanto di tempo tq.
Ad esempio, sulla OpenMV Cam H7 (PCLK1 = 100 MHz), il CAN a 250 kbps con un punto di campionamento al 75% può essere configurato come
prescaler=25, sjw=1, bs1=11, bs2=4:tq = 25 / 100 MHz = 250 ns,bittime = (1 + 11 + 4) × 250 ns = 4 µs, punto di campionamento =(1 + 11) / 16 = 75%, e il baudrate è1 / 4 µs = 250 kHz.Vedere la sezione bxCAN / FDCAN del manuale di riferimento STM32 per l’MCU della OpenMV Cam per maggiori dettagli.
- restart() None¶
Forza un riavvio software del controller CAN senza azzerarne la configurazione.
Se il controller entra nello stato bus-off non parteciperà più all’attività del bus. Se il controller non è configurato per riavviarsi automaticamente (vedere
init()) allora questo metodo può essere usato per attivare un riavvio, e il controller seguirà il protocollo CAN per uscire dallo stato bus-off ed entrare nello stato di errore attivo.
- state() int¶
Restituisce lo stato del controller. Il valore restituito può essere uno tra:
CAN.STOPPED– il controller è completamente spento e azzerato;CAN.ERROR_ACTIVE– il controller è acceso e nello stato Error Active (sia TEC che REC sono inferiori a 96);CAN.ERROR_WARNING– il controller è acceso e nello stato Error Warning (almeno uno tra TEC o REC è pari o superiore a 96);CAN.ERROR_PASSIVE– il controller è acceso e nello stato Error Passive (almeno uno tra TEC o REC è pari o superiore a 128);CAN.BUS_OFF– il controller è acceso ma non partecipa all’attività del bus (TEC è andato in overflow oltre 255).
- info(list: list | None = None) list¶
Ottiene informazioni sugli stati di errore del controller e sui buffer TX e RX. Se viene fornito list allora dovrebbe essere un oggetto list con almeno 8 voci, che verranno riempite con le informazioni. Altrimenti verrà creata e riempita una nuova lista. In entrambi i casi il valore restituito dal metodo è la lista popolata.
I valori nella lista sono:
valore TEC
valore REC
numero di volte che il controller è entrato nello stato Error Warning (riparte da 0 dopo 65535)
numero di volte che il controller è entrato nello stato Error Passive (riparte da 0 dopo 65535)
numero di volte che il controller è entrato nello stato Bus Off (riparte da 0 dopo 65535)
numero di messaggi TX in attesa
numero di messaggi RX in attesa sulla fifo 0
numero di messaggi RX in attesa sulla fifo 1
- setfilter(bank: int, mode: int, fifo: int, params: Tuple[int, ...], *, rtr: Tuple[bool, ...] | None = None, extframe: bool = False) None¶
Configura un banco di filtri:
bank è il banco di filtri del controller CAN classico, o l’indice di filtro CAN FD, da configurare.
mode è la modalità in cui deve operare il filtro, vedere le tabelle sottostanti.
fifo è la fifo (0 o 1) in cui un messaggio deve essere memorizzato, se viene accettato da questo filtro.
params è un array di valori che definisce il filtro. Il contenuto dell’array dipende dall’argomento mode.
Contenuto dell’array params per i controller CAN classico (OpenMV Cam M4 / M7):
mode
Contenuto di params
CAN.LIST16Quattro ID a 16 bit che verranno accettati.
CAN.LIST32Due ID a 32 bit che verranno accettati.
CAN.MASK16Due coppie id/maschera a 16 bit, ad es.
(1, 3, 4, 4). La prima coppia (1, 3) accetta tutti gli ID con bit 0 = 1 e bit 1 = 0; la seconda coppia (4, 4) accetta tutti gli ID con bit 2 = 1.CAN.MASK32Una coppia id/maschera a 32 bit (per il resto uguale a
CAN.MASK16).Contenuto dell’array params per i controller CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):
mode
Contenuto di params
CAN.RANGEDue ID che formano un intervallo di ID accettati.
CAN.DUALDue ID che verranno accettati (ad es.
(1, 2)).CAN.MASKUna coppia
(id, mask)(ad es.(0x111, 0x7FF)).rtr Per i controller CAN classici, è un array di valori booleani che indica se un filtro deve accettare un messaggio di richiesta di trasmissione remota. Se questo argomento non viene fornito, il valore predefinito è
Falseper tutte le voci. La lunghezza dipende da mode:mode
len(rtr)Note
CAN.LIST164
CAN.LIST322
CAN.MASK162
CAN.MASK321
Per il CAN FD questo argomento viene ignorato.
extframe Se True il frame avrà un identificatore esteso (29 bit), altrimenti viene usato un identificatore standard (11 bit).
- clearfilter(bank: int, extframe: bool = False) None¶
Cancella e disabilita un banco di filtri:
bank è il banco di filtri del controller CAN classico, o l’indice di filtro CAN FD, da cancellare.
extframe Per i controller CAN FD, se True, cancella un filtro esteso (configurato con extframe=True), altrimenti cancella un identificatore standard (configurato con extframe=False).
- recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list¶
Riceve dati sul bus:
fifo è un intero, ovvero la FIFO su cui ricevere
list è un oggetto list opzionale da usare come valore di ritorno
timeout è il timeout in millisecondi per attendere la ricezione.
Valore di ritorno: una lista contenente cinque valori.
L’id del messaggio.
Un booleano che indica se l’ID del messaggio è standard o esteso.
Un booleano che indica se il messaggio è un messaggio RTR.
Il valore FMI (Filter Match Index).
Un array contenente i dati.
Se list è
Noneallora verrà allocata una nuova lista, oltre a un nuovo oggetto bytes per contenere i dati (come quinto elemento della lista).Se list non è
Noneallora dovrebbe essere un oggetto list con almeno cinque elementi. Il quinto elemento dovrebbe essere un oggetto memoryview creato da un bytearray o da un array di tipo “B” o “b”, e questo array deve avere spazio sufficiente per almeno 8 byte. L’oggetto list verrà quindi popolato con i primi quattro valori di ritorno sopra indicati, e l’oggetto memoryview verrà ridimensionato in place alla dimensione dei dati e riempito con tali dati. Gli stessi oggetti list e memoryview possono essere riutilizzati nelle chiamate successive a questo metodo, fornendo un modo per ricevere dati senza usare l’heap. Ad esempio: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¶
Invia un messaggio sul bus:
data sono i dati da inviare (un intero da inviare, o un oggetto buffer).
id è l’id del messaggio da inviare.
timeout è il timeout in millisecondi per attendere l’invio.
rtr è un booleano che specifica se il messaggio deve essere inviato come richiesta di trasmissione remota. Se rtr è True allora solo la lunghezza di data viene usata per riempire lo slot DLC del frame; i byte effettivi in data non vengono usati.
extframe se True il frame avrà un identificatore esteso (29 bit), altrimenti viene usato un identificatore standard (11 bit).
fdf per i controller CAN FD, se impostato a True, il frame avrà un formato frame FD, che supporta payload di dati fino a 64 byte.
brs per i controller CAN FD, se impostato a True, viene abilitata la modalità di commutazione del bitrate, in cui la fase dati viene trasmessa a un bitrate diverso. Vedere
CAN.init()per i parametri di configurazione della temporizzazione del bit dati.
Se timeout è 0 il messaggio viene posto in un buffer in uno dei tre buffer hardware e il metodo ritorna immediatamente. Se tutti e tre i buffer sono in uso viene sollevata un’eccezione. Se timeout non è 0, il metodo attende finché il messaggio non viene trasmesso. Se il messaggio non può essere trasmesso entro il tempo specificato viene sollevata un’eccezione.
Valore di ritorno:
None.
- rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None¶
Registra una funzione da chiamare quando un messaggio viene accettato in una FIFO vuota:
fifo è la FIFO ricevente.
fun è la funzione da chiamare quando la FIFO diventa non vuota.
La funzione di callback accetta due argomenti: il primo è l’oggetto CAN stesso; il secondo è un intero che indica il motivo del callback:
Motivo
Significato
0Un messaggio è stato accettato in una FIFO vuota.
1La FIFO è piena.
2Un messaggio è andato perso a causa di una FIFO piena.
Esempio di utilizzo di 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)
Costanti¶
Costanti della modalità bus (argomento
modediinit()):- NORMAL: int¶
Il controller partecipa normalmente sul bus – trasmette i propri frame e conferma i frame ricevuti validi.
- LOOPBACK: int¶
Modalità di loopback interno: il controller è scollegato dai pin e instrada i frame trasmessi direttamente verso il percorso di ricezione. Utile per gli autotest senza un transceiver.
- SILENT: int¶
Modalità solo ascolto: il controller riceve i frame ma non pilota mai il bus (nessun ACK, nessuna trasmissione). Utile per lo sniffing del bus.
- SILENT_LOOPBACK: int¶
Combina
SILENTeLOOPBACK: nessuna attività sui pin e nessuna conferma, con loopback interno della TX verso la RX.
Costanti dello stato del controller (restituite da
state()):- ERROR_ACTIVE: int¶
Il controller è acceso e nello stato Error Active (sia TEC che REC sono inferiori a 96).
- ERROR_WARNING: int¶
Il controller è acceso e nello stato Error Warning (almeno uno tra TEC o REC è pari o superiore a 96).
- ERROR_PASSIVE: int¶
Il controller è acceso e nello stato Error Passive (almeno uno tra TEC o REC è pari o superiore a 128).
- BUS_OFF: int¶
Il controller è acceso ma non partecipa all’attività del bus (TEC è andato in overflow oltre 255).
Modalità di filtro CAN classico (argomento
modedisetfilter()sulla OpenMV Cam M4 / M7):Modalità di filtro CAN FD (argomento
modedisetfilter()sulla OpenMV Cam H7 / H7 Plus / Pure Thermal):