class CAN – controller area network communication bus¶
CAN implements support for both classic CAN (bxCAN, used on the OpenMV Cam M4 and M7) and CAN FD (FDCAN, used on the OpenMV Cam H7, H7 Plus and Pure Thermal) controllers. At the physical level the CAN bus consists of two lines, RX and TX. To connect an OpenMV Cam to a CAN bus you must use a CAN transceiver to convert the CAN logic signals from the MCU to the correct voltage levels on the bus.
Classic CAN in loopback (transceiver-less) mode:
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 with all of the optional features enabled (FD frame, bit-rate switching, extended frame IDs; 500 kbit/s arbitration phase, 1 Mbit/s data phase):
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)
The following CAN module functions and their arguments are available for both classic and FD CAN controllers, unless otherwise stated.
Constructors¶
- class pyb.CAN(bus: int | str, *args, **kwargs)¶
Construct a CAN object on the given
bus(an integer peripheral index, e.g.1forCAN1,2forCAN2). With no additional parameters the object is created but not initialised (it retains the previous bus settings, if any); if extra arguments are given the bus is initialised. SeeCAN.init()for the available parameters.CAN(2)is wired to the same header pins on every OpenMV Cam that exposespyb.CAN(M4 / M7 / H7 / H7 Plus / Pure Thermal):Signal
Header pin
Notes
RXP3TXP2The CAN peripheral provides logic-level signals only; an external CAN transceiver is required to drive a real CAN bus.
pyb.CANis not available on the OpenMV Cam N6.Methods¶
- 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¶
Initialise the CAN bus with the given parameters:
mode is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
prescaler is the value by which the CAN input clock is divided to generate the nominal bit time quanta. The prescaler can be a value between 1 and 1024 inclusive for classic CAN, and between 1 and 512 inclusive for CAN FD.
sjw is the resynchronisation jump width in units of time quanta for nominal bits; it can be a value between 1 and 4 inclusive for classic CAN, and between 1 and 128 inclusive for CAN FD.
bs1 defines the location of the sample point in units of the time quanta for nominal bits; it can be a value between 1 and 16 inclusive for classic CAN, and between 2 and 256 inclusive for CAN FD.
bs2 defines the location of the transmit point in units of the time quanta for nominal bits; it can be a value between 1 and 8 inclusive for classic CAN, and between 2 and 128 inclusive for CAN FD.
auto_restart sets whether the controller will automatically try and restart communications after entering the bus-off state; if this is disabled then
restart()can be used to leave the bus-off statebaudrate if a baudrate other than 0 is provided, this function will try to automatically calculate the CAN nominal bit time (overriding prescaler, bs1 and bs2) that satisfies both the baudrate (within .1%) and the desired sample_point (to the nearest 1%). For more precise control over the CAN timing, set the prescaler, bs1 and bs2 parameters directly.
sample_point specifies the position of the bit sample with respect to the whole nominal bit time, expressed as an integer percentage of the nominal bit time. The default sample_point is 75%. This parameter is ignored unless baudrate is set.
num_filter_banks for classic CAN, this is the number of banks that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2).
The remaining parameters are only present on boards with CAN FD support, and configure the optional CAN FD Bit Rate Switch (BRS) feature:
brs_prescaler is the value by which the CAN FD input clock is divided to generate the data bit time quanta. The prescaler can be a value between 1 and 32 inclusive.
brs_sjw is the resynchronisation jump width in units of time quanta for data bits; it can be a value between 1 and 16 inclusive
brs_bs1 defines the location of the sample point in units of the time quanta for data bits; it can be a value between 1 and 32 inclusive
brs_bs2 defines the location of the transmit point in units of the time quanta for data bits; it can be a value between 1 and 16 inclusive
brs_baudrate if a baudrate other than 0 is provided, this function will try to automatically calculate the CAN data bit time (overriding brs_prescaler, brs_bs1 and brs_bs2) that satisfies both the brs_baudrate (within .1%) and the desired brs_sample_point (to the nearest 1%). For more precise control over the BRS timing, set the brs_prescaler, brs_bs1 and brs_bs2 parameters directly.
brs_sample_point specifies the position of the bit sample with respect to the whole nominal bit time, expressed as an integer percentage of the nominal bit time. The default brs_sample_point is 75%. This parameter is ignored unless brs_baudrate is set.
The time quanta tq is the basic unit of time for the CAN bus. tq is the CAN prescaler value divided by PCLK1 (the frequency of internal peripheral bus 1); see
pyb.freq()to determine PCLK1.A single bit is made up of the synchronisation segment, which is always 1 tq. Then follows bit segment 1, then bit segment 2. The sample point is after bit segment 1 finishes. The transmit point is after bit segment 2 finishes. The baud rate will be 1/bittime, where the bittime is 1 + BS1 + BS2 multiplied by the time quanta tq.
For example, on the OpenMV Cam H7 (PCLK1 = 100 MHz), 250 kbps CAN with a 75% sample point can be configured as
prescaler=25, sjw=1, bs1=11, bs2=4:tq = 25 / 100 MHz = 250 ns,bittime = (1 + 11 + 4) × 250 ns = 4 µs, sample point =(1 + 11) / 16 = 75%, and the baudrate is1 / 4 µs = 250 kHz.See the bxCAN / FDCAN section of the STM32 reference manual for the OpenMV Cam’s MCU for more details.
- restart() None¶
Force a software restart of the CAN controller without resetting its configuration.
If the controller enters the bus-off state then it will no longer participate in bus activity. If the controller is not configured to automatically restart (see
init()) then this method can be used to trigger a restart, and the controller will follow the CAN protocol to leave the bus-off state and go into the error active state.
- state() int¶
Return the state of the controller. The return value can be one of:
CAN.STOPPED– the controller is completely off and reset;CAN.ERROR_ACTIVE– the controller is on and in the Error Active state (both TEC and REC are less than 96);CAN.ERROR_WARNING– the controller is on and in the Error Warning state (at least one of TEC or REC is 96 or greater);CAN.ERROR_PASSIVE– the controller is on and in the Error Passive state (at least one of TEC or REC is 128 or greater);CAN.BUS_OFF– the controller is on but not participating in bus activity (TEC overflowed beyond 255).
- info(list: list | None = None) list¶
Get information about the controller’s error states and TX and RX buffers. If list is provided then it should be a list object with at least 8 entries, which will be filled in with the information. Otherwise a new list will be created and filled in. In both cases the return value of the method is the populated list.
The values in the list are:
TEC value
REC value
number of times the controller entered the Error Warning state (wrapped around to 0 after 65535)
number of times the controller entered the Error Passive state (wrapped around to 0 after 65535)
number of times the controller entered the Bus Off state (wrapped around to 0 after 65535)
number of pending TX messages
number of pending RX messages on fifo 0
number of pending RX messages on fifo 1
- setfilter(bank: int, mode: int, fifo: int, params: Tuple[int, ...], *, rtr: Tuple[bool, ...] | None = None, extframe: bool = False) None¶
Configure a filter bank:
bank is the classic CAN controller filter bank, or CAN FD filter index, to configure.
mode is the mode the filter should operate in, see the tables below.
fifo is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter.
params is an array of values the defines the filter. The contents of the array depends on the mode argument.
Contents of params array for classic CAN controllers (OpenMV Cam M4 / M7):
mode
Contents of params
CAN.LIST16Four 16-bit IDs that will be accepted.
CAN.LIST32Two 32-bit IDs that will be accepted.
CAN.MASK16Two 16-bit id/mask pairs, e.g.
(1, 3, 4, 4). The first pair (1, 3) accepts all IDs with bit 0 = 1 and bit 1 = 0; the second pair (4, 4) accepts all IDs with bit 2 = 1.CAN.MASK32One 32-bit id/mask pair (otherwise the same as
CAN.MASK16).Contents of params array for CAN FD controllers (OpenMV Cam H7 / H7 Plus / Pure Thermal):
mode
Contents of params
CAN.RANGETwo IDs forming a range of accepted IDs.
CAN.DUALTwo IDs that will be accepted (e.g.
(1, 2)).CAN.MASKOne
(id, mask)pair (e.g.(0x111, 0x7FF)).rtr For classic CAN controllers, this is an array of booleans that states whether a filter should accept a remote transmission request message. If this argument is not given it defaults to
Falsefor all entries. The length depends on mode:mode
len(rtr)Notes
CAN.LIST164
CAN.LIST322
CAN.MASK162
CAN.MASK321
For CAN FD this argument is ignored.
extframe If True the frame will have an extended identifier (29 bits), otherwise a standard identifier (11 bits) is used.
- clearfilter(bank: int, extframe: bool = False) None¶
Clear and disables a filter bank:
bank is the classic CAN controller filter bank, or CAN FD filter index, to clear.
extframe For CAN FD controllers, if True, clear an extended filter (configured with extframe=True), otherwise the clear a standard identifier (configured with extframe=False).
- recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list¶
Receive data on the bus:
fifo is an integer, which is the FIFO to receive on
list is an optional list object to be used as the return value
timeout is the timeout in milliseconds to wait for the receive.
Return value: A list containing five values.
The id of the message.
A boolean that indicates if the message ID is standard or extended.
A boolean that indicates if the message is an RTR message.
The FMI (Filter Match Index) value.
An array containing the data.
If list is
Nonethen a new list will be allocated, as well as a new bytes object to contain the data (as the fifth element in the list).If list is not
Nonethen it should be a list object with a least five elements. The fifth element should be a memoryview object which is created from either a bytearray or an array of type ‘B’ or ‘b’, and this array must have enough room for at least 8 bytes. The list object will then be populated with the first four return values above, and the memoryview object will be resized inplace to the size of the data and filled in with that data. The same list and memoryview objects can be reused in subsequent calls to this method, providing a way of receiving data without using the heap. For example: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¶
Send a message on the bus:
data is the data to send (an integer to send, or a buffer object).
id is the id of the message to be sent.
timeout is the timeout in milliseconds to wait for the send.
rtr is a boolean that specifies if the message shall be sent as a remote transmission request. If rtr is True then only the length of data is used to fill in the DLC slot of the frame; the actual bytes in data are unused.
extframe if True the frame will have an extended identifier (29 bits), otherwise a standard identifier (11 bits) is used.
fdf for CAN FD controllers, if set to True, the frame will have an FD frame format, which supports data payloads up to 64 bytes.
brs for CAN FD controllers, if set to True, the bitrate switching mode is enabled, in which the data phase is transmitted at a different bitrate. See
CAN.init()for the data bit timing configuration parameters.
If timeout is 0 the message is placed in a buffer in one of three hardware buffers and the method returns immediately. If all three buffers are in use an exception is thrown. If timeout is not 0, the method waits until the message is transmitted. If the message can’t be transmitted within the specified time an exception is thrown.
Return value:
None.
- rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None¶
Register a function to be called when a message is accepted into an empty FIFO:
fifo is the receiving FIFO.
fun is the function to be called when the FIFO becomes non-empty.
The callback function takes two arguments: the first is the CAN object itself; the second is an integer that indicates the reason for the callback:
Reason
Meaning
0A message has been accepted into an empty FIFO.
1The FIFO is full.
2A message has been lost due to a full FIFO.
Example use of 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)
Constants¶
Bus-mode constants (
modeargument ofinit()):- NORMAL: int¶
The controller participates normally on the bus – transmits its own frames and acknowledges valid received frames.
- LOOPBACK: int¶
Internal loopback mode: the controller is disconnected from the pins and routes transmitted frames straight back to the receive path. Useful for self-tests without a transceiver.
- SILENT: int¶
Listen-only mode: the controller receives frames but never drives the bus (no ACK, no transmissions). Useful for bus sniffing.
- SILENT_LOOPBACK: int¶
Combines
SILENTandLOOPBACK: no pin activity and no acknowledgements, with internal loopback of TX into RX.
Controller-state constants (returned by
state()):- ERROR_ACTIVE: int¶
The controller is on and in the Error Active state (both TEC and REC are less than 96).
- ERROR_WARNING: int¶
The controller is on and in the Error Warning state (at least one of TEC or REC is 96 or greater).
- ERROR_PASSIVE: int¶
The controller is on and in the Error Passive state (at least one of TEC or REC is 128 or greater).
- BUS_OFF: int¶
The controller is on but not participating in bus activity (TEC overflowed beyond 255).
Classic-CAN filter modes (
modeargument ofsetfilter()on the OpenMV Cam M4 / M7):CAN FD filter modes (
modeargument ofsetfilter()on the OpenMV Cam H7 / H7 Plus / Pure Thermal):