一、知识所限(以后学习再进一步整理)
/*
在头文件#include "stm32f10x.h"中选择了预处理指令USE_STDPERIPH_DRIVER,STM32F10X_MD
所以在启动文件system_stm32f10x.c中选择系统频率为72MHz
*/
#define SYSCLK_FREQ_72MHz 72000000
//中断向量不偏移
#define VECT_TAB_OFFSET 0x0
//时钟的定义:系统时钟频率(核心时钟)
#elif defined SYSCLK_FREQ_72MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz;
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
static void SetSysClock(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
#ifdef DATA_IN_ExtSRAM
static void SystemInit_ExtMemCtl(void);
#endif
void SystemInit (void)
{
//将RCC时钟配置重置为默认重置状态(用于调试目的)
//设置HSION位
RCC->CR |= (uint32_t)0x00000001;
//复位SW, HPRE, PPRE1, PPRE2, ADCPRE和MCO位
RCC->CFGR &= (uint32_t)0xF0FF0000;
//重置HSEON, CSSON和PLLON位
RCC->CR &= (uint32_t)0xFEF6FFFF;
//重置HSEBYP位
RCC->CR &= (uint32_t)0xFFFBFFFF;
//复位PLLSRC, PLLXTPRE, PLLMUL和USBPRE/OTGFSPRE位
RCC->CFGR &= (uint32_t)0xFF80FFFF;
//禁用所有中断并清除挂起的位
RCC->CIR = 0x009F0000;
/*
配置系统时钟频率、HCLK、PCLK2和PCLK1预分频器;
配置Flash Latency周期,并开启预取缓冲。
*/
SetSysClock();
#ifdef VECT_TAB_SRAM
//内部SRAM中的矢量表重定位。
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
//在内部FLASH矢量表重定位
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;
#endif
}
/*
根据时钟寄存器值更新SystemCoreClock变量。SystemCoreClock变量包含核心时钟(HCLK),它可以
由用户应用程序用来设置SysTick定时器或配置其他参数。
每次核心时钟(HCLK)改变时,必须调用这个函数更新SystemCoreClock变量值。否则,任何配置
基于此变量的将不正确。
由该函数计算出的系统频率不是真实的频率在芯片中。根据预定义值计算常数和所选时钟源:
如果SYSCLK source是HSI, SystemCoreClock将包含HSI_VALUE
如果SYSCLK source为HSE, SystemCoreClock将包含HSE_VALUE
如果SYSCLK源是PLL, SystemCoreClock将包含HSE_VALUE或HSI_VALUE乘以锁相环因子。
HSI_VALUE是stm32f1xx.h文件中定义的常量(默认值8mhz),但实际值可能会根据变化而变化电压和温度。
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0;
//获取SYSCLK源
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
//HSI作为系统时钟
case 0x00:
SystemCoreClock = HSI_VALUE;
break;
//HSE作为系统时钟
case 0x04:
SystemCoreClock = HSE_VALUE;
break;
//锁相环作为系统时钟
case 0x08:
//获得锁相环时钟源和乘法事实
pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
//计算HCLK时钟频率,获取HCLK预分频器
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
//HCLK时钟频率
SystemCoreClock >>= tmp;
}
//配置系统时钟频率、HCLK、PCLK2和PCLK1预分频器。
static void SetSysClock(void)
{
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
//如果上述定义均未启用,则使用HSI作为系统时钟源(重置后的默认值)
}
二、时钟配置
选择外部高速时钟HSE :8M,选择PLL为系统时钟:PLL=9*HSE=72M;APB:72M;APB1:36M;APB2:72M 。
#elif defined SYSCLK_FREQ_72MHz
//设置系统时钟频率为72MHz,并配置HCLK、PCLK2和PCLK1预压器。
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
//开启HSE
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
//等待,直到HSE准备好,如果超时到达出口
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)
{
//启用预取缓冲区
FLASH->ACR |= FLASH_ACR_PRFTBE;
// Flash 2等待状态
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;
// PCLK2 = HCLK
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
// PCLK1 = HCLK
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
// /* 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);
// 开启PLL
RCC->CR |= RCC_CR_PLLON;
// 等到锁相环准备好
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
// 选择“PLL”作为系统时钟源
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
// 等到锁相环作为系统时钟源
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{
//如果HSE启动失败,应用程序将出现错误时钟配置。用户可以在这里添加一些代码来处理此错误
}
}