cancel
Showing results for 
Search instead for 
Did you mean: 

SPI writing - 1 bit off

jagauthier
Associate III

I have a peripheral I am communicating to using both a Raspberry Pi and also STM32G0B1 (two different devices, two different setups)

I am basically trying to reproduce successful communications that the Pi us doing to this peripheral on the STM32 platforms. I am having some strange results.

The CS line seems to be going low or high, too early/late causing bits to be read that shouldn't be there.

I'm sending 3 separate frames. 4 bytes, 10 bytes, 1 byte. There is no input being read, so those lines can be ignored.

Below I am showing the output comparisons between the RPi and STM32.

The graphs below show the following signals:

SDO

SDI <-- no traffic on any signal

CS

CLK

4 bytes frame on Rpi, matches code:

0693W00000NsUrZQAV.png 

4 bytes on STM32 (should match above):

0693W00000NsUreQAF.png 

It can be seen that it appears the bits are shifted 1 to the left here.

The 10 byte frame:

0693W00000NsUrjQAF.pngSame again with the STM32:

0693W00000NsUroQAF.png 

The final frame is a single byte, the number '8'

On the Rpi it looks like this:

0693W00000NsUs3QAF.pngThe STM32 reads this as 11

0693W00000NsUsDQAV.png 

Here it looks like the CS line line stay low for too long causing a 1 to be read, where in the RPI it can be seen that CS goes high right at the end of the last byte.

My code uses the HAL libraries and the sending function is simple:

void spi_transfer(uint8_t board, uint8_t *pData, uint16_t Size) {
 
	HAL_StatusTypeDef  status;
	HAL_GPIO_WritePin(SPI_CE0_GPIO_Port, SPI_CE0_Pin, GPIO_PIN_RESET);
	status = HAL_SPI_Transmit(&hspi1, pData, Size, 100);
	HAL_GPIO_WritePin(SPI_CE0_GPIO_Port, SPI_CE0_Pin, GPIO_PIN_SET);	
	if (status != HAL_OK) {
		serprintf("Error writing to SPI on board: %i. (%i)\n\r", board, status);
	}
	
}

I've experimented with the clock speed, and some other settings. But nothing seemed to help.

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 7;
  hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

Thanks for any tips

1 ACCEPTED SOLUTION

Accepted Solutions

There are 4 SPI modes, set by 2 bits, traditionally called CPOL and CPHA. Read the SPI chapter in RM.

You set them

hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

i.e. CPOL=0, CPHA=0, and the SPI waveform conforms that.

The RPi waveform does not conform that, it is obviously CPOL=0 CPHA=1, and the LA is set to this mode, too.

0693W00000Nsd9lQAB.png 

JW

View solution in original post

5 REPLIES 5

Increase SCK pin's drive ​in GPIO_OSPEEDR.

JW​

Thanks. I've tried to change the PIN speed to all possibilities:

 00 2 MHz (low)

 01 25 MHz (medium)

 10 50 MHz (high)

 11 100 MHz (very high)

Using just the final frame as an example, I can see that there wasn't a noticeable change.

0693W00000Nsc8NQAR.png 

There are 4 SPI modes, set by 2 bits, traditionally called CPOL and CPHA. Read the SPI chapter in RM.

You set them

hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

i.e. CPOL=0, CPHA=0, and the SPI waveform conforms that.

The RPi waveform does not conform that, it is obviously CPOL=0 CPHA=1, and the LA is set to this mode, too.

0693W00000Nsd9lQAB.png 

JW

Interesting. Thanks for that. I should have drawn the lines, but I wasn't aware of workings of CPOL and CPHA. Confirmed that with my Logic Analyzer setting CPOL=0 and CPHA=1 decodes the Rpi. Setting CPOL=0 and CPHA=0 properly decodes the SPI.

Now to properly communicate to the peripheral I am not sure if I need CPHA=1 or not. I am going to set up my logic analyzer to determine that but need to rewire some things.

Want to close the loop on this for anyone who finds this thread in the future. The above issue is a decoding issue. The difference between the RPI and the STM32 is in fact the CPHA being set to 1 vs 0 (RPI vs STM32)

Once I set the decoder correctly the data was accurate.

I also had to set CPHA to 1 in my code in order to communicate with the peripheral correctly.