cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4: Issues with USART1 Configuration

bmblakeslee
Associate II
Posted on October 29, 2015 at 23:45

I'm currently experimenting with writing a driver for USART1 at the register level for the STM32F4 Discovery board. I've followed the initialization procedure on page 963 of RM0090; however, when I connect to my PC via my FTDI cable, all I get are junk characters. The LED blinks normally though, so I know I'm not blocking on the while loop that checks the TXE bit. I've also checked my HSE_VALUE, which is 8000000. I'm completely at a loss as to what I missed. How can I get this code running?

My source code:

#include ''stm32f4xx.h''
int main(int argc, char* argv[]){
// At this stage the system clock should have already been configured
// at high speed.
// Clock configuration
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Enable GPIOB clock
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // Enable USART1 clock
// GPIO configuration
GPIOB->MODER |= GPIO_MODER_MODER6_1; // Enable GPIOB alternate function on pin 6
GPIOB->MODER |= GPIO_MODER_MODER7_1; // Enable GPIOB alternate function on pin 7
GPIOB->AFR[0] |= 0x07000000; // Select USART1 alternate function (Find this mask)
GPIOB->AFR[0] |= 0x70000000; // Select USART1 alternate function (Find this mask)
GPIOB->OTYPER = 0; // Set GPIOA to push-pull
// USART configuration
USART1->CR1 |= USART_CR1_UE; // Enable USART1
USART1->CR1 &= ~USART_CR1_M; // Configure M bit for word length (8b)
USART1->CR2 &= ~USART_CR2_STOP; // Configure number of stop bits (1b)
USART1->CR3 &= ~USART_CR3_DMAT; // Configure DMA (disabled)
USART1->BRR |= HSE_VALUE / 9600; // Set baud rate
USART1->CR1 |= USART_CR1_TE; // Set transmit enable
// Blinky LED configuration
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Enable GPIOD clock
GPIOD->MODER |= GPIO_MODER_MODER12_0; // Enable GPIO output on port D, pin 12
for(int i = 0; i < 
10000000
; i++){
asm(''nop'');
}
// Infinite loop
while (1){
// Add your code here.
// Send some data!
while(!(USART1->SR & USART_SR_TXE));
USART1->DR = 'B'; // Send 'B'
GPIOD->ODR ^= GPIO_ODR_ODR_12; // Blink LED
for(int i = 0; i < 10000000; i++){
asm(''nop'');
}
}
}

#stm32-uart
6 REPLIES 6
Posted on October 30, 2015 at 00:43

There are electrical issues related to PA9/PA10 on the STM32F4-DISCO, review the schematic.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bmblakeslee
Associate II
Posted on October 30, 2015 at 01:14

Thanks!  I've changed my USART1 pins over to PB6 and PB7 and updated the code in my first post accordingly.  (I wish ST would have made it more obvious that those pins were used by an LED and a USB pin.)  However, now I get no data out from the STM32, not even junk characters.  The LED still blinks though...

Posted on October 30, 2015 at 03:12

There is a big table in the manual, and a schematic.

I'm not keen on this type of coding, but not seeing anything egregious. Make sure you aren't mixing the TX/RX sense. The TX on the STM32 is an output, TX of the USB-to-Serial is probably an output too, in which case you have to cross the connections.

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/USART1%20simple%20use%20problem&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=630

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/STM32F4%20why%20I%20cant%20comunicate%20with%20USART1&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&c...

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
vech2001
Associate II
Posted on October 30, 2015 at 14:54

The problem is at least here as far as I can see:

USART1->BRR |= HSE_VALUE / 9600; // Set baud rate

Baud rate is calculated in a bit more sophisticated way. If you're using a 16-point oversampling (it is so by default) you must use bits 15 to 4 as a mantissa of divider quotient, and bits 3 to 0 as a divider's fractional part, and that fractional part's LSB is 1/ Qucik and drity, the algorithm is:

float
q = (
float
)HSE/(16*9600);
// integer part of the quotient
int
int_part = 
floor
(q);
// fractional part of the quotient in 1/16ths, rounded to nearest 1/16th
int
frac_part = 
floor
((q-int_part)*16+.5);
// int part in upper 12 bits, frac part in lower 4 bits; 
// if fractional part is ''16'' then it automatically means the integer part 
// is increased to 1 and fractional part equals to 0
USART_BRR=(int_part<<4)+frac_part;

P.S. Hmm... It seems there's no need in all this maths if you're in a 16-bit oversampling mode, since in that case a simple HSE/baud_rate gives pretty much all the same result. Except maybe that rounding, but that won't give any serious difference.
Posted on October 30, 2015 at 16:13

I wouldn't OR the value in, you should be cognizant of how the register might be set up, assuming things are in some reset state will give you a lot of headaches.

Also will it be HSE? If the PLL or APB are setup properly, usually in SystemInit(), then the USART source clock will be that of the APB it's on, APB2 for USART1

For 16 over-sample mode, the math really is as easy as USART1->BRR = APB2CLK / 9600;
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bmblakeslee
Associate II
Posted on November 02, 2015 at 19:31

I found the issue.  It was caused by using the wrong clock to set up the BRR register.  It should be USART1->BRR = APB2CLK / 9600;  However, digging through the HAL library code, I found a handy macro that I think I'm going to use.