CAN bus- receive function

10 Jan 2011

Hi,

With reference to CAN bus example code in http://mbed.org/handbook/CAN, I am trying to modify the code in order to receive a message with specific ID.

The follwoing read CAN function: "can1.read(msg)" receives any message, and I want to specify the message ID that it can receive.


Any advise?

 

Thanks in advance

10 Jan 2011 . Edited: 10 Jan 2011

 

if(msg.id == 0x001)
{
    // Your Code
}

The info on this object is in the handbook section

The other option being to hard set the masks, but you're better writing a handler.

03 Apr 2013

I know this thread is a little old, but for future readers: It really depends on your use case.

An important thing to consider is bus loading and ignored packet frequency. If your bus is near capacity and most packets aren't relevant to your device you might spend more cycles than you want ignoring packets.

When to hardware filter: If useful/actionable data will NEVER come from the filter mask and you want to avoid using CPU time to filter.

Example: If you're building a Tachometer, it probably never needs to process data from the Air Conditioner. A hardware filter will save you CPU cycles and inconvenient interrupts.

When to code a filter: During testing/beta when you aren't 100% sure what data you may need. In an environment that changes frequently. If your filter changes based on program flow control.

Example: If you built a CAN bootloader you'd want to ignore bootloader commands that aren't for you. Once you go into bootloader "mode" you could use a flag to process bootloader commands.

Can Bootloader Filter

if(msg.id == 0x01 && BootloaderModeEnabled )
{
     // Your Bootloader Code
}

This will still cost you CPU cycles for every CAN packet, but you won't need to bother processing some of them under some circumstances.

07 May 2014

Hi evryone... newbie here.

ive used the || if (msg.id == 0x01) || within the || if (can2.read(msg1)) ||. That is if only 1 message that we want to filter. how about when we want to filter multiple message ids?

28 Mar 2017

dosh dance wrote:

Hi evryone... newbie here.

ive used the || if (msg.id == 0x01) || within the || if (can2.read(msg1)) ||. That is if only 1 message that we want to filter. how about when we want to filter multiple message ids?

I know this is rather old topic, but I am facing problems while filtering IDs.

The way I am currently doing is using a switch case structure to select the messages I want to read and to save the data in the appropriate variables, however whenever I try filtering a big number of IDs I start noticing a loss of data.

I am using an ST board to communicate with a motor controller which is programmed to send certain data, such as speed, torque and temperatures, but I noticed the variables where the parameters are stored are updating very slowly. I imagined it has something to do with buffers not being cleared in time.

Can anyone explain this? Whats the proper way to filter multiple IDs without losing data?

01 Apr 2017

You should read the ST Reference Manual section on the CAN module and dig into things at the register level. For example the manual for the F0 parts is here:

http://www.st.com/content/ccc/resource/technical/document/reference_manual/c2/f8/8a/f2/18/e6/43/96/DM00031936.pdf/files/DM00031936.pdf/jcr:content/translations/en.DM00031936.pdf

You may also want to generate a CAN project using ST CubeMX and see what they do for a CAN driver. The Hal functions are different than those in the mbed-os.

Per ST the filtering is best done using the built in Filter banks. You can set the hardware to ignore messages you don't care about, saving you a ton of cpu time. Messages you don't care about will be handled entirely by the hardware. The mbed CAN class appears to implement filters, but probably a good chance it does not work right - I have not dug into these yet.

The mbed-os CAN implementation for the STM32F0 sort of works, but a lot of important things are kind of broken. CAN::write and CAN::read always return success. They don't actually check whether the operation was successful. CAN::read is protected by mutexes, which means you shouldn't read it inside an interrupt. Even though they provide a method for attaching an interrupt on read...but (and I have tested this) CAN::read is the only way to clear the interrupt flag. To avoid overflowing the buffer and missing frames you would generally want to use the interrupt on receive options. Or if the bus is slow enough you might get away with polling CAN::read very fast. But neither of these will work without tweaking functions in can_api.c.

Also there is no way to configure a lot of the register options from the CAN class interface.