STM32L152 UART 波特率减半使用 HSE
STM32L152 UART baudrate halfes using HSE
我正在尝试在 STM32L152 上配置 USART1 的波特率。使用外部时钟时,波特率是我配置的一半(例如 57600 而不是 115200)。然而,当使用内部 HSI 时,一切都是正确的。内部频率为 16 MHz,外部频率为 8 MHz crystal,用于驱动 32 MHz 系统时钟的 PLL。
这是 RCC 初始化代码,我想这是非常标准的。
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;
}
我正在使用 STDperiph 配置 UART1,在这个 mcu 上它将 运行 在 PCLK2 上。检查了所有的初始化方法和寄存器内容。波特率寄存器的尾数和小数部分计算正确,无论 PCLK 值是多少,都应该产生正确的波特率。
这是 UART 初始化代码:
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);
}
我现在唯一能想到的可能是 crystal 只有 4 MHz,但这是一块 Nucleo 板,附带的 STLink 的 MCO 用于 HSE,肯定是 8 MHz .
我犯的明显错误是什么?
时钟好像乱了。检查代码中的 HSE_VALUE 宏。这可能正在使用默认的 Dev board crystal 值。我建议将该值更改为您正在使用的 crystal 。您可以使用 this link 来设置时钟速度。
我认为前面的答案是正确的。使用 HSI 时,系统时钟为 16MHz,而使用 HSE 时,系统时钟为 32MHz。
我怀疑 HSE 值设置为 16MHz。
您还可以通过将乘数设置为 4 并将分频器设置为 2 来测试这一点,以便在 运行 HSE 时系统时钟为 16MHz。
HSE 值将在某处的启动代码中。
USART 代码使用该值,以便它知道 USART 的驱动频率,以便计算波特率。
好吧,终于想通了。在默认配置的 Nucleo 板上,HSE 时钟连接到板上 STLink 编程器的 MCO 时钟输出。然而,在我的多个电路板上,这个时钟信号失真太多,以至于目标 uC 只能看到 4 MHz。如果我在目标的 MCO 上输出 HSE,它会产生一个占空比为 75% 的 4 MHz 方波。使用示波器探测 MCO 输入信号时,探头电容足以产生正确的 8 MHz 输入。
所以,我想不要相信你的评估板......现在会得到一些晶体并填充这些板上的 "real" 外部时钟。
我正在尝试在 STM32L152 上配置 USART1 的波特率。使用外部时钟时,波特率是我配置的一半(例如 57600 而不是 115200)。然而,当使用内部 HSI 时,一切都是正确的。内部频率为 16 MHz,外部频率为 8 MHz crystal,用于驱动 32 MHz 系统时钟的 PLL。
这是 RCC 初始化代码,我想这是非常标准的。
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;
}
我正在使用 STDperiph 配置 UART1,在这个 mcu 上它将 运行 在 PCLK2 上。检查了所有的初始化方法和寄存器内容。波特率寄存器的尾数和小数部分计算正确,无论 PCLK 值是多少,都应该产生正确的波特率。
这是 UART 初始化代码:
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);
}
我现在唯一能想到的可能是 crystal 只有 4 MHz,但这是一块 Nucleo 板,附带的 STLink 的 MCO 用于 HSE,肯定是 8 MHz .
我犯的明显错误是什么?
时钟好像乱了。检查代码中的 HSE_VALUE 宏。这可能正在使用默认的 Dev board crystal 值。我建议将该值更改为您正在使用的 crystal 。您可以使用 this link 来设置时钟速度。
我认为前面的答案是正确的。使用 HSI 时,系统时钟为 16MHz,而使用 HSE 时,系统时钟为 32MHz。
我怀疑 HSE 值设置为 16MHz。
您还可以通过将乘数设置为 4 并将分频器设置为 2 来测试这一点,以便在 运行 HSE 时系统时钟为 16MHz。
HSE 值将在某处的启动代码中。
USART 代码使用该值,以便它知道 USART 的驱动频率,以便计算波特率。
好吧,终于想通了。在默认配置的 Nucleo 板上,HSE 时钟连接到板上 STLink 编程器的 MCO 时钟输出。然而,在我的多个电路板上,这个时钟信号失真太多,以至于目标 uC 只能看到 4 MHz。如果我在目标的 MCO 上输出 HSE,它会产生一个占空比为 75% 的 4 MHz 方波。使用示波器探测 MCO 输入信号时,探头电容足以产生正确的 8 MHz 输入。
所以,我想不要相信你的评估板......现在会得到一些晶体并填充这些板上的 "real" 外部时钟。