2024-08-24 01:12 PM - edited 2024-08-24 01:16 PM
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!
Solved! Go to Solution.
2024-08-25 06:51 AM
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!
2024-08-25 10:03 AM - edited 2024-08-25 10:08 AM
@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).
2024-08-25 11:34 AM
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.