Skip to content
This repository was archived by the owner on Nov 19, 2017. It is now read-only.

CanHowTo

Steven Rhodes edited this page Mar 13, 2015 · 1 revision

This documentation was last updated in 2011, it may have experienced some bitrot.

Introduction

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:

  1. Send reset command
  2. Send baud rate commands (which is 3 configuration registers)
  3. Send filter commands (If needed)
  4. Send "Turn on" command

To send:

  1. Check if any transmit buffers are empty
  2. Write a CAN message into a transmit buffer
  3. Send "Transmit" command

To receive:

If the MCP2515 asserts the CAN INT line low, that means there is a new message

  1. Query to see which receive buffer the message is in
  2. Send command to read message out of receive buffer
  3. 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.

Starting up the Microcontroller

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.

Enable buffer

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.

Attach a custom interrupt handler

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.

Enable filters

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.

Receiving a message

Using an interrupt handler

TODO: Write me D:

Sending a message

TODO: Write me D:

Function reference

TODO: Write me D: And maybe move me to a different page

Clone this wiki locally