cancel
Showing results for 
Search instead for 
Did you mean: 

SPI: First byte of 16bit TX transfer is always 0

SFahr
Associate III

Sending display data to an ILI9341 via SPI. The ILI9341 needs 16bit words in BigEndian. When I convert the STM32 LittleEndian data to BigEndian and then send the data paket as 8bit bytes everything is fine. In order to save the conversion I tried to send the STM32 LittleEndian data as 16bit words. This works except for the very first byte of the paket: The SPI outputs always 0 for the first byte, after that everything is perfectly okay again. Reprocuded on STM32L432KC and STM32L45ZI. Any ideas?

1 ACCEPTED SOLUTION

Accepted Solutions
SFahr
Associate III

I start to believe that what I'm trying to do is not actually an official feature at all.

I'm feeding the SPI in 16bit mode from DMA in 8bit mode (sorry, I forgot to mention this, but I just realized it myself). While this does the intended byte swapping it is nowhere mentioned in the datasheets or examples, so I guess I'm using an unsupported mode and it's just dumb luck that is works somehow at all.

Thanks for your help!

View solution in original post

7 REPLIES 7

Perform a one-halfword write and show the resulting waveforms.

JW

TDK
Guru

Possibly a data packing issue? Show the code you're using to send out data. Simplify it as much as possible to isolate the problem.

If you feel a post has answered your question, please click "Accept as Solution".
SFahr
Associate III

I need to toggle between 8bit transfers (for the control registers of the ILI9341) and 16bit transfers (for the display data). So I write several control registers as 8bit, then switch to 16bit and transfer the data. I daresay that my data is correct (I verified by overwriting all display data with test patterns).

It appears like after switching to 16bit the very first byte is corrupted to zero. I checked with the scope, the output on MOSI it is actually 0x00.

The code basically looks like this:

if ((datasize16_b) && (hspi1.Init.DataSize != SPI_DATASIZE_16BIT))
{
	hspi1.Init.DataSize = SPI_DATASIZE_16BIT;
	MODIFY_REG(hspi1.Instance->CR2, SPI_CR2_DS_Msk, hspi1.Init.DataSize);
}
else if (hspi1.Init.DataSize != SPI_DATASIZE_8BIT)
{
	hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
	MODIFY_REG(hspi1.Instance->CR2, SPI_CR2_DS_Msk, hspi1.Init.DataSize);
}
      
SetOutput(chipSelect_s8, 0);
       
HAL_SPI_Transmit_DMA(&hspi1, data_pu8, numBytes_u16);

TDK
Guru

Keep transactions at 8 bits. You can send 16 bits by writing a half-word to DR.

If you feel a post has answered your question, please click "Accept as Solution".

SPI is complex and switching its settings while enabled (i.e. SPIx_CR1.SPE = 1) leads to unexpected effects. So I would try disabling/enabling SPI around any settings changes.

But it's probably simpler to do what TDK said above: stick to 8 bits and use data packing.

JW

SFahr
Associate III

I start to believe that what I'm trying to do is not actually an official feature at all.

I'm feeding the SPI in 16bit mode from DMA in 8bit mode (sorry, I forgot to mention this, but I just realized it myself). While this does the intended byte swapping it is nowhere mentioned in the datasheets or examples, so I guess I'm using an unsupported mode and it's just dumb luck that is works somehow at all.

Thanks for your help!

Interesting.

Thanks for coming back with the solution. Please select your post as Best so that the thread is marked as solved.

JW