STM32F0 Discovery USART sends the wrong value

1.6k views Asked by At

I'm making first steps in the STM32 world, and they are quite hard. I run my Discovery board. When I learnt how to control GPIO and interrupts from them I decided to play with USART. And here hell began. I've spent two evenings struggling with such a simple thing like serial communications!

What I have:

  • Configured GPIO
  • Configured USART
  • Clock from standard STM library - HSI 48 MHz
  • I see characters in PuTTY
  • Transmission parameters tested: 8N1 9600 and 115200

As you can see from the code, I'm expecting to see an 'A' character while I get '_'. In my opinion it is something with baud rate, but I get only this wrong character. When I change BRR to a completely wrong value it will display some junk characters.

Any idea is welcome!

#include <stm32f0xx.h>

void putC(uint8_t Character)
{
  while(!(USART1->ISR & USART_ISR_TXE))
    ;

  USART1->TDR = Character;
}

int main(void)
{
  int i;

  RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_SYSCFGCOMPEN;
  RCC->AHBENR |= (RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIOAEN);

  //ioSetup();
  GPIOA->MODER &= ~(GPIO_MODER_MODER9 | GPIO_MODER_MODER10);
  GPIOA->MODER |= (GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1);

  GPIOA->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEEDR9 | GPIO_OSPEEDR_OSPEEDR10);
  GPIOA->OSPEEDR |= (GPIO_OSPEEDR_OSPEEDR9_0 | GPIO_OSPEEDR_OSPEEDR10_0);

  GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPDR9 | GPIO_PUPDR_PUPDR10);
  GPIOA->PUPDR |= GPIO_PUPDR_PUPDR9_0 | GPIO_PUPDR_PUPDR10_0;

  GPIOA->AFR[1] |= (0x00000110);


  // USART
  USART1->BRR = (uint32_t)(48000000/9600);   // 9600

  //USART1->CR2 = 0;
  //USART1->CR3 = 0;
  //USART1->GTPR = 0;
  USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;

  for (i = 0; i < 0x1000; i++)
    __NOP();

  i = 0;

  for(;;) {
    putC('A');
  }

  return 0;
}
2

There are 2 answers

1
Freddie Chopin On

HSI is not a precise and not a stable clock. It has a big error related to temperature and the frequency in "perfect" temperature is not good either. If this "wrong" value is a few percent away from the value you calculated, then you can be 100% certain that the problem is HSI accuracy.

Your only choice would then be to use an external crystal. If your "wrong" value is a multiple of what you calculated (like 2, 4, 8 times smaller/bigger), then I guess you should take a good look at the code in SystemInit() that sets the clock.

0
PiotrK On

Solution: The output from the STM32F0 Discovery board is 3.0 V. It turned out to be not enough for the USB-to-RS-232 adapter. A simple circuit with MAX232 supplied with 5 V resolved the problem.

Case closed.