cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to perform multi-byte SPI; Single OK

roger99
Associate III

Hello -

Board - STM32 NUCLEO-L476G

Peripheral board ADXL313 (16 byte data registers)

Interface - SPI

I  can perform single byte read, combine the 2, 8 bit values and the data is correct. Yet, when I try to perform a 2 byte SPI read, it's garbage.

This works:

uint8_t ADXL313_ReadRegister(uint8_t reg)
{
uint8_t rxData[1];
uint8_t txVal[1];
txVal[0] = (reg | 0x80);
ACC_CS_ASSERT();  // low
HAL_SPI_Transmit(&hspi3, txVal, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi3, rxData, 1, HAL_MAX_DELAY);
ACC_CS_DEASSERT(); //high

return rxData[0];
}

int16_t ADXL313_ReadDataRegister( uint8_t reg)
{
uint8_t data0 = ADXL313_ReadRegister(reg);
reg += 1;
uint8_t data1 = ADXL313_ReadRegister(reg);
return (int16_t)((data1 << 8  | data0 );
}

Using above data values are correct when doing to separate 1 byte reads and combining

But this...does NOT work:

void ADXL313_ReadDataRegister(int16_t *data)
{
uint8_t txData[1];
uint8_t rxData[2];

txData[0] = ADXL313_REG_DATAX0 | 0x80; // 0x80 to indicate read operation

ACC_CS_ASSERT(); //low
HAL_SPI_Transmit(&hspi3, txData, 1, HAL_MAX_DELAY);

HAL_SPI_Receive(&hspi3, rxData, 2, HAL_MAX_DELAY); //set for 2 byte read
ACC_CS_DEASSERT(); //high

// Combine 2 registers for data
*data = (int16_t)((rxData[1] << 8  | rxData[0]);   //DATA IS NOT GOOD
}

Can someone provide feedback on what the issue might be?

Thanks!

 

 

 

12 REPLIES 12

BarryWhit -

Very useful and productive pieces of information. It seems like the authors of the SPI interface knew that some manufactures needed their interface to be accessed a specific way, hence two ways to do that. I was actually using the separate calls earlier but switched to the single call after looking at some example code. (almost non-existent for this device) Then I discovered the write bit issue in the datasheet. Had I found the write bit issue first it would have worked. There's a lot of detail in those and sometimes easy to overlook.

Just goes to show you...RTFM...read the "Fine" manual! (maybe twice)

Thanks!

 


@roger99 wrote:

BarryWhit -

Very useful and productive pieces of information. It seems like the authors of the SPI interface knew that some manufactures needed their interface to be accessed a specific way, hence two ways to do that. 


Not really. There's no way for the device to respond to a command until that command has been received and processed. So for command/response it's normal for the host to first send, then receive. Sometimes (like high-speed reads from flash chips) the datasheet/device protocol dictates that the master must send the command, then send a dummy byte, and only then start reading back data - to give the device enough time to prepare. SPI is just a bus protocol, the comms that take place on top of it usually follow an extra layer of protocol, defined by the device's manufacturer.

In other contexts, both the master and slave have data independently available at the same time (think for example of a  headset's audio codec simultaneously capturing and sending audio). In which case, it's useful to have data flowing in both directions at the same time.

 

The confusion you fell into arises from the device level protocol being half-duplex, layered on top of a full-duplex SPI bus. This state of affairs is quite common, but can still be confusing for newcomers. (There's also a half-duplex variant of SPI, with one data wire, but it's much rarer).

 

- If someone's post helped resolve your issue, please thank them by clicking "Accept as Solution".
- Please post an update with details once you've solved your issue. Your experience may help others.

Yes, yes, and yes. But the combined HAL_SPI_TransmitReceive works on everything else in accessing all the other  ADXL313 registers, so clearly it's a combined HD/FD device, depending on what you are doing.