-
Notifications
You must be signed in to change notification settings - Fork 3
CanHowTo
This documentation was last updated in 2011, it may have experienced some bitrot.
The CalSol Brain uses a MCP2515 to interface with the CAN bus. In order to communicate with the CAN Interface, the Brain must send a series of messages to the MCP2515 using SPI, and the order generally goes like this:
At startup:
- Send reset command
- Send baud rate commands (which is 3 configuration registers)
- Send filter commands (If needed)
- Send "Turn on" command
To send:
- Check if any transmit buffers are empty
- Write a CAN message into a transmit buffer
- Send "Transmit" command
To receive:
If the MCP2515 asserts the CAN INT line low, that means there is a new message
- Query to see which receive buffer the message is in
- Send command to read message out of receive buffer
- Reads the receive buffer
All of these steps are described clearly in the MCP2515 datasheet, but are generally long and convoluted. To make the process of interfacing with CAN simpler, the Brain comes with a CAN Library that encapsulates all of these steps into easier to use functions.
To start up the microcontroller, call the following function:
Can.begin(1000);
Can.begin takes one argument: the desired baud rate in khz. This function
must be called before you start using Can functions, and can only be
called once.
To enable the use of the software buffer (A ring buffer with 30 slots), call the following function:
Can.begin(1000);
CanBufferInit();
Note that the call to CanBufferInit() is done after the call to Can.begin().
Calling CanBufferInit() will allow you to take advantage of the functions
CanBufferSize() and CanBufferRead().
Note that CanBufferInit() is a global function, that's because its written
specifically for the Brain, and attaches an ISR to the CANINT line.
First write a custom interrupt handler with the following signature:
void process_packet(CanMessage &msg);
The function name can be anything, but for its argument it must take a
reference to a CanMessage object. The CanMessage object passed in is
the message received by the Brain when the interrupt occurs.
Once you have your interrupt handler, add this code as your startup code:
Can.attach(&process_packet);
Can.begin(1000);
CanBufferInit();
Can.attach() tells the CAN library that instead of sending the packet to the
CAN buffer every time it receives a message, that it should call
process_packet() instead to deal with that packet. This means that if you
call Can.attach(), the CAN buffer will no longer be used.
Important: Please read page 23 and look at figure 4-2 (on pg. 25) of the MCP2515 Datasheet before continuing.
The MCP2515 has hardware filters that can be used to allow only relevant
packets to be received. To enable filters, add the following as the startup code
(note this sample code also includes an attach() call):
Can.reset();
Can.filterOn();
// Filters go below here
Can.setFilter(1, 0x020, 1);
Can.setFilter(1, 0x040, 2);
Can.setMask(1, 0x7F0);
Can.setMask(2, 0x000);
// End Filters
Can.attach(&process_packet); // Optional
Can.begin(1000, false);
CanBufferInit(); // Optional
The three relevant functions are as follows:
Can.filterOn(void);
Turns on hardware filtering. Must be called after Can.reset() and before
setFilter().
Can.setFilter(int mask_channel, int filter, int filter_channel);
TODO: Add some description here.
Can.setMask(int mask_channel, int mask);
Sets a hardware mask on the MCP2515. There are two masks channels (1 and
2), and both MUST be set for filters to work. If either channel 1 or 2 is not used,
then call Can.setMask(2, 0x000); to ensure the second mask doesn't leak
packets into your buffer. TODO: Add more description here.
TODO: Write me D:
TODO: Write me D:
TODO: Write me D: And maybe move me to a different page