2026-03-25 10:52 AM
NUCLEO F767ZI, CubeIDE 2.1.1, CubeMX 6.17.0
I'm trying to set up UART with printf()
#include <stdio.h>
UART_HandleTypeDef huart3;
static void MX_USART3_UART_Init(void);
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart3, (uint8_t *)ch, 1, 10);
return ch;
}
....
// in main
// in while
prinf("UART test\r\n");
// MX generated USART3 init
static void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
Clock tree from MX
Output in Tera Term window
TT is set up exactly the same as the UART init in the code.
Anyone know whats going on here?
Solved! Go to Solution.
2026-03-25 1:11 PM - edited 2026-03-25 1:13 PM
@NicRoberts wrote:
Even reconfiguring the UART with an odd partity
You don't have to configure the parity. You need just to set the data in 7-bit mode in the hyperterminal.
Ok, validate your harware using the example I provided previously with the same UART config described in the readme file: https://github.com/STMicroelectronics/STM32CubeF7/blob/master/Projects/STM32F767ZI-Nucleo/Examples/UART/UART_Printf/
If it doesn't work you have an issue with your board.
It's up to you to test, I don't have your board!
2026-03-26 7:18 AM
@mƎALLEm
OK found it after comparison with the reference code linked above. user error (when isn't it) it turns out I wasn't retargeting the printf function correctly. A missing ampersand in the data passed to the UART_transmit function,
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 10);
return ch;
}
2026-03-26 7:24 AM - edited 2026-03-26 7:25 AM
@NicRoberts wrote:int __io_putchar(int ch) { HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 10); return ch; }
Sorry I didn't understand your feedback. What is the difference between the retargeting printf you have shared now and what you have shared in your original post? I don't see any difference!:
int __io_putchar(int ch)
{
HAL_UART_Transmit(&huart3, (uint8_t *)ch, 1, 10);
return ch;
}
2026-03-26 7:39 AM - edited 2026-03-26 7:47 AM
@mƎALLEm wrote:What is the difference
Before After:
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 10);
^-- Here!
After Before:
HAL_UART_Transmit(&huart3, (uint8_t *)ch, 1, 10);
^-- Here!
@NicRoberts so the problem was that you were actually sending gibberish to the terminal!
This is exactly why I always recommend to get direct comms working first - before adding the extra complications of printf redirection!
Edited to correct 'Before' & 'After'
2026-03-26 7:39 AM - last edited on 2026-03-26 7:44 AM by mƎALLEm
My original code,
HAL_UART_Transmit(&huart3, (uint8_t *)ch, 1, 10);
What it should be,
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 10);
Notice the & in front of the ch
2026-03-26 7:42 AM
Other way around, it works with the ampersand but gibberish without it.
2026-03-26 7:46 AM
@NicRoberts wrote:
My original code,
HAL_UART_Transmit(&huart3, (uint8_t *)ch, 1, 10);
What it should be,
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 10);
Notice the & in front of the ch
I moved the solution to this post then..
2026-03-27 1:40 AM
One of those mistakes that we've probably all made that take forever to spot as you read what you thought you had typed when looking at the code ;)
Something that static analysis can help with on a good day.
2026-03-27 3:57 AM
Unfortunately, the mistake was masked by the (uint8_t*) cast - without that, you'd have got a compiler warning...
2026-03-27 4:42 AM
@Andrew Neil wrote:Unfortunately, the mistake was masked by the (uint8_t*) cast - without that, you'd have got a compiler warning...
GCC does generate a warning for it: