I'm trying to configure the baudrate of USART1 on an STM32L152. When using the external Clock the baudrate is half of what I configured (e.g. 57600 instead of 115200). However, when using the internal HSI everything is correct. The internal is 16 MHz and the external is an 8 MHz crystal that is used to drive the PLL for a 32 MHz system clock.
This is the RCC init code, which is pretty much standard I guess.
int RCC_Configuration(void)
{
/* DISABLE HSI and target clocks prior to clock config */
RCC_HSICmd(DISABLE);
RCC_PLLCmd(DISABLE);
RCC_HSEConfig(RCC_HSE_OFF);
/* Set HSE as sys clock*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE);
/* Enable ADC & SYSCFG clocks */
RCC_APB2Periph_SYSCFG , ENABLE);
/* Allow access to the RTC */
PWR_RTCAccessCmd(ENABLE);
/* Reset RTC Backup Domain */
RCC_RTCResetCmd(ENABLE);
RCC_RTCResetCmd(DISABLE);
/* LSI used as RTC source clock */
/* The RTC Clock may varies due to LSI frequency dispersion. */
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait until LSE is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable the RTC */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
// ENABLE HSE
RCC_HSEConfig(RCC_HSE_ON);
ErrorStatus HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
/* 32Mhz = 8Mhz * 12 / 3 */
RCC_PLLConfig(RCC_PLLSource_HSE, RCC_PLLMul_12, RCC_PLLDiv_3);
/* Enable PLL */
RCC_PLLCmd(ENABLE);
/* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
/* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x0C) // 0x0C = PLL
{
}
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR->CR = PWR_CR_VOS_0; /* Select the Voltage Range 1 (1.8V) */
while((PWR->CSR & PWR_CSR_VOSF) != 0); /* Wait for Voltage Regulator Ready */
/* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1);
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);
/* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1);
/* Enable the GPIOs clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC| RCC_AHBPeriph_GPIOD| RCC_AHBPeriph_GPIOE| RCC_AHBPeriph_GPIOH, ENABLE);
/* Enable comparator, LCD and PWR mngt clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_COMP | RCC_APB1Periph_LCD | RCC_APB1Periph_PWR,ENABLE);
}
return 0;
}
I'm using STDperiph to configure the UART1, which on this mcu will run on PCLK2. Checked all the init methods and the register contents. The mantissa and fraction of the baudrate register are correctly calculated and should yield the correct baud rate no matter what the PCLK value is.
This is the UART init code:
void usartinit(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitStructure.USART_BaudRate = 115200 ;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
/* Enable GPIO clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(USARTx_GPIO, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(USARTx_GPIO, GPIO_PinSource10, GPIO_AF_USART1);
/* Configure USART Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Pin = USARTx_TX;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(USARTx_GPIO, &GPIO_InitStructure);
/* Configure USART Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = USARTx_RX;
GPIO_Init(USARTx_GPIO, &GPIO_InitStructure);
/* USART configuration */
USART_Init(USART1, &USART_InitStructure);
/* Enable USART */
USART_Cmd(USART1, ENABLE);
}
The only possibility I can think of right now is that the crystal is just 4 MHz, but this is a Nucleo board and the MCO from the attached STLink is used for HSE, which definitely is 8 MHz.
What's the blatant mistake I'm making?
HSEStartUpStatus == SUCCESS
inRCC_Configuration
- if not you will be running on the HSI unexpectedly. Dumping the USART and RCC registers will help diagnostics - you might add those to the question. Finally you might step the baudUSART_Init()
function in your debugger to see where it might be using incorrect constants. If I where where you are that is what I'd be doing, and is necessary information I think to diagnose remotely. – Clifford