I have a board with a working SPI interface. I can read one slave via the SPI interface successfully.
When I try to read data or get a status on a secondary slave, the MCP2515 IC, I'm not getting any response. I have verified the connections by using a voltmeter continuity test, I have verified the ground and voltage connections to the IC. I understand that the MCP2515 is unique in how it initializes at start-up per the datasheet. I have tried numerous initialization sequences with no success. I am beginning to think I have a bad IC, but I would like to be able to test it and prove that theory.
The only other issue I can think of is a possible clocking issue. I have a 16 MHz crystal on the MCU and a 16 MHz crystal on the MCP2515 per the datasheet. Both have 22 pF capacitors. If the clocking is off, I think I would at least get garbage. Can someone look at the code and validate it looks good and that I do in fact have a clocking or hardware issue?
bool mcp2515_init(void)
{
char str[80];
unsigned int test_value;
SET(MCP2515_CS);
SET_OUTPUT(MCP2515_CS);
SET(USB_CS);
//SET_OUTPUT(USB_CS);
SET(SD_CS);
//SET_OUTPUT(SD_CS);
RESET(P_SCK);
RESET(P_MOSI);
RESET(P_MISO);
SET_OUTPUT(P_SCK);
SET_OUTPUT(P_MOSI);
SET_INPUT(P_MISO);
SET_INPUT(MCP2515_INT);
SET(MCP2515_INT);
// Active SPI master interface
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
SPSR = 0;
// Reset MCP2515 by software reset.
// After this it is in configuration mode.
RESET(MCP2515_CS);
spi_putc(SPI_RESET);
SET(MCP2515_CS);
// Wait a little bit until the MCP2515 has restarted
_delay_us(15);
// Load CNF1..3 Register
RESET(MCP2515_CS);
spi_putc(SPI_WRITE);
spi_putc(CNF3);
spi_putc((1<<PHSEG21)); // Bitrate 125 kbps at 16 MHz
spi_putc((1<<BTLMODE)|(1<<PHSEG11));
spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0));
// Activate interrupts
spi_putc((1<<RX1IE)|(1<<RX0IE));
SET(MCP2515_CS);
test_value = mcp2515_read_register(CANCTRL);
sprintf(str, "test value is [%d]\n\n",test_value);
UART1_TxString(str);
// Test if we could read back the value => is the chip accessible?
if (mcp2515_read_register(CNF1) != ((1<<BRP2)|(1<<BRP1)|(1<<BRP0))) {
return false;
}
// Deactivate the RXnBF pins (high impedance state)
mcp2515_write_register(BFPCTRL, 0);
// Set TXnRTS as inputs
mcp2515_write_register(TXRTSCTRL, 0);
// Turn off filters => receive any message
mcp2515_write_register(RXB0CTRL, (1<<RXM1)|(1<<RXM0));
mcp2515_write_register(RXB1CTRL, (1<<RXM1)|(1<<RXM0));
// Reset device to normal mode
mcp2515_write_register(CANCTRL, 0);
return true;
}
Best Answer
After many hours of debugging and testing the circuit, I finally found the issue being tied to the RESET PIN on the MCP2515. I misunderstood the datasheet thinking that the RESET PIN could be floating and that I could use software RESET in its place. That is NOT the case. The RESET PIN must be terminated with a pull up resistor OR tied to the RESET circuit of your MCU. I chose the PULL-UP resistor option. This prevents the MCP2515 from being stuck/hung in the RESET mode. After adding the pull-up to the circuit, I am now able to communicate with the MCP2515. It would be nice if the datasheet had a section of "Minimum Required PINS" like some datasheets have. Hope this helps someone else by making sure all the required PINS are terminated before coding :)