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!

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

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

 

View solution in original post

12 REPLIES 12

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..


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)

 

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.

 

BarryWhit
Lead II

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.

- 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.

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..?

BarryWhit
Lead II

I'll agree that I could be wrong, if you'll agree to check if I am. :)

- 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.

Hehe, that's a sly way of telling me to do some homework...game on! Thanks. Will let you know what I find.

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

 

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.

 

 

- 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.