Author Topic: STM32F302R8 USART Register does not match with Reference Manual  (Read 5377 times)

0 Members and 1 Guest are viewing this topic.

Offline Glenn0010Topic starter

  • Regular Contributor
  • *
  • Posts: 214
  • Country: mt
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #25 on: May 17, 2019, 01:32:40 pm »
If you are using Nucleo board you don't have to solder external XTAL with supporting components to the board. You can use 8MHz clock from ST-LINK.

Argh that did not come in my mind. I've already moved solder bridges around and put on a 16MHz XTAL so I'll just do that now
 

Offline Glenn0010Topic starter

  • Regular Contributor
  • *
  • Posts: 214
  • Country: mt
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #26 on: May 17, 2019, 01:36:46 pm »
So I've had a look at my scope and here are the results.

The RX line i.e. PC baud rate, exactly 9600:



The TX line i.e. uC baud rate, 8928.57 = 7% error:



Therefore the uC baud rate is obviously off. I will change to the external XTAL and update you. Thanks everyone for your help!
 

Offline Glenn0010Topic starter

  • Regular Contributor
  • *
  • Posts: 214
  • Country: mt
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #27 on: May 19, 2019, 02:35:03 pm »
So I have been trying to get the UART to work for a while and after looking at the lines with scope, I discovered the the uart is twice the Baud rate I programmed it to and I don't know why.

 

So I am running my uC of a 16MHz external crystal dividing that by 2 to get 8MHz at PLL input. Multiplying that by 9 to get 72MHz SYSCLK and then dividing that by 2 to get 36MHz APB1 clock which is the maximum.

 

After I do this I stole a function from the STDPherif Libraries to check that the clocks are indeed what I set them to and they are correct PCLK1 is 36MHz.

 

With the R8, the USART 2 clock source can only be PCLK1 as indicated by the datasheet and it cannot be changed.

 

Hence then I set my Baud rate by plugging in the following into the BRR register. 36000000/9600. However the baud rate comes out twice as fast.

 

So that means either:

 

1 - APB1 is running off 72MHz which is outside is spec

2 - The clock source for the UART2 is being used as the SYSCLK

 

Here is the code:

Code: [Select]
/*---------------------------------------------------------------------------------------------------------------

12/5/2019

SysCroeClock = 64Mhz

Blinky
ADC scaninng 2 channels continously in DMA Mode 1.5 conversiion cycles at 64Mhz
UART2 with interrupt running on clock of 32MHz  at 9600 baud
---------------------------------------------------------------------------------------------------------------*/




#include "stm32f302x8.h"
 //----------------- Gloobal Variables -------------------------------------------------------------------------
uint16_t ADC_Samples[2] = {0,0};
void Delay (uint32_t nTime);
uint16_t ADC1ConvertedValue = 0;
uint16_t ADC1ConvertedVoltage = 0;
int calibration_value = 0;
volatile uint32_t TimingDelay = 0;
int x =0;
int CoreClock = 0;


static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};

 uint32_t tmp = 0, presc = 0; 
 uint32_t hcklf = 0, pckl1f= 0;


int init ()
{

//---------------------- RCC Clock Initalization ------------------------------------------------------------------

RCC->CR |= RCC_CR_HSEON; //HSE on
while((RCC->CR & RCC_CR_HSERDY) != RCC_CR_HSERDY); // Waiting for HSE to be ready

RCC->CR &= ~RCC_CR_PLLON; // Disable PLL
while((RCC->CR & RCC_CR_PLLRDY)== RCC_CR_PLLRDY); // Wait for pll to turn off
RCC->CFGR2 = RCC_CFGR2_PREDIV_DIV2;
RCC->CFGR = RCC_CFGR_PLLSRC_HSE_PREDIV  | RCC_CFGR_PLLMUL9 |  RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 ;//PLLSCR = HSE/2 , PLLMUL = x9 (72Mhz),AHB prescaler not devided, APB1 Clock /2  = 36MHz (Max=36MHz)
RCC->CR |= 0x01000000; // Turn on PLL on
while((RCC->CR & RCC_CR_PLLRDY) != RCC_CR_PLLRDY); // Waiting for PLL to be ready
FLASH->ACR |= FLASH_ACR_LATENCY_1; // Adjust flash speed for new frequency
RCC->CFGR |= RCC_CFGR_SW_1; // Set PLL as system clock
while((RCC->CFGR & RCC_CFGR_SWS_1) != RCC_CFGR_SWS_1); // Wait fpr pll to be used as syste, clock



//---------------------- Blinky Initialization ----------------------------------------------------------------

RCC->AHBENR |= (1<<18); //Enabling AHB GPIOB

  GPIOB->MODER |= 0x00000010; // PB2 Output
GPIOB->OSPEEDR |= 0x0; // Low speed output on all of port B
  GPIOB->PUPDR |= 0x30; // PB2 pull down


//----------------------- Checking System Clock ---------------------------------------------------------------
  SystemCoreClockUpdate(); // Calculating new system clock
CoreClock = SystemCoreClock;

tmp = RCC->CFGR & RCC_CFGR_HPRE;
  tmp = tmp >> 4;
  presc = APBAHBPrescTable[tmp];
  /* HCLK clock frequency */
  hcklf = CoreClock >> presc;

  tmp = RCC->CFGR & RCC_CFGR_PPRE1;;
  tmp = tmp >> 8;
  presc = APBAHBPrescTable[tmp];
  /* PCLK1 clock frequency */
  pckl1f = hcklf >> presc;


/*while (CoreClock != 72000000) // Error Handling
{
GPIOB->BSRR = (1<<2) ;
}*/

//------------------------------------ UART Enable -------------------------------------
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // Enabling USART2 Clock
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;    // Enabling Port A

GPIOA->MODER |= GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1;  // Setting PA2, PA3 as alternate function mode
GPIOA->AFR[0] = 0x7700; // Alternate Functions USART 2 For PA2, PA3
 
USART2->CR1 &= ~USART_CR1_M;
  USART2->BRR = pckl1f/9600; // 36MHz / 9600
USART2->CR2 = 0x0;
USART2->CR1 |= USART_CR1_UE ;
USART2->CR1 |= USART_CR1_TE | USART_CR1_RE |  USART_CR1_RXNEIE; 
 
NVIC_EnableIRQ(USART2_IRQn); // Enabling USART2 interrupt



return(0);

}
int main()
{

init();

while (1)
{

  GPIOB->BSRR = (1<<2) ;
for ( x = 0; x<500000; x++)
{
}
GPIOB->BSRR = (1<<(2+16));
for ( x = 0; x<500000; x++)
{
}

USART2->TDR = 0x55;
  while (!(USART2->ISR & USART_ISR_TC)){};


}
}

void USART2_IRQHandler(void)
{
  if(USART2->ISR & USART_ISR_RXNE)
{
char temp = USART2->RDR;
USART2->TDR = 0x55;
while (!(USART2->ISR & USART_ISR_TC)){};
}

}


Really appreciate any help
 

Offline Freddie Chopin

  • Regular Contributor
  • *
  • Posts: 71
  • Country: pl
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #28 on: May 19, 2019, 03:29:05 pm »
Start with small steps. For example, as a first iteration, don't configure any system clock at all - you should then be running of a HSI 8MHz. Configure USART to this clock and see with the scope whether the baudrate is more-or-less correct. Then just set your clock to HSE, configure UART properly and see whether the baudrate is what you expect. Then maybe enable APB divider by 2 and repeat. Then set PREDIV/2. Then enable PLL, as the last step.

SystemCoreClockUpdate() proves nothing, as it requires proper global definition of HSE_VALUE - do you have it set to 16000000? Please also note that SystemCoreClock is the HCLK, so your calculation of HCLK from this value are actually redundant and correct only because there is no divider. I would just ignore this function, as using it in your code adds just another unknown variable to the whole picture.

One step at a time and you will have it sorted within an hour.

BTW - are you sure there is no code in your project which does automatic clock configuration, which would - for example - set USART2 clock to SYSCLK? Startup codes which come from ST usually call a function called SystemInit() which actually does set the clock...

If you have a debugger, post the values of RCC and USART2 registers.
 

Offline Glenn0010Topic starter

  • Regular Contributor
  • *
  • Posts: 214
  • Country: mt
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #29 on: May 19, 2019, 04:30:07 pm »
Start with small steps. For example, as a first iteration, don't configure any system clock at all - you should then be running of a HSI 8MHz. Configure USART to this clock and see with the scope whether the baudrate is more-or-less correct. Then just set your clock to HSE, configure UART properly and see whether the baudrate is what you expect. Then maybe enable APB divider by 2 and repeat. Then set PREDIV/2. Then enable PLL, as the last step.

SystemCoreClockUpdate() proves nothing, as it requires proper global definition of HSE_VALUE - do you have it set to 16000000? Please also note that SystemCoreClock is the HCLK, so your calculation of HCLK from this value are actually redundant and correct only because there is no divider. I would just ignore this function, as using it in your code adds just another unknown variable to the whole picture.

One step at a time and you will have it sorted within an hour.


I did update the HSE_VALUE to reflect what I have but that did not fix it.

However I did as you said, started working my way backwards and found the mistake. I had it was in line 44 and 43. I removed the CFGR 2 line and added the following to line 44  | RCC_CFGR_PLLXTPRE_HSE_PREDIV_DIV2. That was my main issue.

I also had another little mistake in the last while loop of the RCC Init but that was not the issue.

I was setting CFGR2 as the pre div inas seen below, as it says it is the same as CFGR, however when I set CFGR1 instead and removed the statement of CFGR2 it all worked well.  A bit confusing but figured it out now thanks to your help.




Edit: On second thought I had tried the PLLXTPRE thing before and it didin't work so I think it was the change in definition and putting PLLXTPRE in again together
« Last Edit: May 19, 2019, 04:35:24 pm by Glenn0010 »
 

Offline Freddie Chopin

  • Regular Contributor
  • *
  • Posts: 71
  • Country: pl
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #30 on: May 19, 2019, 04:57:15 pm »
Quote
I was setting CFGR2 as the pre div inas seen below, as it says it is the same as CFGR, however when I set CFGR1 instead and removed the statement of CFGR2 it all worked well.  A bit confusing but figured it out now thanks to your help.
This is because the first bit of CFGR2 and the bit in CFGR are really just one and the same bit. Therefore here you set this one-and-the-same-bit:

   RCC->CFGR2 = RCC_CFGR2_PREDIV_DIV2;

And in the next line you clear it back to zero:

   RCC->CFGR = RCC_CFGR_PLLSRC_HSE_PREDIV  | RCC_CFGR_PLLMUL9 |  RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 ;//PLLSCR = HSE/2 , PLLMUL = x9 (72Mhz),AHB

It would be OK if you would first set CFGR and only then modify CFGR2.
 
The following users thanked this post: Glenn0010

Offline Glenn0010Topic starter

  • Regular Contributor
  • *
  • Posts: 214
  • Country: mt
Re: STM32F302R8 USART Register does not match with Reference Manual
« Reply #31 on: May 20, 2019, 06:27:45 pm »
Quote
I was setting CFGR2 as the pre div inas seen below, as it says it is the same as CFGR, however when I set CFGR1 instead and removed the statement of CFGR2 it all worked well.  A bit confusing but figured it out now thanks to your help.
This is because the first bit of CFGR2 and the bit in CFGR are really just one and the same bit. Therefore here you set this one-and-the-same-bit:

   RCC->CFGR2 = RCC_CFGR2_PREDIV_DIV2;

And in the next line you clear it back to zero:

   RCC->CFGR = RCC_CFGR_PLLSRC_HSE_PREDIV  | RCC_CFGR_PLLMUL9 |  RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 ;//PLLSCR = HSE/2 , PLLMUL = x9 (72Mhz),AHB

It would be OK if you would first set CFGR and only then modify CFGR2.

Thanks so much for your continued help
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf