cancel
Showing results for 
Search instead for 
Did you mean: 

Not getting output via USART2 of STM32F401RE nucleo board

Lalit26
Associate II

Hi All,

I have written a baremetal code to initialize the USART2 of STM32F401RE and print HELLO WORLD. The code does not use HAL and rather accesses and writes to USART2 peripheral registers using the C pointers. I have cross verified the code multiple times and have tried multiple methods to get the print, but I am not seeing any output on the teraterm/puTTY. 

I even used USB-TTL cable for this purpose by connecting the PA2 and PA3 (on the ST-Morpho connector) to TTL's cable Rx and Tx pin respectively. But there is no output. What can be the reason? Below is my code:

#include "stdint.h" #include "stm32f4xx.h" #include "string.h" typedef struct{ volatile uint32_t REG_MODER; volatile uint32_t REG_OTYPER; volatile uint32_t REG_PUPDR; volatile uint32_t REG_IDR; volatile uint32_t REG_ODR; volatile uint32_t REG_AFR[2]; }GPIO_REG_DEF; typedef struct{ volatile uint32_t REG_SR; volatile uint32_t REG_DR; volatile uint32_t REG_BRR; volatile uint32_t REG_CR1; volatile uint32_t REG_CR2; volatile uint32_t REG_CR3; }USART_REG_DEF; /*Create a pointer of type GPIO_REG_DEF pointing to base address of GPIOA*/ #define GPIO_BASE_ADDR 0x40020000 #define GPIO_A ((GPIO_REG_DEF *)GPIO_BASE_ADDR) /*Create pointers of type volatile uint32_t to point to respective registers in the RCC*/ #define AHB1_ADDR (*(volatile uint32_t *)(0x40023800+0x30)) #define APB1_ADDR (*(volatile uint32_t *)(0x40023800+0x40)) /*Create pointers of type USART_REG_DEF pointing to base address of USART2*/ #define USART_BASE_ADDR 0x40004400 #define USART_2 ((USART_REG_DEF *)USART_BASE_ADDR) /*Create an alias for USART pins*/ #define USART_TX_PIN 2 #define USART_RX_PIN 3 /*Create an alias for USART registers' bits*/ #define USART_EN (1<<13) #define USART_OVER8 (1<<15) #define USART_STOP_BITS (0x3<<12) #define USART_WORD_LEN (1<<12) #define USART_PARITY_CTRL (1<<10) #define USART_PARITY_TYPE (1<<9) #define USART_TX_EN (1<<3) #define USART_RX_EN (1<<2) #define USART_BR ((0x16<<4) | (0xD & 0xFF)) #define TXE (1<<7) #define TC (1<<6) #define RXNE (1<<5) #define SEND_MSG "HELLO WORLD" /*Function to set up the clock for GPIOA and USART2*/ void clockSet(){ AHB1_ADDR |= 1; APB1_ADDR |= (1<<17); } /*Function to initialize the UART Tx and Rx pins*/ void gpioConfig(){ /*Configure GPIOA pin2 and pin3 in alternate function mode to use it as an UART*/ GPIO_A->REG_MODER &= ~(0x3<<(2*USART_TX_PIN) | 0x3<<(2*USART_RX_PIN)); GPIO_A->REG_MODER |= (0x2<<(2*USART_TX_PIN) | 0x2<<(2*USART_RX_PIN)); GPIO_A->REG_AFR[0] |= (7<<(4*USART_TX_PIN)| 7<<(4*USART_RX_PIN)); GPIO_A->REG_OTYPER &= ~(0x1<<USART_TX_PIN | 0x1<<USART_RX_PIN); GPIO_A->REG_PUPDR &= ~(0x3<<(2*USART_TX_PIN) | 0x3<<(2*USART_RX_PIN)); } /*Function to initialize the USART*/ void usart_init(){ USART_2->REG_CR1 &= ~USART_EN; USART_2->REG_CR1 &= ~USART_OVER8; //RESET the OVER8 bit in CR1 for oversampling=16 USART_2->REG_CR2 &= ~USART_STOP_BITS; //Configure number of stop bits=1 USART_2->REG_CR1 &= ~USART_WORD_LEN; //Configure the word length (1 start bit+8 data bits+1 stop bits) USART_2->REG_CR1 &= ~USART_PARITY_CTRL; //Disable parity control USART_2->REG_CR1 |= USART_TX_EN; //enable the transmit driver path USART_2->REG_CR1 |= USART_RX_EN; //ENABLE the receive driver path USART_2->REG_BRR = USART_BR; //SET the baud rate to 115200 USART_2->REG_CR1 |= USART_EN; //Enable the USART2 } void send_data(){ unsigned char ch; int i=0; while(i != strlen(SEND_MSG)){ ch = SEND_MSG[i]; while(!(USART_2->REG_SR & TXE)); USART_2->REG_DR = ch; i++; } while(!(USART_2->REG_SR & TC)); } int main(){ clockSet(); gpioConfig(); usart_init(); send_data(); while(1); }
View more

Can anyone please help me to get this working?

Thanks,

Lalit.

4 REPLIES 4

Sanity test with HAL, even if you choose to do it this way. There's a LOT of non-optimal code in your example

Have you checked signal with scope?

Baud rate looks wrong. What was the goal?

Default HSI clock is 8 MHz for F401

#define USART_BR (8000000 / 9600)

#define USART_BR (HSI_VALUE / 9600)

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

I didn't check signal with scope.

My goal for baud rate is 115200. I calculated the DIV_MANTISSA and DIV_FRACTION using formula:

USART_DIV = (APB1 clock freq)/(16*115200).

The integer part of USART DIV was placed into DIV_MANTISSA and the (decimal part*16)  was placed into DIV_FRACTION. Is this the correct calculation?

Thanks,

Lalit.

>>Is this the correct calculation?

Probably, but overly cumbersome. The 4-bit here dispenses with the *16

USART2->BRR = HSI_VALUE / 115200; // If still running from HSI

115200 from 8 MHz is 69 or 0x45 not 0x16D

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

>>The 4-bit here dispenses with the *16 : I didn't get this.

What is the difference between HSI clock and APB1 clock? I am directly using the APB1 clock.