I have an MCP2515/2551 setup on a breadboard that's identical to this circuit: GitHub - autowp/arduino-mcp2515: Arduino MCP2515 CAN interface library
Actually, I've had problems with this board in the past but they are resolved now (DIY CAN MCP2515/2551 Setup w/Nano - MCP2515 keeps sleeping - Networking, Protocols, and Devices - Arduino Forum), so this board is a good benchmark for testing out sending CAN messages. I can probe a message using the example sketch from the SPI bus, to the interface between the two ICs, to the CAN bus in the end eventually.
Now, I have another circuit (actually, the target PCB for the breadboard test circuit), that is identical to the original besides the following changes:
- The MCP2515 is a TSSOP instead of an SOIC (but the wiring is changed to accommodate the different pins)
- The Arduino (which was a Nano on breadboard) has been replaced with an ATMega2560 using MegaCore (GitHub - MCUdude/MegaCore: Arduino hardware package for ATmega64, ATmega128, ATmega165, ATmega169, ATmega325, ATmega329, ATmega640, ATmega645, ATmega649, ATmega1280, ATmega1281, ATmega2560, ATmega2561, ATmega3250, ATmega3290, ATmega6450, ATmega6490, AT90CAN32, AT90CAN64 and AT90CAN128)
- The ATMega2560 uses a 16MHz external crystal (as opposed to the Nano's 8MHz)
Note that the MCP2515 is on an 8MHz external clock in both circuits. So I have the proper setting in the code to use that. Here is the test code I'm using:
#include <SPI.h>
#include <mcp2515.h>
struct can_frame canMsg;
MCP2515 mcp2515(10); // Pin 10 is used on the Nano setup, Pin 28 is the SPI CS pin on my ATmega2560-based PCB (AVR Pinout scheme)
unsigned long lastFrame = 0;
struct can_frame canMsgRx;
struct can_frame canMsgTx;
void setup() {
Serial.begin(115200);
SPI.begin();
canMsgTx.can_id = 0x0F6;
canMsgTx.can_dlc = 8;
canMsgTx.data[0] = 0x8E;
canMsgTx.data[1] = 0x87;
canMsgTx.data[2] = 0x32;
canMsgTx.data[3] = 0xFA;
canMsgTx.data[4] = 0x26;
canMsgTx.data[5] = 0x8E;
canMsgTx.data[6] = 0xBE;
canMsgTx.data[7] = 0x86;
mcp2515.reset();
mcp2515.setBitrate(CAN_125KBPS, MCP_8MHZ); //Using an 8MHz external clock
mcp2515.setNormalMode();
Serial.println("Normal Mode");
}
void loop() {
// Write something every 100ms
if ( ( millis() - lastFrame ) >= 100 ) {
mcp2515.sendMessage(&canMsgTx);
lastFrame = millis();
}
// Check if there's anything to read
if (mcp2515.readMessage(&canMsgRx) == MCP2515::ERROR_OK) {
Serial.print(canMsgRx.can_id, HEX); // print ID
Serial.print(" ");
Serial.print(canMsgRx.can_dlc, HEX); // print DLC
Serial.print(" ");
for (int i = 0; i < canMsgRx.can_dlc; i++) { // print the data
Serial.print(canMsgRx.data[i], HEX);
Serial.print(" ");
}
Serial.println();
}
}
Now I don't expect to get anything back in my test circuit (since the can bus is just hanging), but it should be sending out that specific message repeatedly. And on my test PCB, exactly that is happening. I can see the data on Pin 1 (TX data) of the 2515 passing to the 2551, which then tries to put it on the bus as CAN data.
The problem lies in my ATMega2560 circuit, which seems to be failing at the 2515 output side of things.
I can see my SPI data all coming in the same way, and I've probed it to ensure that it is identical, which it mostly is (more on that in a bit). I also checked every other pin across both devices, and the voltages and signals are all in-line:
Name | SOIC MCP2515 (Breadboard) | TSSOP MCP2515 (PCB) |
| Pin# | Saw... | Pin# | Saw... |
TXCAN | 1 | Proper TxCAN data | 1 | 80% duty ~5kHz square? |
RXCAN | 2 | Proper RxCAN data | 2 | 60% duty ~5kHz square? |
CLKOUT/SOF | 3 | Blip at data start | 3 | Blip at data start |
TX0RTS! | 4 | 5V | 4 | 5V |
TX1RTS! | 5 | 5V | 5 | 5V |
NC | - | | 6 | GND |
TX2RTS! | 6 | 5V | 7 | 5V |
OSC2 | 7 | 8MHz square | 8 | 8MHz square |
OSC1 | 8 | 8MHz square | 9 | 8MHz square |
Vss | 9 | GND | 10 | GND |
RX1BF! | 10 | GND | 11 | GND |
RX0BF! | 11 | GND | 12 | GND |
INT! | 12 | GND | 13 | GND |
SCK | 13 | Intermittent clocking | 14 | Same as BBoard |
NC | - | | 15 | GND |
MOSI | 14 | Intermittent data | 16 | Same as BBoard |
MISO | 15 | 3 short pulses | 17 | Same as BBoard |
CS! | 16 | 57.6kHz square | 18 | 38.9kHz square (!!!) |
Reset! | 17 | 5V | 19 | 5V |
Vdd | 18 | 5V | 20 | 5V |
Now here is the issue. The output data is messed up, and the CS pin seems to have a different speed between the Nano on breadboard (57.6kHz) and the ATMega2560 on PCB (38.9kHz). All the rest of the data on SPI looks about identical, down to the timing, so it's strange to me that just CS would have different timings. I'm not sure what's causing this.
Is this difference in CS pin timing a problem that could cause the corrupted output on the 2515? Or are there any other concerns I should have with my PCB application of the 2515/2551 vs. the working breadboard one?