Showing results for 
Search instead for 
Did you mean: 

Nucleo board stm32f302r8 USART2 TDR has data but TeraTerm did show any output.


I have a problem where Im developing a bare metal USART Send Data for stm32f302r8 nucleo board. Im sending on USART2 which is PA2 and PA3 through the virtual COM. The TDR register is updating 1 byte by 1 byte. But, the TeraTerm is not showing any data. I have checked the nucleo board datasheet where the Virtual COM is enabled by default and I dont think I need to do any rework on the board. 

Here is my application code:



 * uart_tx.c
 *  Created on: 22 Oct 2023
 *      Author: irsyad
#include <string.h>
#include "stm32f30xx.h"
#include <stdio.h>

USART_Handle_t usart2_handle;

// tx buffer
uint8_t msg[1024] = "USART Tx testing...........\n\r";
void delay(void)
  for (uint32_t i = 0; i < 200000; i++);

void USART2_GPIOInit(void)
	GPIO_Handle_t usart2_pins;

	usart2_pins.pGPIOx = GPIOA;
	usart2_pins.GPIO_PinConfig.GPIO_PinAltFunMode = GPIO_MODE_ALTFN;
	usart2_pins.GPIO_PinConfig.GPIO_PinOPType = GPIO_OP_TYPE_PP;
	usart2_pins.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_PU;
	usart2_pins.GPIO_PinConfig.GPIO_PinAltFunMode = 7;
	usart2_pins.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_HIGH;

	usart2_pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_2;

	usart2_pins.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_3;

void USART2_Init()
    usart2_handle.pUSARTx= USART2;
    usart2_handle.USART_Config.USART_Baud = USART_STD_BAUD_115200;
    usart2_handle.USART_Config.USART_HWFlowControl = USART_HW_FLOW_CTRL_NONE;
    usart2_handle.USART_Config.USART_Mode = USART_MODE_ONLY_TX;
    usart2_handle.USART_Config.USART_NoOfStopBits = USART_STOPBITS_1;
    usart2_handle.USART_Config.USART_WordLength = USART_WORDLEN_8BITS;
    usart2_handle.USART_Config.USART_ParityControl = USART_PARITY_DISABLE;


void GPIO_ButtonInit(void)
	//1. first create a variable for our GPIO handle
		GPIO_Handle_t  GpioBtn; //GpioLed;

	/*======================PUSH BUTTON CONFIGURATION===========================*/

    //1. now, we have to initialize
	//mula2 select port
	GpioBtn.pGPIOx= GPIOC;

	//2. Then select pin number
	GpioBtn.GPIO_PinConfig.GPIO_PinNumber = GPIO_PIN_NO_13;

	//3.Select pin mode
	GpioBtn.GPIO_PinConfig.GPIO_PinMode = GPIO_MODE_INPUT;

	//4.Select speed (ni xpenting sgt, boleh biar default)
	GpioBtn.GPIO_PinConfig.GPIO_PinSpeed = GPIO_SPEED_HIGH;

	//5.  enable internal resistor sebab output type open drain
	GpioBtn.GPIO_PinConfig.GPIO_PinPuPdControl = GPIO_NO_PUPD;

	//6.enable peripheral clock
	GPIO_PeriClockControl(GPIOC, ENABLE);

	//7.Call GPIO_init()
	GPIO_Init(&GpioBtn); //send address GpioLed

	/*======================PUSH BUTTON CONFIGURATION===========================*/


int main()




	USART_PeripheralControl(USART2, ENABLE);

	while (1)
	    // wait for button press
	    while(GPIO_ReadFromInputPin(GPIOC, GPIO_PIN_NO_13) );


	     // send some data to the slave
	     USART_SendData(&usart2_handle, (uint8_t *)msg, strlen((char *)msg));

	return 0;




and here is my USART Send data API:



void USART_SendData(USART_Handle_t *pUSARTHandle, uint8_t *pTxBuffer, uint32_t Len)
	uint16_t *pdata;

	//1.loop over until 'Len' number of bytes are transferred.
	for(uint32_t i = 0;i < Len;i++)
		//2.wait until TXE flag is set in the ISR (It indicates the data is ready at the shift register)
		while(! USART_GetFlagStatus(pUSARTHandle->pUSARTx,USART_FLAG_TXE));

		//3.Check the USART_WordLength item for 9BIT or 8BIT in a frame
		if(pUSARTHandle->USART_Config.USART_WordLength == USART_WORDLEN_9BITS)
			//if 9BIT, then we have to load 9 bit to the DR.
			// to extract 9 bits, we use masking.
			//Bit masking is a technique that involves performing bitwise operations on data blocks to extract the required bits
			//0x01FF is used to mask out 9bits from the 16bit data.
			pdata = (uint16_t*) pTxBuffer;//This is why pTxBuffer is typecasted to 16bit to extract 2bytes of data which only 9bit are loaded into the data register
			pUSARTHandle->pUSARTx->TDR = (*pdata & (uint16_t)0x01FF);

			//check for USART_ParityControl
			if(pUSARTHandle->USART_Config.USART_ParityControl == USART_PARITY_DISABLE)
				//If the parity is disabled,
				//No parity is used in this transfer. so, 9bits of user data will be sent
				//So, its like sending 2bytes, sbb utk hold 9 bits, it requires 2 bytes size.
				//hence, increment pTxBuffer twice
				pTxBuffer++; //1byte
				pTxBuffer++; //1byte

				//Parity bit is used in this transfer . so , 8bits of user data will be sent
				//The 9th bit will be replaced by parity bit by the hardware
				pTxBuffer++; //1byte

			//8-bit data transfer
			//Doing this (bitwise AND with 0xFF) ensures that only 8-bits are taken from pTxBuffer.
			pUSARTHandle->pUSARTx->TDR = (*pTxBuffer  & (uint8_t)0xFF);

			//increment the buffer address

	//4.wait until TC flag is set in the ISR
	while( ! USART_GetFlagStatus(pUSARTHandle->pUSARTx,USART_FLAG_TC));



Anyone knows the solution?


Check pins with a scope. Ensure baud rate as expected. Perhaps output a long patterns of 'U' characters.

Ensure clocks are enabled and register content correct. Especially PP/AF settings

Test with code build with usual libraries, not custom, confirm that's working. The compare and contrast registers.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Karl Yamashita
Lead II

Upload your whole project. I have that same Nucleo board to test your code on.

Here is the project:

You just need to build the uart_tx.c from the Src folder:

Screenshot 2023-11-04 231822.png

I am not able to get your code to transmit to the outside world even when TDR is loaded with data. So it's something in your custom code that you've done incorrectly. With HAL UART driver it works just fine. See what the HAL driver does that you're not doing when initializing the UART.

I have found something, why when I just click Start debugging, the TXE Flag is already SET? The program is not yet executed even 1 line. Does that mean the communication is taken over by other process?