STM32
STM32 HSE初始化失败的原因是什么?怎么解决?
回帖(1)
2021-12-16 10:52:48
偶然遇到一个问题,假设HSE初始化失败怎么办,库函数内没有提供处理只是写了
if (HSEStatus == (uint32_t)0x01)
{
。。。
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
让我们自己处理。平常我们都是用SysClk =72M。这是在HSE的情况下才能达到的。如果HSE初始化不成功只能使用HSI。注意上图时钟树HSI想使用PLL要2分频。这样才4M的频率。PLL倍频16也才64M。没有达到我们常用的72M。这样如果我们设置HSI并且16倍频像定时器等外设就要重新计算频率。(UARTx如果使用库函数是不需要自己计算波特率的,库函数内部会自己计算,这点不用担心)。用HSE时又要计算72M的对应数据,想想挺麻烦。为了方便在满足系统运行速度的情况下。我可以设置HSE通过PLLXTPRE位2分频然后PLL16倍频这样SYSCLK就达到64M。如果初始化HSE成功SYSCLK为64M,如果HSE初始化失败继续初始化HSI。这样一来无论内部时钟还是外部时钟都会是64M。
将代码贴在此处方便以后查看
u16 nCount = 0;
ErrorStatus HSEStartUpStatus;
//时钟管理重置
RCC_DeInit();
//打开外部晶振
RCC_HSEConfig(RCC_HSE_ON);
//等待外部晶振就绪
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET && nCount++ < HSE_STARTUP_TIMEOUT);
//等待外部晶振就绪
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if (HSEStartUpStatus == SUCCESS)
{
//flash读取缓冲, 加速
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//flash操作的延时
FLASH_SetLatency(FLASH_Latency_2);
//-----------------------------------------------------------------
//AHB使用系统时钟
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//注:AHB主要负责外部存储器时钟。
//PB2负责AD, I/O, 高级TIM, 串口1
//APB2(高速)为HCLK
RCC_PCLK2Config(RCC_HCLK_Div1);
//APB1负责DA, USB, SPI, I2C, CAN, 串口2345, 普通TIM
//APB1(低速)为HCLK的一半
RCC_PCLK1Config(RCC_HCLK_Div2);
//???
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
//倍频设置---------------------------------------------------------
*(vu32 *)0x40022000 = 0x01;
//PLLCLK = 8MHZ/2 *16 = 64MHZ
RCC_PLLConfig (RCC_PLLSource_HSE_Div2, RCC_PLLMul_16);
//启动PLL
RCC_PLLCmd(ENABLE);
//等待PLL启动
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//将PLL设置为系统时钟源
RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);
//等待系统时钟源的启动
while (RCC_GetSYSCLKSource() != 0x08);
}
//HSE初始化失败,初始化内部HSI
else
{
RCC_HSEConfig(RCC_HSE_OFF);
//时钟管理重置
RCC_DeInit();
//打开内部晶振
RCC_HSICmd(ENABLE);
//等待内部晶振就绪
nCount = 0;
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET && nCount++ < HSE_STARTUP_TIMEOUT );
//flash读取缓冲, 加速
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//flash操作的延时
FLASH_SetLatency(FLASH_Latency_2);
//AHB使用系统时钟 64M
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//注:AHB主要负责外部存储器时钟。
//PB2负责AD, I/O, 高级TIM, 串口1
//APB2(高速)为HCLK 64M
RCC_PCLK2Config(RCC_HCLK_Div1);
//APB1负责DA, USB, SPI, I2C, CAN, 串口2345, 普通TIM
//APB1(低速)为HCLK的一半 32M
RCC_PCLK1Config(RCC_HCLK_Div2);
//PLLCLK = 8MHZ/2 *16 = 64MHZ
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);
//启动PLL
RCC_PLLCmd(ENABLE);
//将PLL设置为系统时钟源 64M
RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);
//等待系统时钟源的启动
while (RCC_GetSYSCLKSource() != 0x08);
}
PS:如果使用SYSTICK注意此时的时钟频率是64M
void ConfigSysTick(void)
{
//SysTick时钟源为AHB HCLK时钟除以8, 即72/8 = 9MHZ
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//SysTick_Config(SystemCoreClock / 1000);
SysTick_Config(64000000 /1000);
}
偶然遇到一个问题,假设HSE初始化失败怎么办,库函数内没有提供处理只是写了
if (HSEStatus == (uint32_t)0x01)
{
。。。
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
让我们自己处理。平常我们都是用SysClk =72M。这是在HSE的情况下才能达到的。如果HSE初始化不成功只能使用HSI。注意上图时钟树HSI想使用PLL要2分频。这样才4M的频率。PLL倍频16也才64M。没有达到我们常用的72M。这样如果我们设置HSI并且16倍频像定时器等外设就要重新计算频率。(UARTx如果使用库函数是不需要自己计算波特率的,库函数内部会自己计算,这点不用担心)。用HSE时又要计算72M的对应数据,想想挺麻烦。为了方便在满足系统运行速度的情况下。我可以设置HSE通过PLLXTPRE位2分频然后PLL16倍频这样SYSCLK就达到64M。如果初始化HSE成功SYSCLK为64M,如果HSE初始化失败继续初始化HSI。这样一来无论内部时钟还是外部时钟都会是64M。
将代码贴在此处方便以后查看
u16 nCount = 0;
ErrorStatus HSEStartUpStatus;
//时钟管理重置
RCC_DeInit();
//打开外部晶振
RCC_HSEConfig(RCC_HSE_ON);
//等待外部晶振就绪
while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET && nCount++ < HSE_STARTUP_TIMEOUT);
//等待外部晶振就绪
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if (HSEStartUpStatus == SUCCESS)
{
//flash读取缓冲, 加速
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//flash操作的延时
FLASH_SetLatency(FLASH_Latency_2);
//-----------------------------------------------------------------
//AHB使用系统时钟
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//注:AHB主要负责外部存储器时钟。
//PB2负责AD, I/O, 高级TIM, 串口1
//APB2(高速)为HCLK
RCC_PCLK2Config(RCC_HCLK_Div1);
//APB1负责DA, USB, SPI, I2C, CAN, 串口2345, 普通TIM
//APB1(低速)为HCLK的一半
RCC_PCLK1Config(RCC_HCLK_Div2);
//???
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
//倍频设置---------------------------------------------------------
*(vu32 *)0x40022000 = 0x01;
//PLLCLK = 8MHZ/2 *16 = 64MHZ
RCC_PLLConfig (RCC_PLLSource_HSE_Div2, RCC_PLLMul_16);
//启动PLL
RCC_PLLCmd(ENABLE);
//等待PLL启动
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
//将PLL设置为系统时钟源
RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);
//等待系统时钟源的启动
while (RCC_GetSYSCLKSource() != 0x08);
}
//HSE初始化失败,初始化内部HSI
else
{
RCC_HSEConfig(RCC_HSE_OFF);
//时钟管理重置
RCC_DeInit();
//打开内部晶振
RCC_HSICmd(ENABLE);
//等待内部晶振就绪
nCount = 0;
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET && nCount++ < HSE_STARTUP_TIMEOUT );
//flash读取缓冲, 加速
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//flash操作的延时
FLASH_SetLatency(FLASH_Latency_2);
//AHB使用系统时钟 64M
RCC_HCLKConfig(RCC_SYSCLK_Div1);
//注:AHB主要负责外部存储器时钟。
//PB2负责AD, I/O, 高级TIM, 串口1
//APB2(高速)为HCLK 64M
RCC_PCLK2Config(RCC_HCLK_Div1);
//APB1负责DA, USB, SPI, I2C, CAN, 串口2345, 普通TIM
//APB1(低速)为HCLK的一半 32M
RCC_PCLK1Config(RCC_HCLK_Div2);
//PLLCLK = 8MHZ/2 *16 = 64MHZ
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);
//启动PLL
RCC_PLLCmd(ENABLE);
//将PLL设置为系统时钟源 64M
RCC_SYSCLKConfig (RCC_SYSCLKSource_PLLCLK);
//等待系统时钟源的启动
while (RCC_GetSYSCLKSource() != 0x08);
}
PS:如果使用SYSTICK注意此时的时钟频率是64M
void ConfigSysTick(void)
{
//SysTick时钟源为AHB HCLK时钟除以8, 即72/8 = 9MHZ
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
//SysTick_Config(SystemCoreClock / 1000);
SysTick_Config(64000000 /1000);
}
举报
更多回帖