一 时钟树功能框图理解
以前是system文件帮我们配置好72M的时钟,没有自己配置。现在学习RCC外设时钟配置。
RCC
:
reset clock control
复位和时钟控制器
RCC
主要作用—时钟部分:
设置系统时钟
SYSCLK
、设置
AHB
分频因子(决定
HCLK
等于多少)、设置
APB2
分
频因子(决定
PCLK2
等于多少)、设置
APB1
分频因子(决定
PCLK1
等于多少)、设置各
个外设的分频因子;控制
AHB
、
APB2
和
APB1
这三条总线时钟的开启、控制每个外设的时
钟的开启。对于
SYSCLK
、
HCLK
、
PCLK2
、
PCLK1
这四个时钟的配置一般是:
PCLK2 =
HCLK = SYSCLK=PLLCLK = 72M
,
PCLK1=HCLK/2 = 36M
。这个时钟配置也是库函数的标
准配置,我们用的最多的就是这个。
我们这里选取 库函数时 钟系统时钟函 数:
SetSysClockTo72();
以这个函数的编写流程来讲解时钟树,这个函数也是我们用库的时候
默认的系统时钟设置函数。该函数的功能是利用
HSE
把时钟设置为:
PCLK2 = HCLK =
SYSCLK = 72M
,
PCLK1=HCLK/2 = 36M
。下面我们就以这个代码的流程为主线,来分析
时钟树
①
HSE
高速外部时钟信号
HSE
是高速的外部时钟信号,可以由有源晶振或者无源晶振提供,频率从
4-16MHZ
不等。当使用有源晶振时,时钟从
OSC_IN
引脚进入,
OSC_OUT
引脚悬空,当选用无源
晶振时,时钟从
OSC_IN
和
OSC_OUT
进入,并且要配谐振电容。
HSE
最常使用的就是
8M
的无源晶振。当确定
PLL
时钟来源的时候,
HSE
可以不分频
或者
2
分频,这个由时钟配置寄存器
CFGR
的位
17
:
PLLXTPRE
设置,我们设置为
HSE
不分频。
②
PLL
时钟源
PLL
时钟来源可以有两个,一个来自
HSE
,另外一个是
HSI/2
,具体用哪个由时钟配
置寄存器
CFGR
的位
16
:
PLLSRC
设置。
HSI
是内部高速的时钟信号,频率为
8M
,根据
温度和环境的情况频率会有漂移,一般不作为
PLL
的时钟来源。这里我们选
HSE
作为
PLL
的时钟来源。
③
PLL
时钟
PLLCLK
通过设置
PLL
的倍频因子,可以对
PLL
的时钟来源进行倍频,倍频因子可以
是
:[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
,具体设置成多少,由时钟配置寄存器
CFGR
的位
21-18
:
PLLMUL[3:0]
设置。我们这里设置为
9
倍频,因为上一步我们设置
PLL
的时钟来源
为
HSE=8M
,所以经过
PLL
倍频之后的
PLL
时钟:
PLLCLK = 8M *9 = 72M
。
72M
是
ST
官方推荐的稳定运行时钟,如果你想超频的话,增大倍频因子即可,最高为
128M
。我们
这里设置
PLL
时钟:
PLLCLK = 8M *9 = 72M
。
④系统时钟
SYSCLK
系统时钟来源可以是:
HSI
、
PLLCLK
、
HSE
,具体的时钟配置寄存器
CFGR
的位
1-0
:
SW[1:0]
设置。我们这里设置系统时钟:
SYSCLK = PLLCLK = 72M
。
⑤
AHB
总线时钟
HCLK
系统时钟
SYSCLK
经过
AHB
预分频器分频之后得到时钟叫
APB
总线时钟,即
HCLK
,
分频因子可以是
:[1,2,4
,
8
,
16
,
64
,
128
,
256
,
512]
,具体的由时钟配置寄存器
CFGR
的位
7-4
:
HPRE[3:0]
设置。片上大部分外设的时钟都是经过
HCLK
分频得到,至于
AHB
总线上的外设的时钟设置为多少,得等到
我们使用该外设的时候才设置,我们这里只需粗
线条的设置好
APB
的时钟即可。我们这里设置为
1
分频,即
HCLK=SYSCLK=72M
。
⑥
APB2
总线时钟
HCLK2
APB2
总线时钟
PCLK2
由
HCLK
经过高速
APB2
预分频器得到,分频因子可以
是
:[1,2,4
,
8
,
16]
,具体由时钟配置寄存器
CFGR
的位
13-11
:
PPRE2[2:0]
决定。
HCLK2
属
于高速的总线时钟,片上高速的外设就挂载到这条总线上,比如全部的
GPIO
、
USART1
、
SPI1
等。至于
APB2
总线上的外设的时钟设置为多少,得等到我们使用该外设的时候才设
置,我们这里只需粗线条的设置好
APB2
的时钟即可。我们这里设置为
1
分频,即
PCLK2
= HCLK = 72M
。
⑦
APB1
总线时钟
HCLK1
APB1
总线时钟
PCLK1
由
HCLK
经过低速
APB
预分频器得到,分频因子可以是
:[1,2,4
,
8
,
16]
,具体的由时钟配置寄存器
CFGR
的位
10-8
:
PRRE1[2:0]
决定。
HCLK1
属于低速的总线时钟,最高为
36M
,片上低速的外设就挂载到这条总线上,比如
USART2/3/4/5
、
SPI2/3
,
I2C1/2
等。至于
APB1
总线上的外设的时钟设置为多少,得等到
我们使用该外设的时候才设置,我们这里只需粗线条的设置好
APB1
的时钟即可。我们这
里设置为
2
分频,即
PCLK1 = HCLK/2 = 36M
。
A
、
USB
时钟
USB
时钟是由
PLLCLK
经过
USB
预分频器得到,分频因子可以是:
[1,1.5]
,具体的由
时钟配置寄存器
CFGR
的位
22
:
USBPRE
配置。
USB
的时钟最高是
48M
,根据分频因子
反推过来算,
PLLCLK
只能是
48M
或者是
72M
。一般我们设置
PLLCLK=72M
,
USBCLK=48M
。
USB
对时钟要求比较高,所以
PLLCLK
只能是由
HSE
倍频得到,不能使
用
HSI
倍频。
B
、
Cortex
系统时钟
Cortex
系统时钟由
HCLK 8
分频得到,等于
9M
,
Cortex
系统时钟用来驱动内核的系统
定时器
SysTick
,
SysTick
一般用于操作系统的时钟节拍,也可以用做普通的定时。
C
、
ADC
时钟
ADC
时钟由
PCLK2
经过
ADC
预分频器得到,分频因子可以是
[2,4,6,8]
,具体的由时
钟配置寄存器
CFGR
的位
15-14
:
ADCPRE[1:0]
决定。很奇怪的是怎么没有
1
分频。
ADC
时钟最高只能是
14M
,如果采样周期设置成最短的
1.5
个周期的话,
ADC
的转换时间可以
达到最短的
1us
。如果真要达到最短的转换时间
1us
的话,那
ADC
的时钟就得是
14M
,反
推
PCLK2
的时钟只能是:
28M
、
56M
、
84M
、
112M
,鉴于
PCLK2
最高是
72M
,所以只能
取
28M
和
56M
。
C
、
ADC
时钟
ADC
时钟由
PCLK2
经过
ADC
预分频器得到,分频因子可以是
[2,4,6,8]
,具体的由时
钟配置寄存器
CFGR
的位
15-14
:
ADCPRE[1:0]
决定。很奇怪的是怎么没有
1
分频。
ADC
时钟最高只能是
14M
,如果采样周期设置成最短的
1.5
个周期的话,
ADC
的转换时间可以
达到最短的
1us
。如果真要达到最短的转换时间
1us
的话,那
ADC
的时钟就得是
14M
,反
推
PCLK2
的时钟只能是:
28M
、
56M
、
84M
、
112M
,鉴于
PCLK2
最高是
72M
,所以只能
取
28M
和
56M
。
D
、
RTC
时钟、独立看门狗时钟
RTC
时钟可由
HSE/128
分频得到,也可由低速外部时钟信号
LSE
提供,频率为
32.768KHZ
,也可由低速内部时钟信号
HSI
提供,具体选用哪个时钟由备份域控制寄存器
BDCR
的位
9-8
:
RTCSEL[1:0]
配置。独立看门狗的时钟由
LSI
提供,且只能是由
LSI
提供,
LSI
是低速的内部时钟信号,频率为
30~60KHZ
直接不等,一般取
40KHZ
。
E
、
MCO
时钟输出
MCO
是
microcontroller clock output
的缩写,是微控制器时钟输出引脚,在
STM32 F1
系列中 由
PA8
复用所得,主要作用是可以对外提供时钟,相当于一个有源晶振。
MCO
的
时钟来源可以是:
PLLCLK/2
、
HSI
、
HSE
、
SYSCLK
,具体选哪个由时钟配置寄存器
CFGR
的位
26-24
:
MCO[2:0]
决定。除了对外提供时钟这个作用之外,我们还可以通过示
波器监控
MCO
引脚的时钟输出来验证我们的系统时钟配置是否正确。
二 实现时钟系统时钟库函数编程
1.官方寄存器配置时钟
1 static void SetSysClockTo72(void)
2 {
3 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
4
5 // ① 使能 HSE,并等待 HSE 稳定
6 RCC->CR |= ((uint32_t)RCC_CR_HSEON);
7
8 // 等待 HSE 启动稳定,并做超时处理
9 do {
10 HSEStatus = RCC->CR & RCC_CR_HSERDY;
11 StartUpCounter++;
12 } while ((HSEStatus == 0)
&&(StartUpCounter !=HSE_STARTUP_TIMEOUT));
13
14 if ((RCC->CR & RCC_CR_HSERDY) != RESET) {
15 HSEStatus = (uint32_t)0x01;
16 } else {
17 HSEStatus = (uint32_t)0x00;
18 }
19 // HSE 启动成功,则继续往下处理
20 if (HSEStatus == (uint32_t)0x01) {
21
22 //-----------------------------------------------------------
23 // 使能 FLASH 预存取缓冲区 */
24 FLASH->ACR |= FLASH_ACR_PRFTBE;
25
26 // SYSCLK 周期与闪存访问时间的比例设置,这里统一设置成 2
27 // 设置成 2 的时候,SYSCLK 低于 48M 也可以工作,如果设置成 0 或者 1 的时候,
28 // 如果配置的 SYSCLK 超出了范围的话,则会进入硬件错误,程序就死了
29 // 0:0 < SYSCLK <= 24M
30 // 1:24< SYSCLK <= 48M
31 // 2:48< SYSCLK <= 72M */
32 FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
33 FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
34 //------------------------------------------------------------
35
36 // ② 设置 AHB、APB2、APB1 预分频因子
37 // HCLK = SYSCLK
38 RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
39 //PCLK2 = HCLK
40 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
41 //PCLK1 = HCLK/2
42 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
43
44 // ③ 设置 PLL 时钟来源,设置 PLL 倍频因子,PLLCLK = HSE * 9 = 72 MHz
45 RCC->CFGR &= (uint32_t)((uint32_t)
46 ~(RCC_CFGR_PLLSRC
47 | RCC_CFGR_PLLXTPRE
48 | RCC_CFGR_PLLMULL));
49 RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
50 | RCC_CFGR_PLLMULL9);
51
52 // ④ 使能 PLL
53 RCC->CR |= RCC_CR_PLLON;
54
55 // ⑤ 等待 PLL 稳定
56 while ((RCC->CR & RCC_CR_PLLRDY) == 0) {
57 }
58
59 // ⑥ 选择 PLL 作为系统时钟来源
60 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
61 RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
62
63 // ⑦ 读取时钟切换状态位,确保 PLLCLK 被选为系统时钟
64 while ((RCC->CFGR&(uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08){
65 }
66 } else {// 如果 HSE 启动失败,用户可以在这里添加错误代码出来
67 }
68 }
2.自己用rcc固件库配置系统时钟:采用HSE与HSI两种方案提供系统时钟
使用
HSE
一般情况下,我们都是使用
HSE
,然后
HSE
经过
PLL
倍频之后作为系统时钟。通常
的配置是:
HSE=8M
,
PLL
的倍频因子为:
9
,系统时钟就设置成
:SYSCLK = 8M * 9 = 72M
。
使用
HSE
,系统时钟
SYSCLK
最高是
128M
。我们使用的库函数就是这么干的, 当程序来
到
main
函数之前,启动文件:
statup_stm32f10x_hd.s
已经调用
SystemInit()
函数把系统时钟
初始化成
72MHZ
,
SystemInit()
在库文件:
system_stm32f10x.c
中定义。如果我们想把系统
时钟设置低一点或者超频的话,可以修改底层的库文件,但是为了维持库的完整性,我们
可以根据时钟树的流程自行写一个。
使用
HSI
当
HSE
故障的时候,如果
PLL
的时钟来源是
HSE
,那么当
HSE
故障的时候,不仅
HSE
不能使用,连
PLL
也会被关闭,这个时候系统会自动切换
HSI
作为系统时钟,此时
SYSCLK=HSI=8M
,如果没有开启
CSS
和
CSS
中断的话,那么整个系统就只能在低速率运
行,这是系统跟瘫痪没什么两样。如果开启了
CSS
功能的话,那么可以当
HSE
故障时,在
CSS
中断里面采取补救措施,使用
HSI
,并把系统时钟设置为更高的频率,最高是
64M
,
64M
的频率足够一般的外设使用,如:
ADC
、
SPI
、
I2C
等。但是这里就又有一个问题了,
原来
SYSCLK=72M
,现在因为故障改成
64M
,那么那些外设的时钟肯定被改变了,那么外
设工作就会被打乱,那我们是不是在设置
HSI
时钟的时候,也重新调整外设总线的分频因
子,即
AHB
,
APB2
和
APB1
的分频因子,使外设的时钟达到跟
HSE
没有故障之前一样。
但是这个也不是最保障的办法,毕竟不能一直使用
HSI
,所以当
HSE
故障时还是要采取报
警措施。
还有一种情况是,有些用户不想用
HSE
,想用
HSI
,但是又不知道怎么用
HSI
来设置
系统时钟,因为调用库函数都是使用
HSE
,下面我们给出个使用
HSI
配置系统时钟例子,
起个抛砖引玉的作用
编程要点对应着时钟树图中的序号。
1
、开启
HSE/HSI
,并等待
HSE/HSI
稳定
2
、设置
AHB
、
APB2
、
APB1
的预分频因子
3
、设置
PLL
的时钟来源,和
PLL
的倍频因子,设置各种频率主要就是在这里设置
4
、开启
PLL
,并等待
PLL
稳定
5
、把
PLLCK
切换为系统时钟
SYSCLK
6
、读取时钟切换状态位,确保
PLLCLK
被选为系统时钟
#ifndef __RCC_H
#define __RCC_H
#include "stm32f10x.h"
void HSE_SetSysClock(uint32_t pllmul);
void MCO_GPIO_Config(void);
void HSI_SetSysClock(uint32_t pllmul);
#endif
#include "rcc.h"
/*
* 使用HSE时,设置系统时钟的步骤
* 1、开启HSE ,并等待 HSE 稳定
* 2、设置 AHB、APB2、APB1的预分频因子
* 3、设置PLL的时钟来源,和PLL的倍频因子,设置各种频率主要就是在这里设置
* 4、开启PLL,并等待PLL稳定
* 5、把PLLCK切换为系统时钟SYSCLK
* 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟
*/
/* 设置 系统时钟:SYSCLK, AHB总线时钟:HCLK, APB2总线时钟:HCLK2, APB1总线时钟:PCLK1
* PCLK2 = HCLK = SYSCLK
* PCLK1 = HCLK/2,最高只能是36M
* 参数说明:pllmul是PLL的倍频因子,在调用的时候可以是:RCC_PLLMul_x , x:[2,3,...16]
* 举例:User_SetSysClock(RCC_PLLMul_9); 则设置系统时钟为:8MHZ * 9 = 72MHZ
* User_SetSysClock(RCC_PLLMul_16); 则设置系统时钟为:8MHZ * 16 = 128MHZ,超频慎用
*
* HSE作为时钟来源,经过PLL倍频作为系统时钟,这是通常的做法
*/
void HSE_SetSysClock(uint32_t pllmul)
{
__IO uint32_t StartUpCounter = 0, HSEStartUpStatus = 0;
RCC_DeInit();// 把RCC外设初始化成复位状态
RCC_HSEConfig(RCC_HSE_ON);//使能HSE,开启外部晶振,开发板用的是8M
HSEStartUpStatus = RCC_WaitForHSEStartUp();// 等待 HSE 启动稳定
if (HSEStartUpStatus == SUCCESS)// 只有 HSE 稳定之后则继续往下执行
{
// 这两句是操作FLASH闪存用到的,如果不操作FLASH的话,这两个注释掉也没影响
// 使能FLASH 预存取缓冲区
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
// SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
// 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
// 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
// 0:0 < SYSCLK <= 24M
// 1:24< SYSCLK <= 48M
// 2:48< SYSCLK <= 72M
//配置三条总线分频因子
RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB预分频因子设置为1分频,HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); // APB2预分频因子设置为1分频,PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div2); // APB1预分频因子设置为1分频,PCLK1 = HCLK/2
//-----------------设置各种频率主要就是在这里设置-------------------//
// 设置PLL时钟来源为HSE,设置PLL倍频因子
// PLLCLK = 8MHz * pllmul 通过参数传递,一般8倍评率
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, pllmul);
RCC_PLLCmd(ENABLE);// 开启PLL
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)// 等待 PLL稳定
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
while (RCC_GetSYSCLKSource() != 0x08)// 读取时钟切换状态位,确保PLLCLK被选为系统时钟
{
}
}
else
{ // 如果HSE开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
// 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,HSI是内部的高速时钟,8MHZ
while (1)
{
}
}
}
void MCO_GPIO_Config(void){
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_Out_PP;//复用推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
GPIO_Init(GPIOA,&GPIO_InitStruct);
}
/*
* 使用HSI时,设置系统时钟的步骤,用内部时钟意义不大
* 1、开启HSI ,并等待 HSI 稳定
* 2、设置 AHB、APB2、APB1的预分频因子
* 3、设置PLL的时钟来源,和PLL的倍频因子,设置各种频率主要就是在这里设置
* 4、开启PLL,并等待PLL稳定
* 5、把PLLCK切换为系统时钟SYSCLK
* 6、读取时钟切换状态位,确保PLLCLK被选为系统时钟
*/
/* 设置 系统时钟:SYSCLK, AHB总线时钟:HCLK, APB2总线时钟:HCLK2, APB1总线时钟:PCLK1
* PCLK2 = HCLK = SYSCLK
* PCLK1 = HCLK/2,最高只能是36M
* 参数说明:pllmul是PLL的倍频因子,在调用的时候可以是:RCC_PLLMul_x , x:[2,3,...16]
* 举例:User_SetSysClock(RCC_PLLMul_9); 则设置系统时钟为:4MHZ * 9 = 36MHZ
* User_SetSysClock(RCC_PLLMul_16); 则设置系统时钟为:4MHZ * 16 = 64MHZ
*
* HSI作为时钟来源,经过PLL倍频作为系统时钟,这是在HSE故障的时候才使用的方法
* HSI会因为温度等原因会有漂移,不稳定,一般不会用HSI作为时钟来源,除非是迫不得已的情况
* 如果HSI要作为PLL时钟的来源的话,必须二分频之后才可以,即HSI/2,而PLL倍频因子最大只能是16
* 所以当使用HSI的时候,SYSCLK最大只能是4M*16=64M
*/
void HSI_SetSysClock(uint32_t pllmul)
{
__IO uint32_t HSIStartUpStatus = 0;
RCC_DeInit();// 把RCC外设初始化成复位状态
RCC_HSICmd(ENABLE);//使能HSI
HSIStartUpStatus = RCC->CR & RCC_CR_HSIRDY; // 等待 HSI 就绪
if (HSIStartUpStatus == RCC_CR_HSIRDY)// 只有 HSI就绪之后则继续往下执行
{
//----------------------------------------------------------------------//
// 这两句是操作FLASH闪存用到的,如果不操作FLASH的话,这两个注释掉也没影响
// 使能FLASH 预存取缓冲区
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
// SYSCLK周期与闪存访问时间的比例设置,这里统一设置成2
// 设置成2的时候,SYSCLK低于48M也可以工作,如果设置成0或者1的时候,
// 如果配置的SYSCLK超出了范围的话,则会进入硬件错误,程序就死了
// 0:0 < SYSCLK <= 24M
// 1:24< SYSCLK <= 48M
// 2:48< SYSCLK <= 72M
RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB预分频因子设置为1分频,HCLK = SYSCLK
RCC_PCLK2Config(RCC_HCLK_Div1); // APB2预分频因子设置为1分频,PCLK2 = HCLK
RCC_PCLK1Config(RCC_HCLK_Div2);// APB1预分频因子设置为1分频,PCLK1 = HCLK/2
//-----------------设置各种频率主要就是在这里设置-------------------//
// 设置PLL时钟来源为HSE,设置PLL倍频因子
// PLLCLK = 4MHz * pllmul
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, pllmul);//规定只能二分屏
RCC_PLLCmd(ENABLE);// 开启PLL
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) // 等待 PLL稳定
{
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);// 当PLL稳定之后,把PLL时钟切换为系统时钟SYSCLK
while (RCC_GetSYSCLKSource() != 0x08) // 读取时钟切换状态位,确保PLLCLK被选为系统时钟
{
}
}
else
{ // 如果HSI开启失败,那么程序就会来到这里,用户可在这里添加出错的代码处理
// 当HSE开启失败或者故障的时候,单片机会自动把HSI设置为系统时钟,HSI是内部的高速时钟,8MHZ
while (1)
{
}
}
}
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "rcc.h"
//系统设置超频成128M,观察灯闪速快慢,发现变快了。
//或者用示波器验证PA8引脚输出128M
//系统设置超频成64M,观察灯闪速快慢,发现变慢了。
//或者用示波器验证PA8引脚输出64M
void delay(uint32_t count){
for(;count!=0;count--);
}
int main(void)
{
LED0_GPIO_Config();
KEY0_GPIO_Config();
//HSE_SetSysClock(RCC_PLLMul_16);//我们不配置时钟默认72M,这里我们用HSE配置系统时钟超频128M
HSI_SetSysClock(RCC_PLLMul_16);//我们不配置时钟默认72M,这里我们用HSI配置系统设置4*16M
MCO_GPIO_Config();
RCC_MCOConfig(RCC_MCO_SYSCLK);
while (1){
GPIO_SetBits(LED0_GPIO_PORT, LED0_GPIO_PIN5);
LED0(ON);
delay(0xfffff);
GPIO_ResetBits(LED0_GPIO_PORT, LED0_GPIO_PIN5);
LED0(OFF);
delay(0xfffff);
}
}