CAN Bus Sensor Module workflow
Initialization
Initialization of the CAN bus sensor is achieved as follows:
params.parameters = "device=can0";
const char8_t * protocol
Name of the protocol.
DW_API_PUBLIC dwStatus dwSAL_createSensor(dwSensorHandle_t *const sensor, dwSensorParams const params, dwSALHandle_t const sal)
Creates a new sensor managed by the SAL module with the given parameters.
struct dwSensorObject * dwSensorHandle_t
Handle representing a sensor.
Holds sets of parameters for sensor creation.
Protocol
The dwSensorParams.protocol
expects one of the following can interfaces:
can.socket
interface for system CAN bus.
can.virtual
interface for reading CAN data from binary logs.
Sensor parameters
The dwSensorParams.parameters
accepts the following parameters:
For all:
filter=id:mask[+id:mask]
:
filter
is a string of +
seperated filters
id
is a hex value
mask
is a hex value
Example: filter=123:FFF+60A:FFF
See the Setting message filters section to see how these values are used.
When using can.socket
:
device=can0[,fifo-size=1024]
device
CAN device interface, usually canx, x starting from 0
- on Linux, use
ifconfig
to list available CAN interfaces
- on QNX, use
pidin a | grep nvcan
to list available CAN interfaces
fifo-size
size of internal buffer, in number of dwCANMessage
stored.
discard-threshold
the timestamp of CAN data who is older than current timestamp by threshold will be discarded.
- only apply on QNX(CANQnx)
read-number
data size to be read from driver buffer in one syscall, default number is 256
- only apply on QNX(CANQnx)
do-not-send
disables send functionality when set to true
.
When using can.simulator
:
Identical parameters to can.socket
.
When using can.virtual
:
file=/path/to/file.can[,create_seek,default_timeout_us,time-offset=0]
file
path to CAN bus recording
create_seek
create seek table
default_timeout_us
period after which sensor times out
time-offset
offset applied to CAN messages timestamps
The CAN buses are setup with CAN FD if supported. If not supported sending and receiving CAN FD messages will fail.
Starting, stopping and releasing sensor
The CAN bus sensor can be started, stopped and released as follows:
DW_API_PUBLIC dwStatus dwSensor_start(dwSensorHandle_t const sensor)
Starts the sensor previously successfully created with 'dwSAL_createSensor()'.
DW_API_PUBLIC dwStatus dwSensor_stop(dwSensorHandle_t const sensor)
Stops the sensor.
DW_API_PUBLIC dwStatus dwSAL_releaseSensor(dwSensorHandle_t const sensor)
Releases a sensor managed by the SAL module.
Reading CAN messages
CAN messages can be read from the bus as follows:
dwStatus
Status definition.
DW_API_PUBLIC dwStatus dwSensorCAN_readMessage(dwCANMessage *const msg, dwTime_t const timeoutUs, dwSensorHandle_t const sensor)
Reads a CAN packet (raw data and process it) within a given timeout from the CAN bus.
This will populate a dwCANMessage
structure with the next CAN message received on the bus, in this example waiting up to 10000us, or 10ms, for a message to arrive. Timeout can be set to DW_TIMEOUT_INFINITE
to indicate infinite waiting until new message arrives, or 0 to immediately return and only read messages already received. The dwCANMessage
structure can hold up to 64 bytes to accommodate CAN FD messages.
To only read messages available in the internal queue, without reading new messages on the CAN bus, the dwSensorCAN_popMessage()
method can be used. Together with dwSensorCAN_processRawData()
, raw binary CAN data can be read and parsed in dwCANMessage
format, see Reading CAN Messages from Raw Data (Binary).
Sending CAN messages
CAN messages can be sent on the bus as follows:
msg.data[0] = 0xFF;
msg.size = 1;
msg.timestamp = 0;
uint32_t id
CAN ID of the message sender.
DW_API_PUBLIC dwStatus dwSensorCAN_sendMessage(const dwCANMessage *const msg, dwTime_t const timeoutUs, dwSensorHandle_t const sensor)
Sends a message over the CAN bus within a specified timeout.
This sends a message over the CAN bus within a specified timeout. A message is guaranteed to have been sent when this method returns DW_SUCCESS
. The method can block for up-to the specified amount of time if a bus is blocked or previous dwSensorCAN_readMessage()
operation has not yet finished.
If the msg.size
value is from 9 - 64, then the message will be sent as a CAN FD message.
Setting message filters
CAN messages be filtered by ID as follows:
uint32_t ids[2] = {0x100, 0x6AB};
uint32_t masks[2] = {0xF00, 0xFFF};
DW_API_PUBLIC dwStatus dwSensorCAN_setMessageFilter(const uint32_t *ids, const uint32_t *masks, uint16_t num, dwSensorHandle_t sensor)
Specifes a set of CAN IDs to be filtered.
This function takes an array of IDs and an array of masks to setup filters. Once the filters are set, only messages with IDs matching the filters will be read. Each call to the above will reset previously set filters. To reset all filtering, call the above with 0 as number of filters.
Internally, only messages that meet the following condition for at least one filter are read:
(messageID & mask) == (id & mask)
Masks are optional; when passing NULL
, a default mask of 1FFFFFFF
is used.
Setting hardware timestamping
The dwSensorCAN_setUseHwTimestamps()
function allows the user to enable or disable hardware timestamping of messages on compatible CAN Bus devices. By default, hardware timestamping is enabled if available, but can be turned off if the default behavior is not working properly with the current hardware stack.
The dwSensorCAN_readMessage()
function reads the next available CAN message with a given timeout. The function call is blocking, until a CAN message is available or the timeout is exceeded. Filters can be set with dwSensorCAN_setMessageFilter()
so that only specific messages are read from the bus. Messages can be sent with dwSensorCAN_sendMessage()
.
The dwCANMessage
structure holds a CAN message, consisting of a timestamp, an ID, message data (payload) and size. The CAN bus module supports the extended CAN frame format.
Example
The following code shows the general structure of a program setting up CAN message filters and receiving/sending messages on the bus. Only messages with IDs 0x100
-0x1FF
and 0x6AB
will be read.
params.parameters = "device=can0";
uint32_t ids[2] = {0x100, 0x6AB};
uint32_t masks[2] = {0xF00, 0xFFF};
while(loop)
{
{
}
msg.data[0] = 0xFF;
msg.size = 1;
msg.timestamp = 0;
}
For more information, refer to CAN Message Logger Sample.