cancel
Showing results for 
Search instead for 
Did you mean: 

How to receive SPI in Half-duplex-Mode?

mfrank9
Associate III

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?

5 REPLIES 5

>>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
Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal

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.

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

Dzor
Associate II

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

RJadh.11
Associate

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