Skip to main content
mfrank9
Associate III
February 4, 2019
Question

How to receive SPI in Half-duplex-Mode?

  • February 4, 2019
  • 5 replies
  • 6808 views

Hallo,

i dont unterstand how i can receive data in Spi Half-Duplex-Mode.

My used Controller is STM32F446RET.

STM32CubeMX is configured as follow0690X000006DN9cQAG.png

Thats my Code: 

HAL_GPIO_WritePin(CS_GPIOxLib, CS_GPIO_PinLib, GPIO_PIN_RESET);
 
 
 
 
 
 status = HAL_SPI_Transmit(hspiLib, (uint8_t*)&register_Address_calculation, 1, 10000);
 
 status = HAL_SPI_Receive(hspiLib, (uint8_t*)Value, 1, 10000);
 
 
 
 if(status != HAL_OK)
 
 {
 
 Error_Handler();
 
 }
 
 
 
 HAL_GPIO_WritePin(CS_GPIOxLib, CS_GPIO_PinLib, GPIO_PIN_SET);

A Logic Analyser shows that there are same Errors on the SPI when i try to receive.

0690X000006DN9mQAG.png

But when i changed

hspi3.Init.Direction = SPI_DIRECTION_1LINE;

to

 hspi3.Init.Direction = SPI_DIRECTION_2LINES;

the SPI looks better:

0690X000006DNA1QAO.png

Is this wrong implemented by STM32Cube?

When i changed my Code back to

hspi3.Init.Direction = SPI_DIRECTION_1LINE;

&

HAL_GPIO_WritePin(CS_GPIOxLib, CS_GPIO_PinLib, GPIO_PIN_RESET);
 
status = HAL_SPI_TransmitReceive(hspiLib, (uint8_t*)&register_Address_calculation, (uint8_t*)Value, 1, 10000);
 
if(status != HAL_OK)
{
 Error_Handler();
}
 
HAL_GPIO_WritePin(CS_GPIOxLib, CS_GPIO_PinLib, GPIO_PIN_SET);

the Function HAL_SPI_TransmitReceive goes in TIMEOUT.

When i changed SPI Direction to

 hspi3.Init.Direction = SPI_DIRECTION_2LINES;

i can see, that STM32 dont spend clocks for receive

0690X000006DNAfQAO.png

Is there anything wrong in my code?

Is there an example code?

This topic has been closed for replies.

5 replies

Tesla DeLorean
Guru
February 4, 2019

>>Is there an example code?

grep through the HAL example trees for the F4, and perhaps others.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal
February 4, 2019

I would advise to use SPI 4 wires mode with MISO and MOSI shorted outside (of as some SPI IP versions have MISO swap MOSI) to make half duplex mode SPI in 3 wire mode.

Still you'll use DMA for TX (how many clocks to send) and RX (receiving data and triggering transfer complete interrupt). The monodirectional may make SCK clock generation more time/latency stressing.

Dzor
Associate
August 27, 2020

Why 4 wires? That's wastes 1 pin and adds 1 extra resistor.

waclawek.jan
Super User
February 5, 2019

If set to master and half-duplex (SPI_CR1.BIDIMODE=1), as soon as turned to Rx (SPI_CR1.BIDIOE=0), SPI starts to automatically output clocks (and shift in data) and does not stop until turned to Tx again. It means, you have to very carefully time the direction turns. Cube/HAL has probably no provision for this - it's one of the many specialty uses of STM32 hardware, and Cube/HAL covers inevitably only the most common modes of use.

As Clive said, look at the examples in Cube. For example, at the STM32L476G-DISCO, there's a magnetometer, LSM303C, which requires bidirectional SPI communication, and CubeL4 handles it in [CubeL4]\Drivers\BSP\STM32L476G-Discovery\stm32l476g_discovery.c , for example:

uint8_t MAGNETO_IO_Read(uint8_t RegisterAddr)
{
 MAGNETO_CS_LOW();
 __SPI_DIRECTION_1LINE_TX(&SpiHandle);
 SPIx_Write(RegisterAddr | 0x80);
 __SPI_DIRECTION_1LINE_RX(&SpiHandle);
 uint8_t val = SPIx_Read();
 MAGNETO_CS_HIGH();
 return val;
}
 
 
static uint8_t SPIx_Read(void)
{
 uint8_t receivedbyte;
 
 __HAL_SPI_ENABLE(&SpiHandle);
 __DSB();
 __DSB();
 __DSB();
 __DSB();
 __DSB();
 __DSB();
 __DSB();
 __DSB();
 __HAL_SPI_DISABLE(&SpiHandle);
 
 while((SpiHandle.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE);
 /* read the received data */
 receivedbyte = *(__IO uint8_t *)&SpiHandle.Instance->DR;
 
 /* Wait for the BSY flag reset */
 while((SpiHandle.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY); 
 
 
 return receivedbyte;
}

Needless to say that interrupts have to be disabled around such code.

https://community.st.com/s/question/0D50X00009XkaBgSAJ/strange-spi-receive-routine-in-cube-example-code

I don't say I like this code. And I don't Cube.

If you don't necessarily need things to go very fast, and/or you don't intend to dig deep, you may be better off bit-banging the SPI.

JW

RJadh.11
Associate
March 8, 2022

same problem i am facing i read data but with garbage value also comming.