参考文章 :http://blog.csdn.net/kevinhg/article/details/17517117
关于 STM32 的时钟, 一共有 5 个时钟源 : HSI、HSE、LSI、LSE、PLL
1、 HSI :高速内部时钟, RC 振荡器, 频率为 8MHz
2、 HSE :高速外部时钟, 可接石英/陶瓷谐振器, 或者接外部时钟源, 频率范围4~16M
3、 LSI :低速内部时钟, RC 振荡器, 频率为 40KHz
4、 LSE :低速外部时钟, 接 32.768KHz 的石英晶体
5、 PLL :锁相环倍频输出, 时钟输入源可选择为HSI/2、HSE 或者 HSE/2。倍频范围 2~16 倍。对于
Cortex-M3 系列, 频率最大频率输出不能超过 72MHz
二、在 STM32 上如果不使用外部晶振,OSC_IN 和 OSC_OUT 的接法 :
如果使用内部 RC 振荡器而不使用外部晶振,请按照下面方法处理 :
① 对于 100 脚或 144 脚的产品, OSC_IN 应接地, OSC_OUT 应悬空。
② 对于少于 100 脚的产品, 有 2 种接法 :
第 1 种 :OSC_IN 和 OSC_OUT 分别通过 10K 电阻接地。此方法可提高 EMC 性能;
第 2 种 :分别重映射 OSC_IN 和 OSC_OUT 至 PD0 和 PD1, 再配置 PD0 和 PD1 为推
挽输出并输出 '0'。此方法可以减小功耗并(相对上面)节省 2 个外部电阻。
三、用 HSE 时钟, 程序设置时钟参数流程:
01、将 RCC 寄存器重新设置为默认值 RCC_DeInit;
02、打开外部高速时钟晶振 HSE RCC_HSEConfig(RCC_HSE_ON);
03、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp();
04、设置 AHB 时钟 RCC_HCLKConfig;
05、设置高速 AHB 时钟 RCC_PCLK2Config;
06、设置低速速 AHB 时钟 RCC_PCLK1Config;
07、设置 PLL RCC_PLLConfig;
08、打开 PLL RCC_PLLCmd(ENABLE);
09、等待 PLL 工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
10、设置系统时钟 RCC_SYSCLKConfig;
11、判断是否 PLL 是系统时钟 while(RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟
四、下面是 STM32 软件固件库的程序中对 RCC 的配置函数(使用外部 8MHz 晶振)
/****************************************************************
* Function Name : RCC_Configuration
* Description : RCC配置(使用外部8MHz晶振)
****************************************************************/
void RCC_Configuration(void)
{
/*将外设RCC寄存器重设为缺省值*/
RCC_DeInit();
/*设置外部高速晶振(HSE)*/
RCC_HSEConfig(RCC_HSE_ON); //RCC_HSE_ON——HSE晶振打开(ON)
/*等待HSE起振*/
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS) //SUCCESS:HSE晶振稳定且就绪
{
/*设置AHB时钟(HCLK)*/
RCC_HCLKConfig(RCC_SYSCLK_Div1); //RCC_SYSCLK_Div1——AHB时钟= 系统时钟
/* 设置高速AHB时钟(PCLK2)*/
RCC_PCLK2Config(RCC_HCLK_Div1); //RCC_HCLK_Div1——APB2时钟= HCLK
/*设置低速AHB时钟(PCLK1)*/
RCC_PCLK1Config(RCC_HCLK_Div2); //RCC_HCLK_Div2——APB1时钟= HCLK / 2
/*设置FLASH存储器延时时钟周期数*/
FLASH_SetLatency(FLASH_Latency_2); //FLASH_Latency_2 2延时周期
/*选择FLASH预取指缓存的模式*/
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); // 预取指缓存使能
/*设置PLL时钟源及倍频系数*/
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
// PLL的输入时钟= HSE时钟频率;RCC_PLLMul_9——PLL输入时钟x 9
/*使能PLL */
RCC_PLLCmd(ENABLE);
/*检查指定的RCC标志位(PLL准备好标志)设置与否*/
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
/*设置系统时钟(SYSCLK)*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
//RCC_SYSCLKSource_PLLCLK——选择PLL作为系统时钟
/* PLL返回用作系统时钟的时钟源*/
while(RCC_GetSYSCLKSource() != 0x08); //0x08:PLL作为系统时钟
}
/*使能或者失能APB2外设时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC , ENABLE);
}
STM32F103 内部 8M 的内部震荡,经过倍频后最高可以达到 72M。目前 TI 的 M3 系列芯片最高频率可以达到 80M。在 stm32 固件库 3.0 中对时钟频率的选择进行了大大的简化,原先的一大堆操作都在后台进行。系统给出的函数为 SystemInit()。但在调用前还需要进行一些宏定义的设置, 具体的设置在
system_stm32f10x.c文件中。文件开头就有一个这样的定义:
//#define SYSCLK_FREQ_HSE HSE_Value
//#define SYSCLK_FREQ_20MHz 20000000
//#define SYSCLK_FREQ_36MHz 36000000
//#define SYSCLK_FREQ_48MHz 48000000
//#define SYSCLK_FREQ_56MHz 56000000
#define SYSCLK_FREQ_72MHz 72000000
ST 官方推荐的外接晶振是 8M,所以库函数的设置都是假定你的硬件已经接了 8M 晶振来运算的.以上东西就是默认晶振 8M 的时候,推荐的 CPU 频率选择.在这里选择了:
#define SYSCLK_FREQ_72MHz 72000000
也就是 103 系列能跑到的最大值 72M
#elif defined SYSCLK_FREQ_72MHz
const uint32_t SystemFrequency = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_SysClk = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_AHBClk = SYSCLK_FREQ_72MHz;
const uint32_t SystemFrequency_APB1Clk = SYSCLK_FREQ_72MHz/2;
const uint32_t SystemFrequency_APB2Clk = SYSCLK_FREQ_72MHz;
这就是在定义了 CPU 跑 72M 的时候, 各个系统的速度了. 他们分别是 : 硬件频率, 系统时钟,AHB 总线
频率, APB1 总线频率, APB2 总线频率.再往下看,看到这个了:
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
这就是定义 72M 的时候,设置时钟的函数.这个函数被 SetSysClock ()函数调用,而 SetSysClock ()
函数则是被 SystemInit()函数调用.最后 SystemInit()函数,就是被你调用的了
所以设置系统时钟的流程就是:
首先用户程序调用 SystemInit()函数,这是一个库函数,然后 SystemInit()函数里面,进行了一些寄存器
必要的初始化后,就调用 SetSysClock()函数.SetSysClock()函数根据那个
#define SYSCLK_FREQ_72MHz 72000000 的宏定义,知道了要调用 SetSysClockTo72() 这个函数,于是,
就一堆麻烦而复杂的设置~!@#$%^然后,CPU跑起来了,而且速度是 72M. 虽然说的有点累赘,但大家只需要知道,用
户要设置频率,程序中就做的就两个事情:
第一个 : system_stm32f10x.c 中 #defineSYSCLK_FREQ_72MHz 72000000
第二个 : 调用 SystemInit()