It's actually going to be used to interface to an Electric Vehicle controller, so no OBD-II needed. Of course, it's a proprietry system that I've got to hack, so we'll see how that goes. : Should be fun though.
Here's the library code:
MCP2515.h
/*
MCP2515.h - Library for Microchip MCP2515 CAN Controller
Author: David Harding
Created: 11/08/2010
For further information see:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
http://en.wikipedia.org/wiki/CAN_bus
*/
#ifndef MCP2515_h
#define MCP2515_h
#include "WProgram.h"
#include "MCP2515_defs.h"
class MCP2515
{
public:
// Constructor defining which pins to use for CS and INT
MCP2515(byte CS_Pin, byte INT_Pin);
// Overloaded initialization function
int Init(int baud, byte freq);
int Init(int baud, byte freq, byte sjw);
// Basic MCP2515 SPI Command Set
void Reset();
byte Read(byte address);
void Read(byte address, byte data[], byte bytes);
Frame ReadBuffer(byte buffer);
void Write(byte address, byte data);
void Write(byte address, byte data[], byte bytes);
void LoadBuffer(byte buffer, Frame message);
void SendBuffer(byte buffers);
byte Status();
byte RXStatus();
void BitModify(byte address, byte mask, byte data);
// Extra functions
bool Interrupt(); // Expose state of INT pin
bool Mode(byte mode); // Returns TRUE if mode change successful
private:
bool _init(int baud, byte freq, byte sjw, bool autoBaud);
// Pin variables
byte _CS;
byte _INT;
};
#endif
MCP2515_defs.h
/*
MCP2515_defs.h - Library for Microchip MCP2515 CAN Controller
Author: David Harding
Created: 11/08/2010
For further information see:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
http://en.wikipedia.org/wiki/CAN_bus
*/
#ifndef MCP2515_defs_h
#define MCP2515_defs_h
#include "WProgram.h"
typedef struct
{
unsigned long id; // EID if ide set, SID otherwise
byte srr; // Standard Frame Remote Transmit Request
byte rtr; // Remote Transmission Request
byte ide; // Extended ID flag
byte dlc; // Number of data bytes
byte data[8]; // Data bytes
} Frame;
// MCP2515 SPI Commands
#define CAN_RESET 0xC0
#define CAN_READ 0x03
#define CAN_WRITE 0x02
#define CAN_RTS 0x80
#define CAN_STATUS 0xA0
#define CAN_BIT_MODIFY 0x05
#define CAN_RX_STATUS 0xB0
#define CAN_READ_BUFFER 0x90
#define CAN_LOAD_BUFFER 0X40
// Register Bit Masks
// CANSTAT
#define MODE_CONFIG 0x80
#define MODE_LISTEN 0x60
#define MODE_LOOPBACK 0x40
#define MODE_SLEEP 0x20
#define MODE_NORMAL 0x00
// CANINTF
#define RX0IF 0x01
#define RX1IF 0x02
#define TX0IF 0x04
#define TX1IF 0x08
#define TX2IF 0x10
#define ERRIF 0x20
#define WAKIF 0x40
#define MERRF 0x80
// Configuration Registers
#define CANSTAT 0x0E
#define CANCTRL 0x0F
#define BFPCTRL 0x0C
#define TEC 0x1C
#define REC 0x1D
#define CNF3 0x28
#define CNF2 0x29
#define CNF1 0x2A
#define CANINTE 0x2B
#define CANINTF 0x2C
#define EFLG 0x2D
#define TXRTSCTRL 0x0D
// TX Buffer 0
#define TXB0CTRL 0x30
#define TXB0SIDH 0x31
#define TXB0SIDL 0x32
#define TXB0EID8 0x33
#define TXB0EID0 0x34
#define TXB0DLC 0x35
#define TXB0D0 0x36
#define TXB0D1 0x37
#define TXB0D2 0x38
#define TXB0D3 0x39
#define TXB0D4 0x3A
#define TXB0D5 0x3B
#define TXB0D6 0x3C
#define TXB0D7 0x3D
// TX Buffer 1
#define TXB1CTRL 0x40
#define TXB1SIDH 0x41
#define TXB1SIDL 0x42
#define TXB1EID8 0x43
#define TXB1EID0 0x44
#define TXB1DLC 0x45
#define TXB1D0 0x46
#define TXB1D1 0x47
#define TXB1D2 0x48
#define TXB1D3 0x49
#define TXB1D4 0x4A
#define TXB1D5 0x4B
#define TXB1D6 0x4C
#define TXB1D7 0x4D
// TX Buffer 2
#define TXB2CTRL 0x50
#define TXB2SIDH 0x51
#define TXB2SIDL 0x52
#define TXB2EID8 0x53
#define TXB2EID0 0x54
#define TXB2DLC 0x55
#define TXB2D0 0x56
#define TXB2D1 0x57
#define TXB2D2 0x58
#define TXB2D3 0x59
#define TXB2D4 0x5A
#define TXB2D5 0x5B
#define TXB2D6 0x5C
#define TXB2D7 0x5D
// RX Buffer 0
#define RXB0CTRL 0x60
#define RXB0SIDH 0x61
#define RXB0SIDL 0x62
#define RXB0EID8 0x63
#define RXB0EID0 0x64
#define RXB0DLC 0x65
#define RXB0D0 0x66
#define RXB0D1 0x67
#define RXB0D2 0x68
#define RXB0D3 0x69
#define RXB0D4 0x6A
#define RXB0D5 0x6B
#define RXB0D6 0x6C
#define RXB0D7 0x6D
// RX Buffer 1
#define RXB1CTRL 0x70
#define RXB1SIDH 0x71
#define RXB1SIDL 0x72
#define RXB1EID8 0x73
#define RXB1EID0 0x74
#define RXB1DLC 0x75
#define RXB1D0 0x76
#define RXB1D1 0x77
#define RXB1D2 0x78
#define RXB1D3 0x79
#define RXB1D4 0x7A
#define RXB1D5 0x7B
#define RXB1D6 0x7C
#define RXB1D7 0x7D
// Buffer Bit Masks
#define RXB0 0x00
#define RXB1 0x02
#define TXB0 0x01
#define TXB1 0x02
#define TXB2 0x04
#define TXB_ALL TXB0 | TXB1 | TXB2
#endif
Continued next post ...
MCP2515.cpp
/*
MCP2515.cpp - Library for Microchip MCP2515 CAN Controller
Author: David Harding
Created: 11/08/2010
For further information see:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
http://en.wikipedia.org/wiki/CAN_bus
*/
#include "WProgram.h"
#include "SPI.h"
#include "MCP2515.h"
#include "MCP2515_defs.h"
MCP2515::MCP2515(byte CS_Pin, byte INT_Pin) {
pinMode(CS_Pin, OUTPUT);
digitalWrite(CS_Pin,HIGH);
pinMode(INT_Pin,INPUT);
digitalWrite(INT_Pin,HIGH);
_CS = CS_Pin;
_INT = INT_Pin;
}
/*
Initialize MCP2515
int CAN_Bus_Speed = transfer speed in kbps
int Freq = MCP2515 oscillator frequency in MHz
int SJW = Synchronization Jump Width Length bits - 1 to 4 (see data sheet)
returns baud rate set
Sending a bus speed of 0 kbps initiates AutoBaud and returns zero if no
baud rate could be determined. There must be two other active nodes on the bus!
*/
int MCP2515::Init(int CAN_Bus_Speed, byte Freq) {
if(CAN_Bus_Speed>0) {
if(_init(CAN_Bus_Speed, Freq, 1, false)) return CAN_Bus_Speed;
} else {
int i=0;
byte interruptFlags = 0;
for(i=5; i<1000; i=i+5) {
if(_init(i, Freq, 1, true)) {
// check for bus activity
Write(CANINTF,0);
delay(500); // need the bus to be communicating within this time frame
if(Interrupt()) {
// determine which interrupt flags have been set
interruptFlags = Read(CANINTF);
if(!(interruptFlags & MERRF)) {
// to get here we must have received something without errors
Mode(MODE_NORMAL);
return i;
}
}
}
}
}
return 0;
}
int MCP2515::Init(int CAN_Bus_Speed, byte Freq, byte SJW) {
if(SJW < 1) SJW = 1;
if(SJW > 4) SJW = 4;
if(CAN_Bus_Speed>0) {
if(_init(CAN_Bus_Speed, Freq, SJW, false)) return CAN_Bus_Speed;
} else {
int i=0;
byte interruptFlags = 0;
for(i=5; i<1000; i=i+5) {
if(_init(i, Freq, SJW, true)) {
// check for bus activity
Write(CANINTF,0);
delay(500); // need the bus to be communicating within this time frame
if(Interrupt()) {
// determine which interrupt flags have been set
interruptFlags = Read(CANINTF);
if(!(interruptFlags & MERRF)) {
// to get here we must have received something without errors
Mode(MODE_NORMAL);
return i;
}
}
}
}
}
return 0;
}
bool MCP2515::_init(int CAN_Bus_Speed, byte Freq, byte SJW, bool autoBaud) {
// Reset MCP2515 which puts it in configuration mode
Reset();
// Calculate bit timing registers
byte BRP;
float TQ;
byte BT;
float tempBT;
float NBT = 1.0 / (float)CAN_Bus_Speed * 1000.0; // Nominal Bit Time
for(BRP=0;BRP<8;BRP++) {
TQ = 2.0 * (float)(BRP + 1) / (float)Freq;
tempBT = NBT / TQ;
if(tempBT<=25) {
BT = (int)tempBT;
if(tempBT-BT==0) break;
}
}
byte SPT = (0.7 * BT); // Sample point
byte PRSEG = (SPT - 1) / 2;
byte PHSEG1 = SPT - PRSEG - 1;
byte PHSEG2 = BT - PHSEG1 - PRSEG - 1;
// Programming requirements
if(PRSEG + PHSEG1 < PHSEG2) return false;
if(PHSEG2 <= SJW) return false;
byte BTLMODE = 1;
byte SAM = 0;
// Set registers
byte data = (((SJW-1) << 6) | BRP);
Write(CNF1, data);
Write(CNF2, ((BTLMODE << 7) | (SAM << 6) | ((PHSEG1-1) << 3) | (PRSEG-1)));
Write(CNF3, (B10000000 | (PHSEG2-1)));
Write(TXRTSCTRL,0);
if(!autoBaud) {
// Return to Normal mode
if(!Mode(MODE_NORMAL)) return false;
} else {
// Set to Listen Only mode
if(!Mode(MODE_LISTEN)) return false;
}
// Enable all interupts
Write(CANINTE,255);
// Test that we can read back from the MCP2515 what we wrote to it
byte rtn = Read(CNF1);
return (rtn==data);
}
void MCP2515::Reset() {
digitalWrite(_CS,LOW);
SPI.transfer(CAN_RESET);
digitalWrite(_CS,HIGH);
}
byte MCP2515::Read(byte address) {
digitalWrite(_CS,LOW);
SPI.transfer(CAN_READ);
SPI.transfer(address);
byte data = SPI.transfer(0x00);
digitalWrite(_CS,HIGH);
return data;
}
void MCP2515::Read(byte address, byte data[], byte bytes) {
// allows for sequential reading of registers starting at address - see data sheet
byte i;
digitalWrite(_CS,LOW);
SPI.transfer(CAN_READ);
SPI.transfer(address);
for(i=0;i<bytes;i++) {
data[i] = SPI.transfer(0x00);
}
digitalWrite(_CS,HIGH);
}
Frame MCP2515::ReadBuffer(byte buffer) {
// Reads an entire RX buffer.
// buffer should be either RXB0 or RXB1
Frame message;
digitalWrite(_CS,LOW);
SPI.transfer(CAN_READ_BUFFER | (buffer<<1));
byte byte1 = SPI.transfer(0x00); // RXBnSIDH
byte byte2 = SPI.transfer(0x00); // RXBnSIDL
byte byte3 = SPI.transfer(0x00); // RXBnEID8
byte byte4 = SPI.transfer(0x00); // RXBnEID0
byte byte5 = SPI.transfer(0x00); // RXBnDLC
message.srr=(byte2 & B00010000);
message.ide=(byte2 & B00001000);
if(message.ide) {
message.id = (byte1>>3);
message.id = (message.id<<8) | ((byte1<<5) | ((byte2>>5)<<2) | (byte2 & B00000011));
message.id = (message.id<<8) | byte3;
message.id = (message.id<<8) | byte4;
} else {
message.id = ((byte1>>5)<<8) | ((byte1<<3) | (byte2>>5));
}
message.rtr=(byte5 & B01000000);
message.dlc = (byte5 & B00001111); // Number of data bytes
for(int i=0;i<message.dlc;i++) {
message.data[i] = SPI.transfer(0x00);
}
digitalWrite(_CS,HIGH);
return message;
}
void MCP2515::Write(byte address, byte data) {
digitalWrite(_CS,LOW);
SPI.transfer(CAN_WRITE);
SPI.transfer(address);
SPI.transfer(data);
digitalWrite(_CS,HIGH);
}
void MCP2515::Write(byte address, byte data[], byte bytes) {
// allows for sequential writing of registers starting at address - see data sheet
byte i;
digitalWrite(_CS,LOW);
SPI.transfer(CAN_WRITE);
SPI.transfer(address);
for(i=0;i<bytes;i++) {
SPI.transfer(data[i]);
}
digitalWrite(_CS,HIGH);
}
void MCP2515::SendBuffer(byte buffers) {
// buffers should be any combination of TXB0, TXB1, TXB2 ORed together, or TXB_ALL
digitalWrite(_CS,LOW);
SPI.transfer(CAN_RTS | buffers);
digitalWrite(_CS,HIGH);
}
void MCP2515::LoadBuffer(byte buffer, Frame message) {
// buffer should be one of TXB0, TXB1 or TXB2
if(buffer==TXB0) buffer = 0;
byte byte1=0; // TXBnSIDH
byte byte2=0; // TXBnSIDL
byte byte3=0; // TXBnEID8
byte byte4=0; // TXBnEID0
byte byte5=0; // TXBnDLC
if(message.ide) {
byte1 = byte((message.id<<3)>>24); // 8 MSBits of SID
byte2 = byte((message.id<<11)>>24) & B11100000; // 3 LSBits of SID
byte2 = byte2 | byte((message.id<<14)>>30); // 2 MSBits of EID
byte2 = byte2 | B00001000; // EXIDE
byte3 = byte((message.id<<16)>>24); // EID Bits 15-8
byte4 = byte((message.id<<24)>>24); // EID Bits 7-0
} else {
byte1 = byte((message.id<<21)>>24); // 8 MSBits of SID
byte2 = byte((message.id<<29)>>24) & B11100000; // 3 LSBits of SID
byte3 = 0; // TXBnEID8
byte4 = 0; // TXBnEID0
}
byte5 = message.dlc;
if(message.rtr) {
byte5 = byte5 | B01000000;
}
digitalWrite(_CS,LOW);
SPI.transfer(CAN_LOAD_BUFFER | buffer);
SPI.transfer(byte1);
SPI.transfer(byte2);
SPI.transfer(byte3);
SPI.transfer(byte4);
SPI.transfer(byte5);
for(int i=0;i<message.dlc;i++) {
SPI.transfer(message.data[i]);
}
digitalWrite(_CS,HIGH);
}
byte MCP2515::Status() {
digitalWrite(_CS,LOW);
SPI.transfer(CAN_STATUS);
byte data = SPI.transfer(0x00);
digitalWrite(_CS,HIGH);
return data;
/*
bit 7 - CANINTF.TX2IF
bit 6 - TXB2CNTRL.TXREQ
bit 5 - CANINTF.TX1IF
bit 4 - TXB1CNTRL.TXREQ
bit 3 - CANINTF.TX0IF
bit 2 - TXB0CNTRL.TXREQ
bit 1 - CANINTFL.RX1IF
bit 0 - CANINTF.RX0IF
*/
}
byte MCP2515::RXStatus() {
digitalWrite(_CS,LOW);
SPI.transfer(CAN_RX_STATUS);
byte data = SPI.transfer(0x00);
digitalWrite(_CS,HIGH);
return data;
/*
bit 7 - CANINTF.RX1IF
bit 6 - CANINTF.RX0IF
bit 5 -
bit 4 - RXBnSIDL.EIDE
bit 3 - RXBnDLC.RTR
bit 2 | 1 | 0 | Filter Match
------|---|---|-------------
0 | 0 | 0 | RXF0
0 | 0 | 1 | RXF1
0 | 1 | 0 | RXF2
0 | 1 | 1 | RXF3
1 | 0 | 0 | RXF4
1 | 0 | 1 | RXF5
1 | 1 | 0 | RXF0 (rollover to RXB1)
1 | 1 | 1 | RXF1 (rollover to RXB1)
*/
}
void MCP2515::BitModify(byte address, byte mask, byte data) {
// see data sheet for explanation
digitalWrite(_CS,LOW);
SPI.transfer(CAN_BIT_MODIFY);
SPI.transfer(address);
SPI.transfer(mask);
SPI.transfer(data);
digitalWrite(_CS,HIGH);
}
bool MCP2515::Interrupt() {
return (digitalRead(_INT)==LOW);
}
bool MCP2515::Mode(byte mode) {
/*
mode can be one of the following:
MODE_CONFIG
MODE_LISTEN
MODE_LOOPBACK
MODE_SLEEP
MODE_NORMAL
*/
BitModify(CANCTRL, B11100000, mode);
delay(10); // allow for any transmissions to complete
byte data = Read(CANSTAT); // check mode has been set
return ((data & mode)==mode);
}
keywords.txt
#######################################
# Syntax Coloring Map MCP2515
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
MCP2515 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
Init KEYWORD2
Reset KEYWORD2
Read KEYWORD2
ReadBuffer KEYWORD2
Write KEYWORD2
LoadBuffer KEYWORD2
SendBuffer KEYWORD2
Status KEYWORD2
RXStatus KEYWORD2
BitModify KEYWORD2
Interrupt KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
CAN_RESET LITERAL1
CAN_READ LITERAL1
CAN_WRITE LITERAL1
CAN_RTS LITERAL1
CAN_STATUS LITERAL1
CAN_BIT_MODIFY LITERAL1
CAN_RX_STATUS LITERAL1
CAN_READ_BUFFER LITERAL1
CAN_LOAD_BUFFER LITERAL1
RXB0 LITERAL1
RXB1 LITERAL1
TXB0 LITERAL1
TXB1 LITERAL1
TXB2 LITERAL1
TXB_ALL LITERAL1
MODE_CONFIG LITERAL1
MODE_LISTEN LITERAL1
MODE_LOOPBACK LITERAL1
MODE_SLEEP LITERAL1
MODE_NORMAL LITERAL1
RX0IF LITERAL1
RX1IF LITERAL1
TX0IF LITERAL1
TX1IF LITERAL1
TX2IF LITERAL1
ERRIF LITERAL1
WAKIF LITERAL1
MERRF LITERAL1
CANTest.pde
/*
MCP2515 CAN Interface Using SPI
Author: David Harding
Created: 11/08/2010
For further information see:
http://ww1.microchip.com/downloads/en/DeviceDoc/21801e.pdf
http://en.wikipedia.org/wiki/CAN_bus
The MCP2515 Library files also contain important information
This sketch shows the most basic of steps to send and receive CAN messages.
It has been tested with a Microchip MCP2515DM-BM Demo Board, which consists of two identical
boards that pass messages between each other. There is a connector available so that another
CAN device can be connected to the bus. Using this I was able to read the messages passed
between the two boards, and also introduce my own messages to the bus, which are then displayed
by the software supplied with the demo kit.
NOTE!!! If you use this sketch to test on a live system I suggest that you comment out the
send messages lines unless you are certain that they will have no detrimental effect!
*/
#include <SPI.h> // Arduino SPI Library
#include <MCP2515.h>
// Pin definitions specific to how the MCP2515 is wired up.
#define CS_PIN 10
#define INT_PIN 6
// Create CAN object with pins as defined
MCP2515 CAN(CS_PIN, INT_PIN);
void setup() {
Serial.begin(115200);
Serial.println("Initializing ...");
// Set up SPI Communication
// dataMode can be SPI_MODE0 or SPI_MODE3 only for MCP2515
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE0);
SPI.setBitOrder(MSBFIRST);
SPI.begin();
// Initialise MCP2515 CAN controller at the specified speed and clock frequency
// In this case 125kbps with a 16MHz oscillator
// (Note: This is the oscillator attached to the MCP2515, not the Arduino oscillaltor)
int baudRate=CAN.Init(125,16);
if(baudRate>0) {
Serial.println("MCP2515 Init OK ...");
Serial.print("Baud Rate (kbps): ");
Serial.println(baudRate,DEC);
} else {
Serial.println("MCP2515 Init Failed ...");
}
Serial.println("Ready ...");
}
byte i=0;
// CAN message frame (actually just the parts that are exposed by the MCP2515 RX/TX buffers)
Frame message;
void loop() {
message.id = 0;
// This implementation utilizes the MCP2515 INT pin to flag received messages or other events
if(CAN.Interrupt()) {
// determine which interrupt flags have been set
byte interruptFlags = CAN.Read(CANINTF);
if(interruptFlags & RX0IF) {
// read from RX buffer 0
message = CAN.ReadBuffer(RXB0);
}
if(interruptFlags & RX1IF) {
// read from RX buffer 1
message = CAN.ReadBuffer(RXB1);
// (this is poor code as clearly if two messages are received then the second will overwrite the first)
}
if(interruptFlags & TX0IF) {
// TX buffer 0 sent
}
if(interruptFlags & TX1IF) {
// TX buffer 1 sent
}
if(interruptFlags & TX2IF) {
// TX buffer 2 sent
}
if(interruptFlags & ERRIF) {
// error handling code
}
if(interruptFlags & MERRF) {
// error handling code
// if TXBnCTRL.TXERR set then transmission error
// if message is lost TXBnCTRL.MLOA will be set
}
}
if(message.id>0) {
// Print message
Serial.print("ID: ");
Serial.println(message.id,HEX);
Serial.print("Extended: ");
if(message.ide) {
Serial.println("Yes");
} else {
Serial.println("No");
}
Serial.print("DLC: ");
Serial.println(message.dlc,DEC);
for(i=0;i<message.dlc;i++) {
Serial.print(message.data[i],HEX);
Serial.print(" ");
}
Serial.println();
// Send out a return message for each one received
// Simply increment message id and data bytes to show proper transmission
// Note: Please see explanation at top of sketch. You might want to comment this out!
message.id++;
for(i=0;i<message.dlc;i++) {
message.data[i]++;
}
CAN.LoadBuffer(TXB0, message);
CAN.SendBuffer(TXB0);
}
}
The above is the latest revision of my code. I've added in an AutoBaud rate feature that works, but is a little clunky code wise. It requires that there are at least two active nodes on the bus, (not including the one you're using), and they must send messages at least every half second. It starts at a baud rate of 5kbps and goes up in increments of 5kbps until it reaches 1000kbps, (max rate for CAN V2.0B). This means that it could take nearly two minutes to detect the baud rate being used by the bus.
It does have a simple to use initialization routine though that simply requires a baud rate, (zero for AutoBaud), and a clock frequency, (frequency of MCP2515 oscillator, not Arduino). It then calculates out the proper bit timing for you.
Any comments or suggestions on the code would be welcome. Right now I'm waiting for a version 1.1 PCB, but I have the v1.0 shield pictured up and running just fine connected to SepEx motor controller at 125kbps. It happily streams data all day long. If the code doesn't work for you I'd be interested to know so that I can make it more universal.
Im trying to make my own CAN shield and eventually an complete unit with atmega mcu and can controller and tranceiver.
I have a working beta version of the hardware, and got the canbus working with the library from: kreatives-chaos.com » Universelle CAN Bibliothek
But as soon as i try to add a filter it all goes badly. either no message gets through or all messages gets through.
This is my filter code:
// create a new filter for receiving messages
can_filter_t filter = {
.id = 0x1ff,
.mask = 0x7ff,
.flags = {
.rtr = 0,
.extended = 0
}
};
can_set_filter(0, &filter);
can_init(BITRATE_1_MBPS);
This is done in the init part of the program,
Is anything else needed to activate the filters ?
the sending-part of my program that sends the message looks like this:
can_t msg;
msg.id = 0x7FF;
msg.flags.rtr = 0;
msg.flags.extended = 0;
msg.length = 4;
msg.data[0] = 0xde;
msg.data[1] = 0xad;
msg.data[2] = 0xbe;
msg.data[3] = 0xef;
can_send_message(&msg);
This message is still received, even though the id = 0x1ff should ignore it in the filter as i understand it.
From what I can gather from a quick glance at the data sheet and your code the filter works on the first two data bytes of a standard frame, not the message ID. I think you're trying to filter on the message ID, but you're using a standard frame, so this won't work.
If you use an extended frame then the mask applies to the full 29 bit ID field.
The mask you have requires an exact match between the message ID and the filter - i.e. only one specific message ID will be received. I think your test code is correct, (i.e. you're right and the message should be rejected), but again, it comes down to using a standard ID instead of an extended ID.
See figure 4-4 on page 32 of the MCP2515 datasheet.
Would you be willing to share your schematic and/or eagle files? I'm trying to start up a similar project, and could use a decent reference.
My prototype is a small (2,5 x 5 cm) shield for the arduino, which just fits the mcp2515 and a can tranceiver (both can be sampled from TI afair). All is done with smd components and pinheaders through hole, as i think thats easiest. The shield's size makes all the analog and half of the digital i/o pins available when the shield is on.
I can upload the eagle files if you want
Hello RiiiisDK! I would be very interessted in seeing your design.
I am searching especially for a small desing for an Arduino Mini pro project.
cheers,
Michael
Hello!
I get a lot of errors when trying to compile Dave AKs Code:
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Reset()':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:153: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'byte MCP2515::Read(byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:159: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:160: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:161: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Read(byte, byte*, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:170: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:171: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:173: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'Frame MCP2515::ReadBuffer(byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:186: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:187: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:188: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:189: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:190: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:191: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:208: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Write(byte, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:217: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:218: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:219: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::Write(byte, byte*, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:227: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:228: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:230: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::SendBuffer(byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:238: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::LoadBuffer(byte, Frame)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:272: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:273: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:274: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:275: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:276: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:277: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:280: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'byte MCP2515::Status()':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:287: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:288: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'byte MCP2515::RXStatus()':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:305: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:306: error: expected primary-expression before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp: In member function 'void MCP2515::BitModify(byte, byte, byte)':
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:331: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:332: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:333: error: expected unqualified-id before '.' token
C:\Dokumente und Einstellungen\WW\Desktop\[PROJEKTE]\arduino-0018\libraries\MCP2515\MCP2515.cpp:334: error: expected unqualified-id before '.' token
Any ideas where to look at?
Would it be possible to post the code in file form?
Regards,
Michael
hi.
Seems to work on Arduino 0021.
Sorry for the confusion, I would be intressted in dem SMT design thought.
Thanks a lot to all for all the effort.
regards,
Michael
You are so right the projects never end.
I'll have to email that to a few people make there days as great as mine also great job.
MakerMann
Here's the latest versions of my board. I would love to make these SMD at some time but I'm a newbie at this stuff so it will have to wait. Also these boards are to fulfill a specific need, which is strictly CAN only at the moment.
I now have two boards. A single and a double. The single is shrunk down in size a little and has protection for taking power from the bus. It still has a switchable CS pin.
The double allows you to split a CAN bus. It has two separate CAN circuits, CAN 1 uses D10 and CAN 2 uses D9 as CS. You can use either of the CAN circuits individually, or together either with separate cables or a single cable plugged in to CAN 1. (Providing it's correctly configured of course!)
That looks very nice. Are you going to be selling them?
That looks very nice. Are you going to be selling them?
Thanks! I haven't decided on whether to sell them or not. There are a few CAN implementations on the market already. Not sure if I could be profitable selling these.
Yeah, that's pretty much what I was checkin on, was to see if you were doing this for a better price than the current market options.
Hello
I am working on a project to read can data from a ECU. I use an arduino uno & sparkfun CAN bus shield.
I have a problem of
error: expected unqualified-id before '.',
Do you know a solution to this ?
Thank you
Usually a typo in the code somewhere. If you post yours, we can help you find it.