时钟系统 寄存器
LinkedInSTM32F4 时钟系统初始化是在system_stm32f4xx.c中的 SystemInit()函数中完成的。 对于系统时钟关键寄存器设置主要是在 SystemInit 函数中调用 SetSysClock()函数来设置的。我们可以先看看 SystemInit ()函数体:
void SystemInit(void)
{
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB-》CPACR |= ((3UL 《《 10*2)|(3UL 《《 11*2));
#endif
RCC-》CR |= (uint32_t)0x00000001;
RCC-》CFGR = 0x00000000;
RCC-》CR &= (uint32_t)0xFEF6FFFF;
RCC-》PLLCFGR = 0x24003010;
RCC-》CR &= (uint32_t)0xFFFBFFFF;
RCC-》CIR = 0x00000000;
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB-》VTOR = SRAM_BASE | VECT_TAB_OFFSET;
#else
SCB-》VTOR = FLASH_BASE | VECT_TAB_OFFSET;
#endif
}
SystemInit函数开始先进行浮点运算单元设置,然后是复位PLLCFGR,CFGR寄存器,同时通过设置 CR 寄存器的 HSI 时钟使能位来打开 HSI 时钟。默认情况下如果 CFGR 寄存器复位,那么是选择HSI作为系统时钟,这点大家可以查看RCC-》CFGR 寄存器的位描述最低2位可以得知,当低两位配置为 00的时候(复位之后),会选择 HSI振荡器为系统时钟。也就是说,调用 SystemInit 函数之后,首先是选择 HSI 作为系统时钟。
在设置完相关寄存器后,接下来SystemInit函数内部会调用 SetSysClock函数。这个函数比较长,我们就把函数一些关键代码行截取出来给大家讲解一下。这里我们省略一些宏定义标识符值的判断而直接把针对STM32F407 比较重要的内容贴出来:
static void SetSysClock(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
RCC-》CR |= ((uint32_t)RCC_CR_HSEON);
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)
{
RCC-》APB1ENR |= RCC_APB1ENR_PWREN;
PWR-》CR |= PWR_CR_VOS;
RCC-》CFGR |= RCC_CFGR_HPRE_DIV1;
RCC-》CFGR |= RCC_CFGR_PPRE2_DIV2;
RCC-》CFGR |= RCC_CFGR_PPRE1_DIV4;
RCC-》CFGR |= RCC_CFGR_PPRE2_DIV1;
RCC-》CFGR |= RCC_CFGR_PPRE1_DIV2;
RCC-》PLLCFGR = PLL_M | (PLL_N 《《 6) | (((PLL_P 》》 1) -1) 《《 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q 《《 24);
RCC-》CR |= RCC_CR_PLLON;
while((RCC-》CR & RCC_CR_PLLRDY) == 0)
{
}
FLASH-》ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN
|FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
RCC-》CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC-》CFGR |= RCC_CFGR_SW_PLL;
while ((RCC-》CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
{
}
}
else
{
}
}
这段代码的大致流程是这样的:先使能外部时钟 HSE,等待 HSE 稳定之后,配置AHB,APB1,APB2 时钟相关的分频因子,也就是相关外设的时钟。等待这些都配置完成之后,打开主PLL时钟,然后设置主PLL作为系统时钟 SYSCLK时钟源。如果HSE 不能达到就绪状态(比如外部晶振不能稳定或者没有外部晶振),那么依然会是HSI作为系统时钟。
在这里要特别提出来,在设置主PLL时钟的时候,会要设置一系列的分频系数和倍频系数参数。大家可以从SetSysClock函数的这行代码看出:
RCC-》PLLCFGR = PLL_M | (PLL_N 《《 6) | (((PLL_P 》》 1) -1) 《《 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q 《《 24);
这些参数是通过宏定义标识符的值来设置的。默认的配置在 System_stm32f4xx.c 文件开头的地方配置。对于我们开发板,我们的设置参数值如下:
#define PLL_M 8
#define PLL_Q 7
#define PLL_N 336
#define PLL_P 2
所以我们的主PLL时钟为:
PLL=8MHz * N/ (M*P)=8MHz* 336 /(8*2) = 168MHz
在开发过程中,我们可以通过调整这些值来设置我们的系统时钟。
这里还有个特别需要注意的地方,就是我们还要同步修改 stm32f4xx.h 中宏定义标识符HSE_VALUE 的值为我们的外部时钟:
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)8000000)
#endif
这里默认固件库配置的是25000000,我们外部时钟为8MHz,所以我们根据我们硬件情况修改为8000000即可。
讲到这里,大家对 SystemInit 函数的流程会有个比较清晰的理解。那么 SystemInit 函数是怎么被系统调用的呢?SystemInit是整个设置系统时钟的入口函数。这个函数对于我们使用ST提供的 STM32F4 固件库的话,会在系统启动之后先执行main函数,然后再接着执行SystemInit函数实现系统相关时钟的设置。这个过程设置是在启动文件 startup_stm32f40_41xxx.s中间设置的,我们接下来看看启动文件中这段启动代码:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
这段代码的作用是在系统复位之后引导进入main函数,同时在进入main函数之前,首先
要调用 SystemInit系统初始化函数完成系统时钟等相关配置。
最后我们总结一下SystemInit()函数中设置的系统时钟大小:
SYSCLK(系统时钟) =168MHz
AHB总线时钟(HCLK=SYSCLK) =168MHz
APB1总线时钟(PCLK1=SYSCLK/4) =42MHz
APB2总线时钟(PCLK2=SYSCLK/2) =84MHz
PLL主时钟 =168MHz
上一篇:STM32CUBEMX开发GD32F303(7)----配置printf
下一篇:STM32F103C8T6读写内部flash
推荐阅读最新更新时间:2024-11-06 12:11
设计资源 培训 开发板 精华推荐
- LTC3265EFE 低噪声 +7V/-2V 电源的典型应用电路来自一个单端 5V 输入电源(频率 = 200kHz)
- UC2844B 电压反相电荷泵转换器的典型应用
- 使用 LTC2389HLX-18、18 位、2.5Msps SAR ADC 的典型应用
- MAXREFDES1099:采用MAX17690的93%效率的小尺寸24V/500mA、无光耦反激式DC-DC转换器
- LT3080EDD-1 演示板、1.1A 可调、单电阻器 LDO、稳压器与集成镇流电阻器并联
- NTAG I2C + Explorer套件,带NFC读卡器
- EVAL-AD7686SDZ,用于 AD7686BRMZ 10 引脚 MSOP 的 16 位、500 kSPS PulSAR ADC 评估板
- 基于Arduino的简易测光表 copy
- STM32F10xxx GPIO 应用示例,使用 STM32F10xxx SWJ-DP 引脚作为标准 I/O
- 使用带有集成电容式触摸模块和 RN42 蓝牙模块的 PIC16F15XX MCU 系列的连接温度计演示板
- TI 邀您填问卷赢好礼|私人定制专属你的 2019 工业应用方案
- 打造健康生活,成就强劲工具 TE Connectivity (TE) 智慧生活子系统解决方案
- 更好的供电方式:使用更小、更轻的电源模块加速车辆电气化
- 似兰斯馨,一个老电子工程师的点滴足迹
- 直播已结束|Molex 和 TTI 更小型、高速、可靠的连接器推动物联网应用的新发展
- Keysight教你如何提高测试精度,答对问题还有礼品相送,速速参与!
- 一起分享,共同成长!EEWORLD月月有奖优秀主题/回复第29期
- 宝藏电路图分享计划开启,学习拿奖两不误
- 【传感器,开玩啦】第一关:免费申请评测运动和环境传感器开发板
- 全新吉时利4200A SCS参数分析仪震撼上市,邀您参与翻盖有礼!