cancel
Showing results for 
Search instead for 
Did you mean: 

Occasional errors on UART's received Bytes.

PMach.1
Senior

Hi, everyone,

I have been struggling with an issue for sometime. Upon reception, occasionally, a Byte is received with an error in which the most significant bit is received as a '1'. For example, if 0x55 (0101 0101) is sent, 0xD5 (1101 0101) is received (not always, though). THe UART's configuration is as follows:

static void MX_USART2_UART_Init(void)
{
 
  /* USER CODE BEGIN USART2_Init 0 */
 
  /* USER CODE END USART2_Init 0 */
 
  /* USER CODE BEGIN USART2_Init 1 */
 
  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_2;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */
 
  /* USER CODE END USART2_Init 2 */
 
}

As a debug measure, reducing the baudrate from 115200 to 2400 had no effect. I also changed the oversampling from 16 bits to 8 bits, with no avail. One bit sampling was also enabled, with no success. The last two configurations were also set simultaneously and the problem persists.

I have set the UART with enabled interrupts. Thus, upon a received Byte, an interrupt is triggered and the Byte extracted inside the ISR. Whenever the issue occurs, the RDR (receive data register) contains the Byte with the said error on the Byte's most significant bit. This fact leads me to the suspicion that there's a kind of sampling problem, leading to the UART sampling the stop bit as the MS bit.

A curious behavior that I observed during the UART_SetConfig function was that HAL_RCC_GetPCLK1Freq() returns 16MHz, when it is configured as 170MHz in .ioc file (ClockPrescaler=0) altough, given this unexpected clock, the USARTDIV constant is well computed and stored in BRR. Does this fact relate to the issue?

I think it is relevant to say that the transmission occurs with no problem whatsoever. The bytes are correctly received on a terminal in my computer.

What might be happening?

Thanks in advance and, please, let me know if there's any detail I may have missed exposing here.

Kind regards,

Pedro Machado

1 ACCEPTED SOLUTION

Accepted Solutions
PMach.1
Senior

[SOLVED]

It turned out to be the case that the oscillator was broken. A new oscillator solved the problem.

View solution in original post

13 REPLIES 13
TDK
Guru

If the MSB error is always present, and always read as 1,the other side is probably only sending 7 data bits instead of 8.

If the MSB is only occasionally incorrect, it would suggest there's a mismatch between clock speeds, since the MSB is the last bit. Seems like you realize that.

A mismatch of 16MHz vs 170MHz seems like it would cause more than just an occasional bit error. If you have a way of seeing the speed on the line via a logic analyzer or scope, I would do that. Otherwise, double check the clocks are consistent. UART baud is the peripheral clock divided by BRR (usually), which is easy to calculate.

If you feel a post has answered your question, please click "Accept as Solution".

Hi,

First of all, thank you for your answer.

The serial terminal is sending at the right rate. With a logic analyzer, I managed to measure the bit time, which is 0.416ms (+-0.001), which is the equivalent to a 2400 bps baudrate. This phenomenon occurs also when the Byte is received with error. By the way, the pattern is always correctly sent, even with the Byte error upon reception (start bit + 8 Data bits + stop bit).

The computed BRR is 6667. For a clock speed of 16MHz, the baudrate is then: baud = pclk/BRR = 16000000/6667 = 2399.88

It seems to me there's nothing wrong with clock timing

Okay, so data sent to the MCU seems correct in terms of timing. So the PC is doing its job.

Is data sent by the MCU to the computer also correct?

If you feel a post has answered your question, please click "Accept as Solution".

I forgot to mention it. Yes. Data sent from MCU to PC is correct and is correctly shown in the terminal.

Okay so it "works", but is the timing correct as measured by a logic analyzer? That would show you if the MCU clock is accurate. If that's not it, I'm not sure what the issue could be. Maybe a pullup that is too weak, but that seems unlikely.
If you feel a post has answered your question, please click "Accept as Solution".

> With a logic analyzer, I managed to measure the bit time,

What did you measure - Tx from the STM32, or Rx to STM32?

If you measured Rx to STM32, measure Tx from STM32 and post result.

JW

Jack Peacock_2
Senior III

What you describe is a start bit bleeding over into the first data bit. The most common reason for this is a baud rate mismatch, but there are other causes. First off, are you using the HSE oscillator with a crystal, or an internal RC oscillator as the system (and PCLK) clock source? An RC source may test out okay on the scope but keep in mind it can drift.

If your PCLK1 clock is only 16MHz something is amiss in your clock configuration, especially if the HCLK is 170MHz.

Bit jitter problems in async UARTs can occur when receiving long strings with no gap (other than stop bit) between characters. Async works best when there are frequent gaps longer than the stop bit so the RX window aligns properly to the start bit. When it doesn't align you either get framing/overrun errors or high bit set from sampling the start bit instead of first data bit. You can verify this isn't occurring by sending short bursts instead of long strings. Do you check for OE and FE errors when receiving UART data? Always read the status register before data in your RX ISR routine.

There's also the possibility of too much capacitance on the RX pin or somewhere in the transmission line. In your case since it's only one bit this is less likely, but you should make sure the RX signal is a clean square wave and doesn't show slow rise times indicative of capacitor charging/discharging.

Jack Peacock

Hi, Jack,

Thanks for your answer.

Indeed, the signals sent from the MCU to the computer showed a clock mismatch. Please, check my answer below for more details.

Kind regards

Hi,

I have measured the TX from STM32. Please, check my answer below for more details.

Kind regards.