# STM32 UART send broken frames

I have a NUCLEO-F303RE board and try to send some data by one-wire UART with 57600 baudrate. But frames are sent broken (see images below):

How must to be:

What I get:

I've tried to use different clocks (HSE 32MHz and internal HSI 8MHz), change baud rate to 9600, but nothing helps and frames are broken the same way. I suppose I have a bad configuration of something, but I have no idea what is wrong. I have another UART connected which is used for debug and it works fine on 57600 baud rate (not in half-duplex mode) with same clock.

My UART configuration:

#define SERVO_PORT            GPIOB
#define SERVO_PIN             GPIO_PIN_10
#define SERVO_GPIO_ENABLE()   __HAL_RCC_GPIOB_CLK_ENABLE()

#define UART_INSTANCE         USART3
#define UART_CLK_ENABLE()     __HAL_RCC_USART3_CLK_ENABLE()
#define UART_AF               GPIO_AF7_USART3
#define UART_IRQ              USART3_IRQn
#define UART_IRQ_HANDLER      USART3_IRQHandler

static UART_HandleTypeDef huart = {
.Instance          = UART_INSTANCE,
.Init.BaudRate     = 57600,
.Init.WordLength   = UART_WORDLENGTH_8B,
.Init.StopBits     = UART_STOPBITS_1,
.Init.Mode         = UART_MODE_TX_RX,
.Init.Parity       = UART_PARITY_NONE,
};

/* Called later in HAL_UART_MspInit */
void Servo_UART_MspInit(UART_HandleTypeDef* h) {
if (h == &huart) {
SERVO_GPIO_ENABLE();
UART_CLK_ENABLE();

GPIO_InitTypeDef pin = {
.Pin        = SERVO_PIN,
.Mode       = GPIO_MODE_AF_PP,
.Pull       = GPIO_NOPULL,
.Speed      = GPIO_SPEED_FREQ_HIGH,
.Alternate  = UART_AF,
};
HAL_GPIO_Init(SERVO_PORT, &pin);
}
}

void initUART() {
HAL_TIM_PWM_DeInit(&htim);

HAL_HalfDuplex_Init(&huart);

HAL_NVIC_SetPriority(UART_IRQ, 0, 0);
HAL_NVIC_EnableIRQ(UART_IRQ);
}

bool servoSend(uint8_t* data, uint8_t size) {
HAL_HalfDuplex_EnableTransmitter(&huart);
return HAL_OK == HAL_UART_Transmit(&huart, data, size, HAL_MAX_DELAY);
}


And I send data like this:

...
uint8_t d[5] = {0x2B, 0x0, 0xD5, 2, 0xB1};
bool ret = servoSend(d, 5);
if (!ret) return DITEX_SERVO_CALLBACK_FAILED;
...


My clock initialization:

static void initSystemClock() {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2;
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_USART3
|RCC_PERIPHCLK_TIM2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
PeriphClkInit.Usart3ClockSelection = RCC_USART3CLKSOURCE_SYSCLK;
PeriphClkInit.Tim2ClockSelection = RCC_TIM2CLK_HCLK;
}

• Well the first problem I see is that your signal is inverted. That, of course, will confuse the receiver and cause a framing error. Jan 7 at 19:27
• @jwh20 I've tried invert data logic or tx active level but then data is completely incorrect. Invertion of rx active level changes nothing Jan 7 at 19:34
• Well it's inverted and that's wrong. Fix that and move to next problem. Jan 7 at 19:52
• What does "one-wire UART" mean? You are using a common ground, aren't you? Jan 7 at 21:35
• Are you checking that the content of your UART TX data register have been successfully shifted by for example while(!(USART1->ISR & USART_ISR_TXE)) checking that the TX register is empty. Otherwise this smells like a clock/baud mismatch, show us your clock tree, the clock source for your USART is the system clock and not the APB where I assume the USART is connected to Jan 8 at 7:02

Problem was in UART pin configuration: it needed to be pulled up instead of open drain:

GPIO_InitTypeDef pin = {
.Pin        = SERVO_PIN,
.Mode       = GPIO_MODE_AF_PP,
.Pull       = GPIO_PULLUP,
.Speed      = GPIO_SPEED_FREQ_HIGH,
.Alternate  = UART_AF,
};
HAL_GPIO_Init(SERVO_PORT, &pin);


I believe that you have problem in configuring the system clock. You can use ST's STM32CubeIDE to get the right configuration.

If you are using crystal, use

  RCC_OscInitStruct.HSEState = RCC_HSE_ON;


You specified RCC_HSE_BYPASS, unless you have clock source (not crystal).

(sorry, I have to put this as answer as I do not have enough reputation)