STM32: create the project and send text over the UART
Video coming soon
We create an STM32 project for the NUCLEO-F401RE and turn on USART2, which reaches the computer over the same USB cable. Then we make printf send text to it and watch a counter in the serial plotter in the browser.
In this lesson · 9 steps
1Start a new project from the board
- STM32CubeMX → Board Selector
- Search
NUCLEO-F401RE, select it, press Start Project - "Initialize all peripherals with their default Mode?" → No (we enable only what we need)
2Enable USART2
- Pinout & Configuration → Connectivity → USART2: Mode =
Asynchronous - Keep the default Parameter Settings:
115200baud, 8 bits, no parity, 1 stop bit - Pins:
PA2= TX,PA3= RX → wired to the ST-LINK on the Nucleo board (virtual COM port)
Why?
Why USART2, not 1 or 3? On the Nucleo board, its pins PA2 and PA3 are already wired to the ST-LINK. So the text goes to the computer over the same USB cable, and we don't need any adapter.
3Project Manager and code generation
- Project Name:
CH1_UART - Project Location: one folder for all the course projects
- Toolchain / IDE:
STM32CubeIDE→ Generate Code → Open Project - CubeIDE starts and asks for a workspace (the folder where it keeps projects): choose the same folder as the Project Location → Launch
Why?
The toolchain must be STM32CubeIDE. That's the key, otherwise CubeIDE can't open the project. And the workspace must be the same folder as the Project Location.
4Include stdio.h
main.c · USER CODE BEGIN Includes
stdio.h gives us printf.
/* USER CODE BEGIN Includes */ #include <stdio.h> /* USER CODE END Includes */
Why?
We always write our code between USER CODE BEGIN and END. Otherwise, it's erased when CubeMX generates the code again.
5Send printf to the UART
main.c · USER CODE BEGIN PV
Every time we call printf, the C library hands the text to _write, so the name must be exactly this.
/* USER CODE BEGIN PV */ int _write(int file, char *ptr, int len) { HAL_UART_Transmit(&huart2, (uint8_t *)ptr, len, HAL_MAX_DELAY); return len; } /* USER CODE END PV */
Why?
Inside, HAL_UART_Transmit sends it: first &huart2, the USART2 handle CubeMX made at the top of main.c, then the pointer and the length. The last one is the timeout: HAL_MAX_DELAY means wait until it's all sent. Then we return the length.
6Say hello once
main.c · USER CODE BEGIN 2
This printf runs once, after the peripherals start. \r\n ends the line.
/* USER CODE BEGIN 2 */ printf("Hello from STM32!\r\n"); int counter = 0; /* USER CODE END 2 */
Why?
And here is our counter, starting at zero, so the loop below can use it.
7Print a counter every 100 ms
main.c · inside while (1), before USER CODE END WHILE
We print a name, a colon and the value, like counter:12.
/* USER CODE BEGIN WHILE */ while (1) { printf("counter:%d\r\n", counter); counter++; HAL_Delay(100); /* USER CODE END WHILE */
Why?
The plotter needs exactly this format: the value goes on the plot, the name in the legend. HAL_Delay(100) waits 100 ms, so we get about 10 lines per second.
8Build and run
- Project Explorer → right-click the project → Build Project (0 errors)
- Debug (or Run): the first time, a launch dialog (Edit Configuration) opens → press OK
- In the debugger, the program stops at the start: press Resume (F8) and it runs
9Open the serial plotter
- steppeschool.com → Tools → Serial Plotter (or go straight to serial.steppeschool.com)
- Baud:
115200(the same as USART2) → Connect - In the browser window, pick the STM32 STLink port (ST-Link VCP) → Connect
- The
counterline goes up on the plot, and the console on the right shows the lines - Press the black reset button on the board to see the hello line again
Why?
Our serial plotter runs in the browser, so there is nothing to install. It needs Chrome or Edge, because it uses Web Serial. Only one program can use the port, so close any other serial monitor first.
Check & troubleshoot
What you should see
- The console shows
Hello from STM32once, then lines likecounter:12 - The counter goes up about 10 times per second
- The plot shows one line,
counter, going up
If it doesn't work
- Build does nothing: click the project name in the Project Explorer first, then press Build
- No port in the plotter: choose the STLink Virtual COM Port, and close any other program that uses it
- Nothing printed: check the
_writefunction is inside USER CODE BEGIN PV, and the baud rate is 115200 - Missed the hello line: it is sent only once at start; connect the plotter first, then press reset or Resume
Good to know
- Several values fit in one line, with commas:
ax:1,ay:2,az:3. The plotter draws each name as its own line. That's extremely helpful for sensors - The rate isn't exact. HAL_Delay waits 100 ms, but printf and the rest of the loop add time too. We fix that in lesson 1.3 with a timer