This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52832 SPI with MCP2515: nrf_drv_spi_transfer seems to send properly, but not receiving in all cases.

Hi, 

I'm trying to use the nrf_drv_spi.c to communicate with a BL652 + MCP2515 CAN SPI custom device. I've connected the MCP2515 to the nRF52832 (BL652 module) in the following way with SCLK = P0.25, SPI_MISO_PIN = P0.24, SPI_MOSI_PIN = P0.23 and SPI_SS_PIN = P0.05 and a 16MHz resonator. I've tested the power and the osc clock signal. Both of these test out fine with my oscilloscope.

I've taken the following arduino .cpp code and started modifying to work with the nRF52832 and the nrf_drv_spi driver. https://github.com/Seeed-Studio/CAN_BUS_Shield/blob/master/mcp_can.cpp. Most functions are commented out presently as I'm trying to get the basics to work.

The attached is my main.c, mcp_can.c, mcp_can.h and mcp_can_dfs.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
mcp2515_can.c
mcp_can.h
2012 Copyright (c) Seeed Technology Inc. All right reserved.
Author:Loovee (loovee@seeed.cc)
2014-1-16
Contributor:
Cory J. Fowler
Latonita
Woodward1
Mehtajaghvi
BykeBlast
TheRo0T
Tsipizic
ralfEdmund
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

mcp_can.h

mcp_can_dfs.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I've modified for this use case. The only thing I've been able to "maybe" get working is my mcp2515_readStatus(); function. This returns 0x92 (I can't tell if that is a valid response or not since the device really isn't initialized yet).

I've been trying to get my mcp_can_begin(CAN_500KBPS, MCP_16MHz) with it only returning a MCP2515_FAIL. I've tried many different ways to use the nrf_spi_drv for the SPI bus including the mcp2515_spi_transfer function (I could never get anything back with this). Presently I'm trying the following method (directly call nrf_drv_spi_transfer vs call in a separate function) for any of the base commands that the MCP2515 uses (see image). When I put an oscilloscope on I see the CS, CLK, and MOSI just fine. I never see anything on the MISO line (even when I get 0x92 back).

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*********************************************************************************************************
** Function name: mcp2515_readRegister
** Descriptions: read register
*********************************************************************************************************/
uint8_t mcp2515_readRegister(const uint8_t address)
{
//uint8_t ret;
//MCP2515_SELECT();
uint8_t m_tx_buf[] = {MCP_READ, address};
uint8_t m_rx_buf[sizeof(MCP_READ_STATUS) + 1];
uint8_t m_length = sizeof(m_tx_buf);
memset(m_rx_buf, 0, m_length);
spi_xfer_done = false;
APP_ERROR_CHECK(nrf_drv_spi_transfer(&can_spi, m_tx_buf, m_length, m_rx_buf, m_length));
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I've looked at the following messages and tried to implement the solutions, but none of the suggestions fix anything (unless I'm implementing them wrong).

1. https://devzone.nordicsemi.com/f/nordic-q-a/9353/mcp2515-with-nrf51-dk

2. https://devzone.nordicsemi.com/f/nordic-q-a/30949/how-use-nrf5-sdk14-2-0-spi-driver-functions

3. https://devzone.nordicsemi.com/f/nordic-q-a/45727/nrf52810-spi-and-duration-of-cs-after-last-byte-transferred

To me it seems like my device either has a hardware issue and won't/cannot respond or the SPI implementation for reading back is incorrect. The one thing that leads me to think this I when I use the oscilloscope I cannot see anything on the MISO line. 

Based on all of the above information. Is there anything wrong that I'm doing when utilizing SPI? Or does it look like anything with the hardware is wrong? Does anyone have anything that might help me figure this out?

Thanks! 

  • SPI Modes 0,0 (Mode 0) or 1,1 (Mode 3) both work on the MCP2515, but the initialisation code above has Mode 2 (NRF_DRV_SPI_MODE_2). I would suggest first try changing this to NRF_DRV_SPI_MODE_0 or NRF_DRV_SPI_MODE_3.

    The Reset capacitor seems very large at 10uF. given that only a minimum of 2uSec reset is required, although no max is quoted; unless the VDD rise time is extremely slow it might be wise to reduce that somewhat. 100nF might be a better choice. However that's unlikely to be an issue with the SPI.

    The read command (if Read Instruction) seems to be 1 byte short, though it's not clear which command is in the code. The 3-byte transfer is <instruction><address><response>. If that was meant to be Read Rx Buffer, only 2 bytes <instruction><response>, then the address would not be part of the tx.

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    uint8_t mcp2515_readRegister(const uint8_t address)
    {
    uint8_t m_tx_buf[] = {MCP_READ, address};
    uint8_t m_rx_buf[3]; // not sure what MCP_READ_STATUS is: sizeof(MCP_READ_STATUS) + 1];
    uint8_t m_tx_length = sizeof(m_tx_buf);
    uint8_t m_rx_length = sizeof(m_rx_buf);
    memset(m_rx_buf, 0, m_rx_length);
    spi_xfer_done = false;
    APP_ERROR_CHECK(nrf_drv_spi_transfer(&can_spi, m_tx_buf, m_tx_length, m_rx_buf, m_rx_length));
    while (!spi_xfer_done)
    {
    __WFE();
    }
    return m_rx_buf[2]; // was 1, require 3rd byte
    }
    STATIC_ASSERT(m_rx_length == 3);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Hi, 

    Thanks for the response. I have tried modes 0 through 3 earlier with no results. I just tried again, but the initialization still fails. Interestingly enough regardless of SPI_MODE, the response I get for mcp2515_readStatus() is always 0x92. 

    Good point on the reset capacitor. I'll have to test that in a moment. 

  • On another note I just tried your newest response with the read command being 1 byte short. That was exactly the problem for the initialization! 

    Much appreciated, now I can work on getting some messages flowing. 

    Thanks!

  • If you are not usisng SES. This is a much better driver.  Works with 100s of devices and sensors. https://github.com/IOsonata/IOsonata/blob/master/ARM/Nordic/src/spi_nrf5x.cpp

  • Presently I'm using SES. But if I move away from it in the future, I'll have to look at it. Thanks!