Skip to main content
Associate
August 17, 2026
Question

Issues with half-duplex single wire 8E2 inverted logic uart receive and frame errors

  • August 17, 2026
  • 9 replies
  • 120 views

I have some custom STM32G43KB boards that don’t always behave.  The firmware starts with the UART in receive mode, 9600 baud, 9B (8 + parity) 2 stop bits, TX and RX inverted to interface with the host device.  The device UART line idles low (ground) as expected for inverted logic, and sends a 17-byte poll message that my board will reply to.  

Out of 25 boards that have been programmed with the same firmware, about 60 percent of them work, the other 40% show a frame error and do not decode the first byte of the message properly.  

I have been using alternate function push pull for PA9 configuration, with a 10K pull down resistor to create the idle low condition when in receive mode.  Some boards work, some don’t.  

The same boards, when programmed with other versions of the firmware for interface to different external systems are working fine with AF Push/Pull, 8N1, not inverted, baud rates of 100K, 115.2K and 250K with no issues.  

When configured for 9600 baud 8E2 inverted, some of the boards work, some don’t. 

Suggestions?  

9 replies

G-MACAuthor
Associate
August 17, 2026

some additional info:  It has been suggested that the preferred configuration for the PA9 UART TX line is alternate function open drain with a pull up resistor.  I don’t believe this is going to work with the master device (my board is a slave, responds to polls from the master).  

The master appears to start up in a TX condition, with the line held low.  After the master sends it’s 17 byte poll, the line idles at ~1.94V, indicating that it is in receive mode with a pull down resistor of about 14.3K ohms, from the voltage divider of the 10K pullup on my board and the pull down resistor in the master device.  

I have no details of the hardware in the master device, this is all based on measurements.  

Is alternate function push-pull, with a 10K pull DOWN resistor the appropriate configuration for my board?  the push-pull TX would properly drive the master when responding to a poll, and when my board is in receive mode, the line would idle near ground which is the desired condition.  

Ozone
Principal
August 18, 2026

I suspect there is either some signal/noise or level issue.
With 9600 bps, and in a (supposedly) controlled environment, so many glitches or signal deformation seem unlikely.

What is the other side of your application, the one which sends this 17-byte message ?
Does it use the same logic / output level ?

I used to have similiar problems when trying to connect 5V RS232 logic directly to 3.3V MCU pins.
The UART pins of basically all STM32s are 5v tolerant, so reception usually works fine. But the Tx level of the 3.3V side was too low to drive the 5V side consistently.

I would recommend trying to capture a transmission error with a scope.

Andrew Neil
Super User
August 18, 2026

Out of 25 boards that have been programmed with the same firmware, about 60 percent of them work, the other 40% show a frame error and do not decode the first byte of the message properly

Suggests there is something marginal in your design.

Are you sure that the baud rate is actually correct?

What clock source are you using?

Have you used an oscilloscope to see what’s actually happening on the wire?

 

PS:

As this is half-duplex on a single wire, are you sure that your change-of-direction is clean?

Specifically, that you’re not getting a glitch which causes a framing error or corrupt byte?

 

Have you logged what your device thinks it receives? Is there a pattern?

 

Some tips on Debugging Serial Comms.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
G-MACAuthor
Associate
August 18, 2026

I’ve run a test with the uart com wire disconnected from the outside world, a 10K pull down on the board, so there is no outside interference on that wire.  The board was powered via a battery input, on-board regulated to 3.3V.  Under these conditions, the frame error on a non-working board shows up when the board is started via the cubeIDE and ST-link.  The working boards do not set the frame error under the same conditions.  

 

G-MACAuthor
Associate
August 18, 2026

Another thing - the same non-working boards, using the same uart configuration (8E2 inverted) DO work at 100000 baud.  

I’ve tried shifting the baud rate slightly +/- from 9600 on the board, same issue.  Crystal frequency on the custom board is 24.0 MHz, (sourced the same crystal as that used on the STM32G431 Nucleo-32 board).  This handful of boards fails the 9600 baud case, but do work at the 100K as mentioned, or other configurations of firmware with 8N1 non-inverted work at 115200 bad and 250000 baud reliably.  It’s this 9600 bit that is giving me fits.  I’ve investigated the incoming waveform using a 200MHz scope and a Logic Analyzer - manually decoding the first byte of the input waveform based on the 104.17 uS bit time gives the proper result as does the logic analyzer.  

It appears to be some sort of startup hiccup when the RX is enabled, even with a solid low from the 10K pulldown and nothing eternal connected to that line.  

Any hints on how I might sync a scope to that function call in the code (  HAL_HalfDuplex_EnableReceiver(huart);   )  and a 2nd probe on the PA9 uart1 TX (and RX) line?  

 

code snippet for the UART initialization.   I’m NOT a software engineer, a retired RF/Analog/Antenna/navaid engineer, so if I’ve done something wrong here, let me know?   

 

HAL_UART_DeInit(huart);

 

huart->Init.BaudRate = 9600;

huart->Init.WordLength = UART_WORDLENGTH_9B;

huart->Init.StopBits = UART_STOPBITS_2;

huart->Init.Parity = UART_PARITY_EVEN;

huart->Init.Mode = UART_MODE_TX_RX;

huart->Init.OverSampling = UART_OVERSAMPLING_16;

 

 

huart->AdvancedInit.AdvFeatureInit =

UART_ADVFEATURE_TXINVERT_INIT |

UART_ADVFEATURE_RXINVERT_INIT;

 

huart->AdvancedInit.TxPinLevelInvert = UART_ADVFEATURE_TXINV_ENABLE;

huart->AdvancedInit.RxPinLevelInvert = UART_ADVFEATURE_RXINV_ENABLE;

 

HAL_HalfDuplex_Init(huart);

 

 

/* Enable TX inversion */

SET_BIT(huart->Instance->CR2, USART_CR2_TXINV);

 

/* Enable RX inversion */

SET_BIT(huart->Instance->CR2, USART_CR2_RXINV);

 

HAL_HalfDuplex_EnableReceiver(huart);

 

Pavel A.
August 19, 2026

> Any hints on how I might sync a scope to that function call in the code (  HAL_HalfDuplex_EnableReceiver(huart);   )  and a 2nd probe on the PA9 uart1 TX (and RX) line?  

Set trigger to the start bit : the first level change on the RX pin from the idle state ?