SPI reading from slave


I have small question about how bytes move around during SPI reading.
I have a flash memory chip and microcontroller.
Suppose I want to know jedec data from the chip(although it can be any data, this is just example), I found how to do it and it works fine, but I don't get the part when we assign jedec parameters to variables.

From the C code below I can see the possible logic like this:
we send "retrieve jedec" command to chip, then for some reason we start to send zeros to assign values to variables, probably it reads the value by sending dummy-bytes. Question is – isn't it supposed to overwrite bytes we are reading?
I mean – you shift something to the register you want to read therefore you get the value back by replacing it with what you have sent.

Maybe I express my question blurry, ask more info if you are confused, but to sum up everything I have two questions:
1. Why we are sending zeros during value assignments like *b1 = SPI_MasterTransmit(0);
2. If we do it to shift the value from slave device to master – why don't we erase the value from the slave by doing this?

enter image description here

void get_jedec_id(uint8_t *b1, uint8_t *b2, uint8_t *b3) {  
    PORTB |= 1<<PINB2; // turn high ss pin(/cs)
    PORTB &= ~1<<PINB2; // turn low ss pin(/cs)
    SPI_MasterTransmit(0x9F); // transmit get_jedec command of this chip
    *b1 = SPI_MasterTransmit(0); // manufacturer id
    *b2 = SPI_MasterTransmit(0); // memory type
    *b3 = SPI_MasterTransmit(0); // capacity
    PORTB |= 1<<PINB2;

SPI_MasterTransmit code:

unsigned char SPI_MasterTransmit(uint8_t outData)
// Transmission start
SPDR = outData;
// Waiting for transmission to end
while(!(SPSR & (1<<SPIF))) ;
return SPDR; // return received byte

Best Answer

SPI is a full-duplex protocol. In order to receive data, you have to send data at the same time, even though the Flash chip might do nothing with the data that you send.

So, for example, you want to read the JEDEC ID. You lower the /CS signal and send the "read JEDEC ID" command. That command instructs the Flash chip to "send your JEDEC ID and do nothing with any other data that you receive". You keep sending data (which is all zeroes and will be ignored anyway), and as you do so it sends you back its JEDEC ID - you get back one byte of JEDEC ID for each zero byte that you send. When you raise /CS at the end of the transaction, that resets the Flash chip's controller.

Related Topic