Electronic – Getting no response from MCP2515 using SPI

avrcanspi

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 :)