cancel
Showing results for 
Search instead for 
Did you mean: 

SPI debug for mode 1 on STM32G4 using HAL APIs

newbie_stm32
Associate III

Hi Community, I recently worked on SPI in mode 1 and observed some miscellaneous behavior. Can anyone please confirm the configurations made to work with mode 1 are proper? 

And when I use Hardware NSS Signal to Hardware NSS Output Signal there is no proper signaling (high at idle low when sending data) on SPI2_NSS even after setting pull-up in the GPIO Settings. So setting it up as GPIO_Output and controlling manually.

Please find the sample test code below

 

uint16_t tx_data = 0x25A5; // 0b 0010 0101 1010 0101
uint16_t rx_data = 0;

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi2, (uint8_t*) &tx_data, (uint8_t*) &rx_data, sizeof(tx_data), 10);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);

 

newbie_stm32_2-1687412040134.png

newbie_stm32_3-1687412076515.png

newbie_stm32_1-1687411306419.png

Please find the captured signal

newbie_stm32_4-1687412780488.png

Signal definition:

SignalPurpose
RedNSS (Controlled manually)
GreenSCK
BrownMOSI

The captured signal is wrong. The first data bit from the left should be 0 but is 1. In mode 1 raising edge of the SCK should alter the data bit and in falling edge should latch it.

The discussion points are:

  • Why hardware NSS is not working? Is wrongly configured?
  • Is SPI set to work in mode 1?

 

8 REPLIES 8
newbie_stm32
Associate III

Hi Community,

I was able to resolve the issue and found answers to my own question except for one

Why hardware NSS is not working

As we closely observe the data being sent is byte swapped. So swapping bytes while sending and after receiving solved the problem.

But not clear why it is sending 0xA5 first followed by 0x25 although it is configured to send MSB first.

Can anyone help me to understand this? Thank you.

Hi,

STM32 is little endian, that means that in memory, tx_data is stored as this:

AdressContent
rx_data0xA5
rx_data + 10x25

When you call HAL_SPI_TransmitReceive with rx_data address, it send first content of rx_data, then content of rx_data + 1, so 0xA5, then 0x25.

`

 

newbie_stm32
Associate III

Hi @Patricklaf ,

It is mentioned in the stm32g4xx_hal_spi.h that SPI_NSS signal will be enabled only if CPHA = 0. But in my case, it is 1. So why can't NSS isn't going to work in this case?

newbie_stm32_0-1689050948187.png

 

Hello @newbie_stm32 ,

Can you please share the SPI settings you set for mode1 (CPOL=0;CPHA=1). I'm not able to identify the issue because of which I'm not able to communicate with SPI slave.

I'm using STM32H723 with a SPI slave AD5293 (digital pot). AD5293 follows SPI protocol with CPOL=0;CPHA=1. Here is the screenshot of my SPI settings in CubeMX.
Screenshot from 2024-04-25 11-46-18.png

Note: I referenced the settings from another answer from STM forum where I found the following image - 

0693W00000WKsL6QAL.png

 

Also the slave I'm using communicates 16-bit data. Hence, I'm sending data in the following manner:

        // Step 1
	_shift_register.bytes = 0x1802;

	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 0);
	HAL_Delay(10);
	printf("shift register contents: %x\r\n", _shift_register.bytes);
	printf("SPI transmit return: %d\r\n", HAL_SPI_Transmit(&hspi1, (uint8_t*)(&_shift_register.bytes), 2, 0xFF));
	HAL_Delay(5);
	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 1);

	HAL_Delay(100);
	printf("DEBUG: Step 1 complete\r\n");

	// Step 2
	_shift_register.bytes = 0x0500;

	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 0);
	HAL_Delay(10);
	printf("shift register contents: %x\r\n", _shift_register.bytes);
	printf("SPI transmit return: %d\r\n", HAL_SPI_Transmit(&hspi1, (uint8_t*)(&_shift_register.bytes), 2, 0xFF));
	HAL_Delay(5);
	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 1);

	HAL_Delay(100);

//	printf("SPI receive return: %d\r\n", HAL_SPI_Receive(&hspi1, (uint8_t*)(&data_to_receive), 2, 10));
//	printf("Return SDO output: %x\r\n", data_to_receive);
	printf("DEBUG: Step 2 complete\r\n");

	// Step 3
	_shift_register.bytes = 0x0800;

	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 0);
	HAL_Delay(5);
	printf("shift register contents: %x\r\n", _shift_register.bytes);
	printf("SPI transmit return: %d\r\n", HAL_SPI_Transmit(&hspi1, (uint8_t*)(&_shift_register.bytes), 2, 0xFF));
	HAL_Delay(5);
	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 1);

	HAL_Delay(100);

//	printf("SPI receive return: %d\r\n", HAL_SPI_Receive(&hspi1, (uint8_t*)(&data_to_receive), 2, 10));
//	printf("Return SDO output: %x\r\n", data_to_receive);
	printf("DEBUG: Step 3 complete\r\n");


	// Step 3
	_shift_register.bytes = 0x0000;

	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 0);
	HAL_Delay(5);
	printf("shift register contents: %x\r\n", _shift_register.bytes);
	printf("SPI transmit return: %d\r\n", HAL_SPI_Transmit(&hspi1, (uint8_t*)(&_shift_register.bytes), 2, 0xFF));
	HAL_Delay(5);
	HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 1);

	HAL_Delay(100);

//	printf("SPI receive return: %d\r\n", HAL_SPI_Receive(&hspi1, (uint8_t*)(&data_to_receive), 2, 10));
//	printf("Return SDO output: %x\r\n", data_to_receive);
	printf("DEBUG: Step 4 complete\r\n");

 I'm sure this is a problem with the SPI communication. HAL_SPI_Transmit and HAL_SPI_Receive functions both return HAL_OK which makes this even more difficult to debug. Since I do not have a logic analyser at the moment, I need to debug this using the best known debugger - PRINTF STATEMENTS.

In my application, I need to change the resistance of the digital pot. But the pot is always at its reset position and does not change. Which means its not receiving my commands. I have verified the sequence of commands I'm sending and it is according to the "Basic operation" section in the datasheet. Please find the "Basic operation" section picture attached below. You will find that the code snip I pasted earlier does this exact same thing.
Screenshot from 2024-04-25 11-59-55.png

newbie_stm32
Associate III

Hi @bruce_wayne_1997 the following configuration worked well for me with AD5592 SPI on CubeMX.

Data Size8 Bits
CPOLLOW
CPHA2 Edge

Use HAL_SPI_TransmitReceive and probe the SPI on the oscilloscope/analyzer.

 

In my case, as the data sent to AD5592 is 16 bits in MSB first order, STM32 sends the MSB of the first byte 0x02 (rather than 0x18) in your case a swap between bytes is needed.

 

I hope this helps!!!

Hey @newbie_stm32 ,

I changed the cubemx configuration to CPOL=low;CPHA=2 Edge as I understood from your reply.

Picture:

Screenshot from 2024-04-25 17-13-47.png

I adjusted the code to the following after your suggestion:

 

// Step 1
my_shift_register.bytes = 0x0218; // Sending 0x1802

HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 0);
HAL_Delay(10);
printf("shift register contents: %x\r\n", my_shift_register.bytes);
printf("SPI transmit return: %d\r\n", HAL_SPI_Transmit(&hspi1, (uint8_t*)(&my_shift_register.bytes), 2, 0xFF));
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 1);

HAL_Delay(100);
printf("DEBUG: Step 1 complete\r\n");

// Step 2
my_shift_register.bytes = 0x0005; // Sending 0x0005

HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 0);
HAL_Delay(10);
printf("shift register contents: %x\r\n", my_shift_register.bytes);
printf("SPI transmit return: %d\r\n", HAL_SPI_Transmit(&hspi1, (uint8_t*)(&my_shift_register.bytes), 2, 0xFF));
HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB, AD5293_SYNC_Pin, 1);

HAL_Delay(100);

 

But I still dont see the wiper moving from the 1/2 position. Please let me know if you think any of this is wrong.

 

newbie_stm32
Associate III

Hi @bruce_wayne_1997, can you run a debug session on STM32CubeIDE and check for the following?

As per basic operation

  1. Send 0x1802 on SPI using HAL_SPI_Transmit (You are doing it correctly)
  2. Send 0x0500 using HAL_SPI_TransmitReceive and check you received 0x1802 (As per Table 9)

PS: Consider swapping bytes

 

bruce_wayne_1997
Associate II

Hello @newbie_stm32

I have followed your suggestions on changed I need to make to transfer the data to AD5293 chip.

First I'd like to share my SPI configuration again: (Figure 1)

Screenshot from 2024-05-03 12-41-31.png

Sharing the SPI GPIO config: (Figure 2)

Screenshot from 2024-05-03 12-44-02.png

Code used to send data to AD5293: (followed "Basic Operation" table from the datasheet) (Code 1)

  /* SPI test */
  // Reset AD5293
  HAL_GPIO_WritePin(GPIOB, AD5293_RESET_Pin, GPIO_PIN_RESET);
  HAL_Delay(100);
  HAL_GPIO_WritePin(GPIOB, AD5293_RESET_Pin, GPIO_PIN_SET);

  // Read RDY pin

  // Make CS low
  HAL_GPIO_WritePin(GPIOB, AD5293_CS_Pin, GPIO_PIN_RESET);
  // Transfer 0x1802
  spi_tx_buf[0] = 0x02;
  spi_tx_buf[1] = 0x18;
  if(HAL_SPI_Transmit(&hspi1, spi_tx_buf, 2, 0xFF) != HAL_OK)
	  printf("SPI transmit failed\r\n");
  // Make CS high
  HAL_GPIO_WritePin(GPIOB, AD5293_CS_Pin, GPIO_PIN_SET);

  // Make CS low
  HAL_GPIO_WritePin(GPIOB, AD5293_CS_Pin, GPIO_PIN_RESET);
  // Transfer 0x0500
  spi_tx_buf[0] = 0x00;
  spi_tx_buf[1] = 0x05;
  if(HAL_SPI_TransmitReceive(&hspi1, spi_tx_buf, spi_rx_buf, 2, 0xFF) != HAL_OK)
	  printf("SPI transmit receive failed\r\n");
  // Make CS high
  HAL_GPIO_WritePin(GPIOB, AD5293_CS_Pin, GPIO_PIN_SET);

 I'm not able to receive anything on spi_rx_buf[2]. I concluded this using debug mode after line 27 from the code above. I believe this is happening because my SPI on the STM is not working properly - the SCLK line.

Sharing the Oscilloscope data: (oscilloscope is 24MHz, 8ch): (Figure 3)

Screenshot from 2024-05-03 12-50-38.png

 As you can see, the clock line is only changing once, the SPI data is not being transferred to the slave.

Sharing the SPI initialization code generated by Device configurator: (Code 2)

SPI Config: SPI Mode 1 (CPOL=0;CPHA=1), 8 bits, MSB first

static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  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_2EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 0x0;
  hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
  hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
  hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
  hspi1.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi1.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;
  hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
  hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
  hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
  hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
  hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

 

I'm just not able to figure out why SPI is not working. I have tried using other SPI peripherals like SPI_4 instead of SPI_1 and it is still the same. I also tried pulling down the SCLK line but it outputs the same waveform as shown above in Figure 3. Can the experts please suggest me how I can go about this problem? Now I'm sure that this problem is not a problem of slave but infact the master's SPI initialization itself. I'm using STM32H723 Nucleo board. Request STM experts to share their thoughts.

 

Although the slave is not the problem I'd like to share the schematics of AD5293 circuit I made for more clarity.

WhatsApp Image 2024-05-03 at 12.59.36 PM.jpeg

Is this correct?