Electronic – STM32 USART synchronous mode receive does not work

spistm32stm32luart

I am using a STM32L052K6U6 to communicate with an SPI slave using the UART1 synchronous mode (configured with CubeMX, using the LL library).

Setup code generated by CubeMX (I left out the Tx and Clk pin config as those pins do what they should):

  GPIO_InitStruct.Pin = USART1_RX_ECG_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_4;
  LL_GPIO_Init(USART1_RX_ECG_GPIO_Port, &GPIO_InitStruct);

  USART_InitStruct.BaudRate = 2000000;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_0_5;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_8;

  LL_USART_Init(USART1, &USART_InitStruct);

  USART_ClockInitStruct.ClockPolarity = LL_USART_POLARITY_LOW;
  USART_ClockInitStruct.ClockPhase = LL_USART_PHASE_1EDGE;
  USART_ClockInitStruct.LastBitClockPulse = LL_USART_LASTCLKPULSE_OUTPUT;
  LL_USART_ClockInit(USART1, &USART_ClockInitStruct);

  LL_USART_EnableDEMode(USART1);

  LL_USART_DisableDEMode(USART1);

  LL_USART_DisableDMADeactOnRxErr(USART1);

  LL_USART_Enable(USART1);

  LL_USART_ConfigSyncMode(USART1);

  LL_USART_Enable(USART1);

Init code written by me, executed after the code above (the EnableDirection calls are not actually needed, Tx and RX is already enabled in the code above):

LL_USART_Disable(USART1);

LL_USART_SetTransferBitOrder(USART1, LL_USART_BITORDER_MSBFIRST);

LL_USART_EnableDirectionTx(USART1);
LL_USART_EnableDirectionRx(USART1);

LL_USART_Enable(USART1);

This is part of the code that receives data:

LL_USART_TransmitData8(USART1, 0);
while(!LL_USART_IsActiveFlag_BUSY(USART1));
while(LL_USART_IsActiveFlag_BUSY(USART1));
uint8_t data_1 = LL_USART_ReceiveData8(USART1);

Probing the bus reveals that the clock generation and data sending works fine and the slave responds with the expected data. The receiver is enabled, but the data is not received by the microcontroller. The receive data register and the RXNE flag stay zero.
What could cause this?

Best Answer

  • Wait for TXE before transmitting

  • Wait for RXNE instead of monitoring the BUSY bit before reading the answer. Waiting on BUSY that way might fail when an interrupt comes at the wrong time, and the data might not yet be transferred to the data register when BUSY goes to 0.

  • Check CPOL and CPHA, it might be sampling the input at the wrong time