2023-06-21 10:50 PM - edited 2023-06-21 10:57 PM
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);
Please find the captured signal
Signal definition:
Signal | Purpose |
Red | NSS (Controlled manually) |
Green | SCK |
Brown | MOSI |
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:
2023-06-27 12:15 AM
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.
2023-06-27 01:03 AM
Hi,
STM32 is little endian, that means that in memory, tx_data is stored as this:
Adress | Content |
rx_data | 0xA5 |
rx_data + 1 | 0x25 |
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.
`
2023-07-10 09:51 PM
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?
2024-04-24 11:31 PM
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.
Note: I referenced the settings from another answer from STM forum where I found the following image -
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.
2024-04-24 11:53 PM
Hi @bruce_wayne_1997 the following configuration worked well for me with AD5592 SPI on CubeMX.
Data Size | 8 Bits |
CPOL | LOW |
CPHA | 2 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!!!
2024-04-25 04:43 AM - edited 2024-04-25 04:44 AM
Hey @newbie_stm32 ,
I changed the cubemx configuration to CPOL=low;CPHA=2 Edge as I understood from your reply.
Picture:
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.
2024-04-26 02:26 AM - edited 2024-04-26 02:29 AM
Hi @bruce_wayne_1997, can you run a debug session on STM32CubeIDE and check for the following?
As per basic operation
PS: Consider swapping bytes
2024-05-03 12:32 AM
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)
Sharing the SPI GPIO config: (Figure 2)
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)
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.
Is this correct?