跟踪进入该函数,可见一连串的条件编译:
单步运行,执行的是:
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
为何执行该行呢,找到SYSCLK_PREQ_**的相关定义,如下图所示。
这样就得到了我们所要的一个结论:如果要更改系统工作频率,只需要在这里更改就可以了。
可以继续跟踪进入这个函数来观察如何将工作频率设定为72MHz的。
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC-》CR |= ((uint32_t)RCC_CR_HSEON);
//开启HSE
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC-》CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
//等待HSE确实可用,这有个标志,即RCC_CR寄存器中的HSERDY位(bit 17),这个等待不会无限长,有个超时策略,即每循环一次计数器加1,如果计数的次数超过HSEStartUp_TimeOut,就退出循环,而这个HSEStartUp_TimeOut在stm32f10x.h中定义,
#define HSEStartUp_TimeOut ((uint16_t)0x0500) /*!《 Time out for HSE start up */
///////////////////////////////////////////////////////////////////////////////////////////////
if ((RCC-》CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
///再次判断HSERDY标志位,并据此给HSEStatus变量赋值。
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH-》ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH-》ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH-》ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC-》CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
//找到定义: #define RCC_CFGR_HPRE_DIV1 ((uint32_t)0x00000000) /*!《 SYSCLK not divided */
/* PCLK2 = HCLK */
RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
//找到定义:#define RCC_CFGR_PPRE2_DIV1 ((uint32_t)0x00000000) /*!《 HCLK not divided */
/* PCLK1 = HCLK */
RCC-》CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
//找到定义:#define RCC_CFGR_PPRE1_DIV2 ((uint32_t)0x00000400) /*!《 HCLK divided by 2 */
#ifdef STM32F10X_CL
……
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC-》CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC-》CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */
//以上是设定PLL的倍频系数为9,也就是说,这个72M是在外部晶振为8M时得到的。
/* 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)0x08)
{
}
}
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 */
/* Go to infinite loop */
while (1)
{
}
}
}
至此,我们可以归纳几条:
(1) 时钟源有3个
(2) 开机时默认是HSI起作用,可以配置为所要求的任意一个时钟
(3) 配置时必须按一定的顺序来打开或都关闭一些位,并且各时钟起作用有一定的时间,因此要利用芯片内部的标志位来判断是否可以执行下一步。
(4) 如果外部时钟、PLL输出失效,系统可以自动回复到HSI(开启时钟安全系统)
(5) HSI的频率准确度可以达到+/- 1%,如果有必要时,还可以用程序来调整这个频率,可调的范围大致在200KHz左右。
最后让我们来感受一下劳动的果实吧--试着改改频率看有何反应。
为查看更改后的效果,先记录更改前的数据。将调试切换到仿真,在第一条:
Delay(0xAFFFF);
指令执行前后,分别记录下Status和Sec
Status:2507 3606995
Sec:0.00022749 0.05028982
将振荡频率更改为36MHz,即
。。.
#define SYSCLK_FREQ_36MHz 36000000 //去掉该行的注释
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
/*#define SYSCLK_FREQ_72MHz 72000000*/ //将该行加上注释
再次运行,结果如下:
Status:2506 3606994
Sec:0.00008478 0.10036276
基本上是延时时间长了一倍。改成硬件仿真,将代码写入板子,可以看到LED闪烁的频率明显变慢了。
评论
查看更多