cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 trying to get uasart to transmit

benjamin Gräf
Associate II

Hello, I wanted to upgrade my simple blinky program with the usart 2, so that it sends a simple 'B' over the serial port to my PC. I am using a Nucleo-F334R8. In the datasheet it says usart2 is connected with the USB port.

Here is my code, that is not working because I do not receive anything on the pc side with terra term. The com port is there, by the way,

int main(void)

{

  // Enable Port A

  SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOAEN);

  // PA5 = LED output

  MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODER5, GPIO_MODER_MODER5_0);

  // PA2 = Tx of UART 2, set to alternative function

  MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODER2, GPIO_MODER_MODER2_1);

  //Enable USART2 clock

  SET_BIT(RCC->APB1ENR, RCC_APB1ENR_USART2EN);

  // Enable TX

  SET_BIT(USART2->CR1, USART_CR1_TE);

  // Use 1 start bit, 8 data bits

  CLEAR_BIT(USART2->CR1, USART_CR1_M1);

  CLEAR_BIT(USART2->CR1, USART_CR1_M0);

  // Set Baudrate to 9600 bit/s

  WRITE_REG(USART2->BRR, 0x341);

  // Use 1 stop bit

  CLEAR_BIT(USART2->CR2, USART_CR2_STOP_0);

  CLEAR_BIT(USART2->CR2, USART_CR2_STOP_1);

  // Enable the uart

  SET_BIT(USART2->CR1, USART_CR1_UE);

  // Send an idle frame at beginning

  SET_BIT(USART2->CR1, USART_CR1_TE);

  while(1)

  {

    // LED Pin -> High

  SET_BIT(GPIOA->BSRRL, GPIO_BSRR_BS_5);

  // Transmitt 'B' with uart

  WRITE_REG(USART2->TDR, 'B');

  // Wait for data to be moved from the TDR register to the shift register.

  // So new data can be put into the TDR register.

  while(!(READ_BIT(USART2->ISR, USART_ISR_TXE)));

    delay(50);

    // LED Pin -> Low

  SET_BIT(GPIOA->BSRRH, GPIO_BSRR_BS_5);

    delay(50);

  }

}

Any help is welcomed, thanks 🙂

4 REPLIES 4

You'd probably need to ensure you have the correct AF mapping set for the port via AFR

I'd advise spinning for TXE to go high BEFORE the write to TDR, not after.

Surely there are more efficient methods to program the registers? You have about a dozen more accesses than necessary.

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

Hi, I tryed using the while(!(READ_BIT(USART2->ISR, USART_ISR_TXE))); before writing data into the TDR register, did not help. Debugging it, I can see that the TXE Bit is always high, even directly after writing data into the TDR register.

The problem was the AFR register, a bit confusing but it works now. Thank you 🙂

Regarding the more effiecent way of writing into registers, yes there are better ways to do this (I guess you mean with structs) but I wanted to do it this way to better learn all the registers, and writing 0 to registers is probably not necesarry but I think that its on the safe side, since you can not assume the inital state of registers, or am i wrong?

thanks anyway

S.Ma
Principal

The datasheet tells for each HW register their reset value (0,1, undefined).

The peripheral can be SW reset (SYSCFG) or HW reset.

As Clive said, you don't set GPIOB_AFR for the Tx/Rx pins.

As first debug step, I recommend reading out and checking the content of relevant (here GPIO and USART) registers. In some cases you might've been hit with things like that in some STM32 models it takes time after enabling a peripheral's clock in RCC until you can actually write to given peripheral. Reviewing the registers' content reveals these, and sometimes also other inadvertent programming errors. The point is, that ultimately the mcu behaves according how the registers are actually set, not according to what the programmer thinks he did by writing and running the program.

Of course reading registers should be done cautiously, as reading some registers (particularly the UART/SPI status registers containing RXNE or similar bit) automatically change their state.

JW