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

SPI master cannot receive SPI slave response

Hi DevZone, 

I am modifying an CAN library for nRF52840 preview DK. In my project, nRF52 preview DK is working as a SPI master and Arduino CAN Bus Shield is working as a SPI slave.

Before starting test with Arduino CAN Bus shield, I test it with an Arduino UNO board, a simple Arduino SPI slave program is run on the Arduino UNO board. 

It seems the Arduino UNO board correctly receive the data from nRF DK, but nRF DK could not receive the response from Arduino UNO.

In nRF52 DK program, function mcp2515_readStatus(void) is  is called periodically,

    uint8_t mcp2515_readStatus(void) 
    {
        uint8_t i;
        uint8_t dummy_receive;
        spi_send_recv(SPI_MASTER_0, 0xA0, dummy_receive, 1);
        nrf_delay_ms(50);
        spi_send_recv(SPI_MASTER_0, 0x00, i, 1);
        nrf_delay_ms(50);
    
        return i;
    }

where spi_send_recv() is defined as:

static void spi_send_recv(const nrf_drv_spi_t spi_master_instance, uint8_t p_tx_data, uint8_t p_rx_data,const uint16_t len)
{
    uint8_t tx_data = p_tx_data;
    uint32_t err_code = nrf_drv_spi_transfer(&spi_master_instance, &tx_data, len, &p_rx_data, len);
}

In Arduino UNO, the SPI slave code is as below:

// Include SPI (Serial Peripheral Interface) library. Does not support SPI Slave.
#include <SPI.h>
boolean SSlast = LOW; // SS last flag.
const byte led = 9; // Slave LED digital I/O pin.
boolean ledState = HIGH; // LED state flag.
const byte cmdBtn = 1; // SPI cmdBtn master command code.
const byte cmdLEDState = 2; //

//Initialize SPI slave.
void SlaveInit(void) {
   // Initialize SPI pins.
   pinMode(SCK, INPUT);
   pinMode(MOSI, INPUT);
   pinMode(MISO, INPUT);
   pinMode(SS, INPUT);
   // Enable SPI as slave.
   SPCR = (1 << SPE);
}

// SPI Transfer.
byte SPItransfer(byte value) {
   SPDR = value;
   while(!(SPSR & (1<<SPIF)));
   return SPDR;
}

void setup() {
   Serial.begin(9600);
   digitalWrite(led, ledState);
   SlaveInit();
}
   
void loop() {
   if (!digitalRead(SS)) {
    if (SSlast != LOW) {
    pinMode(MISO, OUTPUT);
    Serial.println("***Slave Enabled.");
    SSlast = LOW;
    }
    byte rx = SPItransfer(255);
    Serial.println("Initial -1 slave response code sent");
    Serial.println("rx:" + String(rx) + "."); 
   }
   else {
    if (SSlast != HIGH) {
    pinMode(MISO, INPUT);
    Serial.println("Slave Disabled.");
    SSlast = HIGH;
    }
    SPDR = 0;
   }
}

When I run nRF DK and Arduino the log is as below:

nRF 52 DK log:

tx data A0
Transfer Complete!
rx data 0
tx data 0
Transfer Complete!
rx data 0

The Arduino log:

***Slave Enabled.
Initial -1 slave response code sent
rx:160.
Slave Disabled.
***Slave Enabled.
Initial -1 slave response code sent
rx:0.
Slave Disabled.

My questions are:

1) Could you please help find the reason causing nRF52 DK cannot receive the response from Arduino? I have check the connection cable, there is no problem...

2) Does nrf_drv_spi_transfer function automatically set SS PIN when it is called? From Arduino log, I find the SS PIN is disable and enable for every time nrf_drv_spi_transfer function is called...

The real scenario looks like: SS enable (set Low)-> SPI Master send 0xA0 (DEC: 160) ->SS disable(Set High)->SS enable(Set Low) -> SPI Master send 0x00 -> SS disable(Set High),

But the scenario I expect is: SS enable (set Low)-> SPI Master send 0xA0 (DEC: 160) -> SPI Master send 0x00 -> SS disable(Set High).

How can I realise the scenario that I expect?

Thanks 

Related