SystemInit()实现的功能
来源:互联网 发布:纸箱设计用什么软件 编辑:程序博客网 时间:2024/06/04 18:51
花了一天的时间,总算是了解了SystemInit()函数实现了哪些功能,初学STM32,,现记录如下(有理解错误的地方还请大侠指出):
使用的是3.5的库,用的是STM32F107VC,开发环境RVMDK4.23 我已经定义了STM32F10X_CL,SYSCLK_FREQ_72MHz 函数调用顺序:
startup_stm32f10x_cl.s(启动文件) → SystemInit() → SetSysClock () → SetSysClockTo72()
初始化时钟用到的RCC寄存器复位值:
RCC_CR = 0x0000 xx83; RCC_CFGR = 0x0000 0000;RCC_CIR = 0x0000 0000; RCC_CFGR2 = 0x0000 0000; SystemInit()
在调用 SetSysClock()之前RCC寄存器的值如下(都是一些与运算,或运算,在此就不赘述了):
RCC->CR = 0x0000 0083; RCC->CIR = 0x00FF0000; RCC->CFGR2 = 0x00000000;至于这些寄存器都代表着什么意思,详见芯片资料RCC寄存器,该文重点不在此处;
SetSysClock()函数如下:
static void SetSysClock(void) {
#ifdef SYSCLK_FREQ_HSE SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz //我的定义的是SYSCLK_FREQ_72MHz,所以调用SetSysClockTo72() SetSysClockTo72(); #endif }
SetSysClockTo72()函数如下:
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);
/* Wait till HSE is ready and if Time out is reached exit */ 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) {
/* 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;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2; #ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0) { }
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9); #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 */
/* 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 */ } }
1:AHB, APB1,APB2时钟确定
//HCLK = SYSCLK ,从下面的分析可以得出SYSCLK是使用PLLCLK时钟的,也就是72MHZ(至于72MHZ如何得来,请看下面分析) //那么就是HCLK(AHB总线时钟)=PLLCLK = 72MHZ //AHB总线时钟等于系统时钟SYSCLK,
//也就是 AHB时钟 = HCLK = SYSCLK = 72MHZ /* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
//PLCK2等于HCLK一分频, 所以PCLK2 = HCLK,HCLK = 72MHZ, //那么PLCK2(APB2总线时钟) = 72MHZ
//APB2总线时钟等于HCLK的一分频,也就是不分频; //APB2 时钟 = HCLK = SYSCLK = 72MHZ /* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
//PCLK1 = HCLK / 2;PCLK1 等于HCLK时钟的二分频, //那么PCLK1(APB1) = 72MHZ / 2 = 36MHZ
//APB1总线时钟等于HCLK的二分频,也就是 APB1时钟= HCLK / 2 = 36MHZ /* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
2:如何得出SYSCLK(系统时钟)为72MHZ(外部晶振25MHZ)
//记得参考英文芯片资料的时钟树P115页和RCC时钟寄存器进行理解
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8
|RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
RCC_CFGR2_PREDIV2_DIV5: PREDIV2 = 5; 5分频
也就是PREDIV2对输入的外部时钟 5分频,那么PLL2和PLL3没有倍频前 是25 /5 = 5MHZ
RCC_CFGR2_PLL2MUL8 : PLL2MUL = 8; 8倍频
8倍频后,PLL2时钟 = 5 * 8 = 40MHZ; 因此 PLL2CLK = 40MHZ RCC_CFGR2_PREDIV1SRC_PLL2 : RCC_CFGR2的第16位为1, 选择PLL2CLK 作为PREDIV1的时钟源
RCC_CFGR2_PREDIV1_DIV5:PREDIV1 = 5;PREDIV1对输入时钟5分频 PREDIV1CLK = PLL2CLK / 5 = 8MHZ
--------------------------------------------------------------------------------------
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
RCC_CFGR_PLLXTPRE_PREDIV1 :操作的是RCC_CFGR的第17位PLLXTPRE,操作这一位和操作RCC_CFGR2寄存器的
位[3:0]中的最低位是相同的
效果
RCC_CFGR_PLLSRC_PREDIV1 :选择PREDIV1输出作为PLL输入时钟;PREDIV1CLK = 8MHZ,所以输入给PLL倍频的
时钟源是8MHZ
RCC_CFGR_PLLMULL9 :PLLMUL = 9;PLL倍频系数为9,也就是对 PLLCL
K = PREDIV1CLK * 8 = 72MHZ
以上是对RCC_CFGR进行的配置
--------------------------------------------------------------------------------------- //选择PLLCLK作为系统时钟源
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
--------------------------------------------------------------------------------------- 至此基本配置已经完成,配置的时钟如下所述: SYSCLK(系统时钟) = 72MHZ AHB总线时钟 = 72MHZ APB1总线时钟 = 36MHZ APB2总线时钟 = 72MHZ PLL时钟 = 72MHZ PLL2时钟 = 40MHZ
- SystemInit()实现的功能
- SystemInit
- SystemInit()函数的结构分析
- STM32库函数SystemInit()的理解
- stm32的SystemInit()函数(转)
- STM32之SystemInit()函数的探讨
- HR8P506,哪里冒出来的SystemInit函数,用库函数点灯again.
- 翻页功能的实现
- 拖放功能的实现
- 撤消功能的实现
- 拖放功能的实现
- 抽屉功能的实现
- Tags功能的实现
- 实现数组的功能
- 实现系统托盘的功能
- 手推车”功能的实现
- 分页功能的实现
- 实现热键的功能
- Shell命令--怎么统计文本中第一列数据满足指定条件的行数
- C语言编程(练习3:循环,三大循环结构 )
- java.net 网络相关
- TIZEN RPM Package Guidelines
- spring 事务管理文档意译(3/5)
- SystemInit()实现的功能
- JS中根据出生日期计算年龄
- 牛人整理分享的面试知识:操作系统、计算机网络、设计模式、Linux编程,数据结构总结
- windos下启动、停止apache
- hdu 月之数
- [ERROR] mysqld: File './mysql-bin.~rec~' not found (Errcode: 13)解决方法
- hadoop(十一) - hadoop各版本集群环境搭建
- 恶意代码分析模板
- Android访问网络:服务端返回XML或JSON格式数据,Android 进行解析并使用ListView显示