8 years, 9 months ago.

With SPI, how do you read from slave?

Is there a way to read?

Thanks!

3 Answers

8 years, 9 months ago.

That seems reasonably straight forward.How do you configure the nucleo as slave?

The handbook has an example for SPI Slave code. See here. Make sure you use the correct SPIx NSS pin for the SPI port that you are using. Note that the SPI Master code can use any pin for CS, but the SPI slave needs to use a dedicated NSS pin.

posted by Wim Huiskamp 05 Aug 2015
8 years, 9 months ago.

Reading from SPI slaves works as usual: you write a dummy byte to the slave and the slave returns a value at the same time. Obviously, you need to connect the MISO pins and in most cases you first need to write some commands to the slave to select the correct internal register. For example when using the lpc1768 :

#include "mbed.h"
 
SPI spi(p5, p6, p7); // mosi, miso, sclk
DigitalOut cs(p8);
 
int main() {
// Select the device by setting chip select low
    cs = 0;
 
    // Send 0x8f, the command to read the WHOAMI register
    spi.write(0x8F);
 
    // Send a dummy byte to receive the contents of the WHOAMI register
    int whoami = spi.write(0x00);
    printf("WHOAMI register = 0x%X\n", whoami);
 
    // Deselect the device
    cs = 1;
}

8 years, 7 months ago.

I have a question about the SPI read from slave. My ADC has six channel, so I need 96 clock. I wonder that is my code as follows correct?

Serial pc(P0_2, P0_3); // tx, rx***

SPI spi(P2_27,P2_26, P2_22); // mosi, miso, sclk
DigitalOut reset(P5_2);
DigitalOut convst(P5_3);
DigitalIn busy(P5_4);
DigitalOut cs(P2_23);        // ssel


int main() {
	convst = 0;
	reset = 0;
            
    cs = 1; // Chip must be deselected

    spi.format(16,2); // Setup the spi for 8 bit data, high steady state clock,
    spi.frequency(1000000); // second edge capture, with a 1MHz clock rate
        reset = 1;
        wait_ns(50);
        reset = 0;

    while(1)
    {
    	convst = 1;
    	wait_ns(20);
    	while(busy != 0 );
		// Select the device by seting chip select low
	    cs = 0;
	    // Send 0x8f, the command to read the WHOAMI register
	    wait_ns(6);
	    signed short CH_A0 = spi.write(0x0000);
	    signed short CH_A1 = spi.write(0x0000);
	    signed short CH_B0 = spi.write(0x0000);
	    signed short CH_B1 = spi.write(0x0000);
	    signed short CH_C0 = spi.write(0x0000);
	    signed short CH_C1 = spi.write(0x0000);

        // Deselect the device
        cs = 1;
        convst = 0;
        wait_ns(40);
        pc.printf("SDO=%d,", SDO);
	    pc.printf("CH_A0 = %d, ", CH_A0);
	    pc.printf("CH_A1 = %d, ", CH_A1);
	    pc.printf("CH_B0 = %d, ", CH_B0);
	    pc.printf("CH_B1 = %d, ", CH_B1);
	    pc.printf("CH_C0 = %d, ", CH_C0);
	    pc.printf("CH_C1 = %d\r\n", CH_C1);

    }
}

In general, this should be the procedure. However, it all depends on the slave device. What ADC are you using? The ADC datasheet should provide all the necessary information regarding the sequence of commands and read/write operations. You may have to set some control registers first before the ADC does anything at all. You may also have to set a specific SPI format (# bits, clock phase, clockspeed..)

posted by Wim Huiskamp 02 Oct 2015

I am using ADS8556 in Hardware mode. The datasheet shows that in HW mode, SDI pin is connected to GND. That's what I confuse how can I read the data from it. ADS8556 Datasheet is over there: http://www.ti.com/lit/ds/symlink/ads8556.pdf I want to use LPC4088DM to control it. and my code is as follows: ----------------------

Serial pc(P0_2, P0_3); // tx, rx***
SPI spi(P2_27,P2_26, P2_22); // mosi, miso, sclk
DigitalOut reset(P5_2);
DigitalOut convst(P5_3);
DigitalIn busy(P5_4);
DigitalOut cs(P2_23);        // ssel

int main() {

	convst = 0;
	reset = 0;
    cs = 1;   // Chip must be deselected
    spi.format(16,2); // Setup the spi for 8 bit data, high steady state clock,
    spi.frequency(1000000); // second edge capture, with a 1MHz clock rate
    wait_ns(20);

    while(1)
    {
    	reset = 1;
    	reset = 0;
    	convst = 1;
    	wait_ns(20);

    	while(busy != 0 );

    		convst = 0;
    		wait_ns(6);
	    cs = 0;   // Select the device by seting chip select low
	    float CH_A0, CH_A1, CH_B0, CH_B1, CH_C0, CH_C1;

	    CH_A0 = spi.write(0x0000);
	    CH_A1 = spi.write(0x0000);
	    CH_B0 = spi.write(0x0000);
	    CH_B1 = spi.write(0x0000);
	    CH_C0 = spi.write(0x0000);
	    CH_C1 = spi.write(0x0000);

        cs = 1;  // Deselect the device

        wait_ns(40);

	    pc.printf("CH_A0 = %f, ", CH_A0);
	    pc.printf("CH_A1 = %f, ", CH_A1);
	    pc.printf("CH_B0 = %f, ", CH_B0);
	    pc.printf("CH_B1 = %f, ", CH_B1);
	    pc.printf("CH_C0 = %f, ", CH_C0);
	    pc.printf("CH_C1 = %f\r\n", CH_C1);

    }

}

------------------

Is anywhere need to modify, please let me know. Thank you very much

posted by Wei Chang Shen 02 Oct 2015

Please use <<code>> and <</code>> tags on separate lines around you posted code to keep it readable.

The device has many options. I assume you selected the serial mode (PAR/SER is high). In HW mode the SDI is at GND since you dont send any config data to the control register. All settings are defined by external pins. The SPI input on the mbed (MISO) should be connected to the ADC SDO_X. I suppose you have it set to SEL_A = 1, SEL B = SEL_C = 0 so that all outputs are routed to SDO_A (see fig 37). Did you use CONVST_A to activate all 6 ADCs or are all CONVST_X wired in parallel. Why do you store the results in a float. The 16 bit data is output as signed short. You dont need to use a reset inside the while loop. One reset before the loop should do it.

posted by Wim Huiskamp 05 Oct 2015

Thank you for answer my question. I'm using HW / serial mode now, and setting SEL_A = 1, SEL B = SEL_C = 0 already. Also the mbed(MISO) is connected to the ADC serial Control pin (SDO). And the CONVST_X are wired in parallel. I've modified the code float into signed short, and reset do one time before the loop. (The code that I've modify is as follows) Since the SDI at GND, so I don't send any config data to the control register. That's mean I can read data from MISO pin directly ?

Serial pc(P0_2, P0_3); // tx, rx***
 
SPI spi(P2_27,P2_26, P2_22); // mosi, miso, sclk
DigitalOut reset(P5_2);
DigitalOut convst(P5_3);
DigitalIn busy(P5_4);
DigitalOut cs(P2_23);        // ssel
 
 
int main() {
    convst = 0;
    reset = 0;
            
    cs = 1; // Chip must be deselected
 
    spi.format(16,2); // Setup the spi for 8 bit data, high steady state clock,
    spi.frequency(1000000); // second edge capture, with a 1MHz clock rate
        reset = 1;
        wait_ns(50);
        reset = 0;
 
    while(1)
    {
        convst = 1;
        wait_ns(20);
        while(busy != 0 );
        // Select the device by seting chip select low
        cs = 0;
        // Send 0x8f, the command to read the WHOAMI register
        wait_ns(6);
        signed short CH_A0 = spi.write(0x0000);
        signed short CH_A1 = spi.write(0x0000);
        signed short CH_B0 = spi.write(0x0000);
        signed short CH_B1 = spi.write(0x0000);
        signed short CH_C0 = spi.write(0x0000);
        signed short CH_C1 = spi.write(0x0000);
 
        // Deselect the device
        cs = 1;
        convst = 0;
        wait_ns(40);

        pc.printf("CH_A0 = %d, ", CH_A0);
        pc.printf("CH_A1 = %d, ", CH_A1);
        pc.printf("CH_B0 = %d, ", CH_B0);
        pc.printf("CH_B1 = %d, ", CH_B1);
        pc.printf("CH_C0 = %d, ", CH_C0);
        pc.printf("CH_C1 = %d\r\n", CH_C1);
 
    }
}
posted by Wei Chang Shen 06 Oct 2015