Showing results for 
Search instead for 
Did you mean: 

STM32F103RB UART comm. in half-duplex, single-wire mode


I am using two NUCLEO-F103RB boards for implementing and testing single-wire, half-duplex UART communication in polling mode. First I implemented and tested code based on the ‘UART_TwoBoards_ComPolling' example, which is included in the STM32F1 HAL library. Next I modified the code with the STM32CubeMX tool and set UART to Single-Wire (Half-Duplex), then re-created the code. See the screenshot. The idea is to only change what is required for switching from full-duplex to half-duplex, and leave the remaining code unchanged.

Note that STM32CubeMX configures full-duplex UART config with a Push-Pull output. The half-duplex output is Open Drain and requires a pull-up resistor.

Test setup:

* Two NUCLEO-F103RB boards.

* STM32CubeIDE Version 1.12.1.

* STM32CubeMX Version 6.8.1.

Known required changes from full-duplex to half-duplex (here UART1):

* One wire from UART1 PA9 on both NUCLEOs.

* Call in main(): HAL_UART_MspInit() changes pin PA9 to Open drain.

* CubeMX adds HAL_HalfDuplex_Init() to MX_USART1_UART_Init().


Is it required to call HAL_HalfDuplex_EnableTransmitter() and HAL_HalfDuplex_EnableReceiver() every time before sending/receiving packets? For example:

HAL_UART_Transmit(&huart1, (uint8_t*)aTxBuffer, TXBUFFERSIZE, 5000);
HAL_UART_Receive(&huart1, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 5000);



Accepted Solutions

The answer is yes, the two functions HAL_HalfDuplex_EnableTransmitter(&huart1) and HAL_HalfDuplex_EnableReceiver(&huart1) must be used as shown.

View solution in original post


The answer is yes, the two functions HAL_HalfDuplex_EnableTransmitter(&huart1) and HAL_HalfDuplex_EnableReceiver(&huart1) must be used as shown.



I have a problem with the STM32G031J6M6.

I'm trying to run half duplex on uart1, but I can't receive data, only transmit.

I use HAL_HalfDuplex_EnableReceiver but no effect.




I don't know if it's the same for your processor, but for the BluePill (STM32F103C8T6) I am able to receive data in half-duplex mode (note:  the data is received on the TX pin) if I set the RE bit in USART->CR1 register after my last transmit on that USART has completed.  Make sure the previous transmit has completed (check the TC bit in the SR register, otherwise, you may get an echo of a portion of the transmitted message if you set the RE bit in the next instruction after your Serial.print statement).  

I'm using the Arduino framework within VSCode using PlatformIO.

Be aware, that you will need to either attach an external pull-up resistor, or define your TX pin as an INPUT_PULLUP pin AFTER you setup the serial port for half-duplex.

During transmissions, the TX pin is driven during the start bit, data bits, and stop bit continuously until the final frame.  After the stop bit of the final frame, the TX output driver is disconnected from the TX pin, and the pin is pulled up with the (internal or external) resistor.  

If you are setting up a multi-drop single-wire system, I recommend using an external pull-up resistor(s) and configure your TX pins as simple INPUT (or don't configure at all, and they will be set as INPUT by default).  Otherwise if you set too many of the devices on the line as INPUT_PULLUP, the TX driver may not be able to pull the line LOW.

Sorry all of this is referenced to the BluePill, but that's all I've got.

Good luck.