Prepare hardware
For an easy jumpstart let's use this basic setup of Arduino Nano and MCP2515 CAN-Shield: The MCP2515 is a CAN-Controller and uses an MCP2551 as an CAN-Driver. The controller has an SPI-Interface with a maximum clock-frequency of 10 MHz, which we connect directly to the SPI-Ports of the Arduino. SPI is a serial protocol with nearly no overhead (see "SPI-Protocol" unter "Communication protocols" for further details). The Quarz on the MCP-Shield is mostly an 8 MHz one. It is only used for generating/calculating clock frequencies on the CAN-Bus and has nothing to do with SPI-communication, so you can easly forgett about it.
Load libs
To communicate with the MCP-Controller we need at least two libraries:
1. An SPI-Library to use the hardware-SPI-Interface of the Arduino. I prefer the one from Paul Stoffregen, download here: https://github.com/PaulStoffregen/SPI/a ... master.zip
2. And a CAN-library, which contains basic functions of the CAN-Controller. Here i would suggest using the one from Cory J. Fowler called "MCP_CAN_LIB" which can be downloaded here: https://github.com/coryjfowler/MCP_CAN_ ... master.zip
Unzip them and rename the folder inside (the one where the files are inside) to "SPI" and "MCP_CAN_LIB" (remove the "-master" from the name) and put them into your Arduinos library directory found here: %USERPROFILE%\Documents\Arduino\libraries
First step: Include the libs
Now it's time to program! Start Arduino IDE, create new Sketch and use the libs:
Code: Select all
#include <mcp_can.h>
#include <SPI.h>
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
Setup the hardware
Next we need to tell the library how we connected the board. This is done by calling the universal constructor method of the class, giving the IO-Pin name where the CS-Signal (Chip-Select) is connected. In our example above it is connected to Pin 2, which can be referred to in Arduino by simply using "2":
Code: Select all
MCP_CAN CAN0(2);
Code: Select all
#define CAN0_CS 2
MCP_CAN CAN0(CAN0_CS);
Code: Select all
MCP_CAN MMCAN_IN(..);
or
MCP_CAN MMCAN_OUT(..);
For the first examples we're not going to use the interrupt-signal, so ignore it for a while.
Initialize the controller
By calling the "begin()"-method of the object you created in the step above, you configure the controller using the most basic parameters:
Code: Select all
CAN0.begin(MCP_STD, CAN_125KBPS, MCP_8MHZ);
Send a message
Now we are ready to send a message. Until now, the controller is in loopback-mode, which means it does not receive anything from the CAN, nor could it send anything to it. We first need to "activate" it with:
Code: Select all
CAN0.setMode(MCP_NORMAL);
To send a message you need the following informations:
- The CAN-ID of the message
- The number of data bytes to send (payload)
- The bytes to send itself
Code: Select all
unsigned long canid = 0x433;
Code: Select all
unsigned char dlc = 8;
[code]
And least the data, which is an array of bytes, which can be assigned as a fixed value:
[code]
unsigned char data[8] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0x55, 0xAA, 0x55 };
Code: Select all
unsigned char data[8];
data[0] = 0xDE;
data[1] = 0xAD;
...
data[7] = 0x55;
Code: Select all
CAN0.sendMsgBuf(canid, dlc, data);
Here the complete code:
Code: Select all
#include <mcp_can.h>
#include <SPI.h>
#define CAN0_CS 2
MCP_CAN CAN0(CAN0_CS);
void setup() {
CAN0.begin(MCP_STD, CAN_125KBPS, MCP_8MHZ);
CAN0.setMode(MCP_NORMAL);
unsigned long canid = 0x433;
unsigned char dlc = 8;
unsigned char data[8] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0x55, 0xAA, 0x55 };
CAN0.sendMsgBuf(canid, dlc, data);
}
void loop() {
// put your main code here, to run repeatedly:
}
The opposite way is just as simple. Use "readMsgBuf()" method to retrieve data from the last received CAN frame:
Code: Select all
CAN0.readMsgBuf(&canid, &dlc, &data);
Code: Select all
if (canid == 0x1F0) {
...
}
Code: Select all
#include <mcp_can.h>
#include <SPI.h>
#define CAN0_CS 2
MCP_CAN CAN0(CAN0_CS);
void setup() {
CAN0.begin(MCP_STD, CAN_125KBPS, MCP_8MHZ);
CAN0.setMode(MCP_NORMAL);
unsigned long canid;
unsigned char dlc;
unsigned char data[8];
CAN0.readMsgBuf(&canid, &dlc, &data);
if (canid == 0x1F0) {
// do something with the data...
}
}
void loop() {
// put your main code here, to run repeatedly:
}
That's all it needs for the basics!
Try it out, get familar and we can go on to more complicated, but more usefull code...