最近用到了STM32F051C8T6这款芯片,没有外接晶振,使用的是内部时钟,工程是参考网上以及论坛教程弄的。资料说定时器的时钟达48MHz,我测试定时器时,48MHz进行48分频,使用1MHz来产生定时时间,但是定时时间死活不对,刚开始以为是自己配置出错了,所以重新检查了好几次代码,仍然不能解决问题。
没办法,只能按照所得的波形进行倒推,计算得到定时器的时钟为8MHz,然后往上慢慢寻找问题所在,最终在system_stm32f0xx.c文件里面看到下面这么一段话:
* 5. This file configures the system clock as follows:
*=============================================================================
*=============================================================================
* System Clock source | PLL(HSE)
*-----------------------------------------------------------------------------
* SYSCLK(Hz) | 48000000
*-----------------------------------------------------------------------------
* HCLK(Hz) | 48000000
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB Prescaler | 1
*-----------------------------------------------------------------------------
* HSE Frequency(Hz) | 8000000
*----------------------------------------------------------------------------
* PLLMUL | 6
*-----------------------------------------------------------------------------
* PREDIV | 1
*-----------------------------------------------------------------------------
* Flash Latency(WS) | 1
*-----------------------------------------------------------------------------
* Prefetch Buffer | ON
*-----------------------------------------------------------------------------
******************************************************************************
再往下找找,看到SetSysClock()这个函数,函数内部如下
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/******************************************************************************/
/* PLL (clocked by HSE) used as System clock source */
/******************************************************************************/
/* SYSCLK, HCLK, PCLK configuration ----------------------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer and set Flash Latency */
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
/* PLL configuration */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL)
{
}
}
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 */
}
可见,函数的主时钟来自于外部时钟,但是我的小板子却没有接外部时钟,所以系统的主时钟不对,定时自然就出问题。后来在网上看到一位好心网友分享他的设置过程,将上面的代码替换为下面的即可。
RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_12);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08)
{
}
最后分享一个小插曲,定时器正常以后,还进行了ADC采样测试,但是ADC的值一直不对,这个问题困扰了我很久,刚开始也是怀疑软件问题(哈哈,本人对硬件不是擅长,出问题基本是从软件开始寻找),后面发现配置没问题,拿官网的例子来测试也出错,所以不得不检查硬件了,好家伙,居然是芯片的VDDA没接电源,VSSA没接地。幸运的是,接上电源和地以后,一切正常。