Reputation: 169
I have a question about SPI bus. I often see in some libraries that I found, but I can't understand how it works.
Quick examples from one library I found. Writing by SPI:
static void nRF24_WriteRegister(uint8_t reg, uint8_t val)
{
uint8_t tmp[2];
tmp[0] = NRF24_CMD_W_REGISTER | reg;
tmp[1] = val;
NRF24_CSN_LOW;
nRF24_SendSpi(tmp, 2);
NRF24_CSN_HIGH;
}
How it works, if we are putting to the same frame register(which we are writing to) and data to this register?
But even more confusing for me is reading from SPI:
static uint8_t nRF24_ReadRegister(uint8_t reg)
{
uint8_t result;
reg = NRF24_CMD_R_REGISTER | reg;
NRF24_CSN_LOW;
nRF24_SendSpi(®, 1);
nRF24_ReadSpi(&result, 1);
NRF24_CSN_HIGH;
return result;
}
Why do we have to send first some info and then read?
Upvotes: 1
Views: 4413
Reputation: 93476
In may respects your question is about the behaviour of a specific device rather than SPI in general. However to first answer:
Why do we have to send first some info and then read?
The "info" you are sending in this case is a command specifying which register to read.
SPI is a "Master/Slave" communication interface. A slave device cannot on its own initiate communication. SPI devices comprise of a shift register. On a clock edge, one bit is shifted into the register from MOSI (Master-Out/Slave-In), and one bit is shifted out of the register on to MISO (Master-In/Slave-Out). The master drives the clock, so to read from a device, the master must clock data into the device in order for data to be output from the device. This is intrinsically a "duplex" operation (i.e. data is input and output simultaneously. Even of you only want to read, you have to write and often this is done by sending "dummy" data on MOSI.
So in your second fragment: NRF24_CMD_R_REGISTER | reg
is a command to read the register index reg
. The data output will be whatever was in the shift register when the command was sent, so will not be the result of the actual read because that command has not yet been received. When the device receives the complete command, it will load the shift register with the value in the register reg
, and then the data must be read by a second bus operation which will clock dummy data onto MOSI in order to retrieve the result of the read instruction from MOSI.
With respect to:
How it works, if we are putting to the same frame register(which we are writing to) and data to this register?
In the associate fragment, the first byte containing: NRF24_CMD_W_REGISTER | reg
is a command that says: write the following byte value to register reg
. The second byte containing val
is the data to be written to reg
. When nRF24_SendSpi(tmp, 2);
called both bytes are sent on MOSI by clocking the teh SCLK line 16 times.
Attribution CBurnett from https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#/media/File:SPI_8-bit_circular_transfer.svg
Upvotes: 2
Reputation: 7057
The SPI device contains a set of registers. Each register has an address and a value. The register values may be read and/or written by the master. The SPI device needs to know which register address the master is reading/writing. So the protocol is that the master first writes the register address, then subsequently reads/writes the register value. See the device datasheet for details about the available registers and the read/write protocol.
In your first example, nRF24_SendSpi(tmp, 2);
writes two bytes, first the register address and then the register value.
In your second example, nRF24_SendSpi(®, 1);
writes one byte, the register address. Then nRF24_ReadSpi(&result, 1);
reads one byte, the register value.
If the protocol did not start with writing the register address, then the SPI device would not know which register the master is trying to read/write.
Upvotes: 2
Reputation: 67546
SPI slave does not generate the clock signal, only master. So Slave to transmit anything needs the clock signal from the Master. That is the reason why the Master has to send dummy data - to generate the clock signal for the Slave.
Upvotes: 2