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-24 06:29 PM
hi -
working! not sure why this does not work:
HAL_SPI_TransmitReceive(&hspi3, txData, rxData, 7, HAL_MAX_DELAY);
But no matter because this does!
HAL_SPI_Transmit(&hspi3, txData, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi3, rxData, 7, HAL_MAX_DELAY);
But I think the big think from this is the "multi-byte" bit 0x40 that has to be set in addition the the read bit 0x80 with the target register.
Thanks again.
Gary
2024-08-24 01:17 PM
Might suggest using the HAL_SPI_TransmitReceive to ensure data order and flag checking/clearing
View signals with scope or analyzer to confirm states, ordering and timing.
2024-08-24 01:31 PM
Tesla DeLorean-
Thanks for feedback. Same wrong data. I've looked at this before on scope, signals seems OK. It's a bit of a pain on a 2 chn scope as I can't trigger on CS while watching TX,RX. 8--( But the signals were clean enough with no obvious problems.
The rest of the ADXL device works with no issues. Just this multi-byte read is being difficult. Project uses a rather slow main clock (4MHz) and using a prescaler of 2 on SPI (2Mbits baud)
2024-08-24 02:46 PM
hi tesla delorean,
after going through the datasheet I have found the probable issue. it seems that when writing the address register, two bits need to be set on a read. The first is bit 8, and the other is bit 7 for "multibyte". now the write value is
address = ADXL313_REG_DATAX0 = 0x32
then: txData[0] = ADXL313_REG_DATAX0 | 0x80 | 0x40 which results in a value of 0xF2
But still the values are incorrect. I've checked the data sheet for other issues but can see nothing suspicious.
2024-08-24 03:33 PM - edited 2024-08-24 03:53 PM
Double check that behavior of the CS waveform matches the expectations of chip. Some chips require CS not be toggled between bytes, some require the opposite ("framing").
Also double check that you are meeting the timing requirements on the CS signal. Chips have expectations re minimal pulse duration and perhaps its timing relative to surrounding data bits.
2024-08-24 03:43 PM
Thanks for this information, I will review the data sheet. But since it works well enough reading single registers do you believe this is still possible possible regarding the CS? One would think that behavior of CS with respect to all R/W operations should be uniform..?
2024-08-24 03:54 PM - edited 2024-08-24 03:54 PM
I'll agree that I could be wrong, if you'll agree to check if I am. :)
2024-08-24 06:18 PM
Hehe, that's a sly way of telling me to do some homework...game on! Thanks. Will let you know what I find.
2024-08-24 06:29 PM
hi -
working! not sure why this does not work:
HAL_SPI_TransmitReceive(&hspi3, txData, rxData, 7, HAL_MAX_DELAY);
But no matter because this does!
HAL_SPI_Transmit(&hspi3, txData, 1, HAL_MAX_DELAY);
HAL_SPI_Receive(&hspi3, rxData, 7, HAL_MAX_DELAY);
But I think the big think from this is the "multi-byte" bit 0x40 that has to be set in addition the the read bit 0x80 with the target register.
Thanks again.
Gary
2024-08-24 08:04 PM - edited 2024-08-25 09:53 AM
Those two pieces of code are not at all equivalent, since SPI is intrinsically Full-Duplex.
TransmitReceive does the write and read simultaneously (think two shift registers clocking in data at the same time, one from MOSI and the other from MISO). This involves 8 clock cycles on SCLK overall.
Transmit+Receive first writes a byte via MOSI (while ignoring bits incoming on MISO), then reads a new byte from MISO (while sending dpn't-care values on MOSI). This involves 8+8=16 clock cycles on SCLK overall.