一、背景
  最近做个项目,需要使用STM32,还是以前一样的观点,时钟就是MCU心脏,供血即时钟频率输出,想要弄明白一个MCU,时钟是一个非常好的切入点。言归正传,网上已经有太多大神详述过STM32的详细配置方法了,在此就简单介绍下STM32时钟系统,以及如何配置做个简单记录,方便以后的快速开发。

二、正文
  废话不多说,上一张STM32F10xx的时钟树图:

  

  由图可知,STM32F10XX有两级时钟
  第一级时钟
    * 高速内部时钟(HSI)
    * 锁相环时钟(PLLCLK)
    * 高速外部时钟(HSE)
  第二级时钟
    * 低速内部时钟(LSI)
    * 低速外部时钟(LSE)

  又由图可知,
    * HSE由外部晶振从"OSC_OUT","OSC_IN"两脚输入提供。
    * LSE由外部晶振从"OSC32_OUT","OSC32_IN"两脚输入提供。
    * HSI由8MHZ高速内部RC震荡电路提供。
    * LSI由40kHZ低速内部RC震荡电路提供。

  STM32F10XX还可通过MCO脚向外提供时钟输出。时钟来源有PLLCLK/HSI/HSE/SYSCLK,由MCO选择器来选择。

  研究过时钟来源,再来研究时钟的去向,MCU自身要能正常运作,即需要一个时钟,这个时钟既是系统时钟(SYSCLK),而基本上所有外设的时钟均来自于这个系统时钟(SYSCLk)。然后由系统时钟对外提供各种外设时钟。详见图。  

  当然,也有例外,USB时钟必须为48MHZ,这里的USB时钟(USBCLK)由PLLCLK直接提供,RTC时钟 (RTCCLK)也不是来源于系统时钟(SYSCLK),详见图。  

  时钟结构大体也就如此,不再深究,网上有许多更加深入的讲解,接下来说说如何去配置。用代码来说明问题:

  先贴文件"system_stm32f10x.c",此文件即库文件。里面有一个很重要的函数"SystemInit()"

  解析过STM32启动代码的朋友都应该知道,这个函数跑在进入main函数之前,里面做的事情即是配置系统时钟。代码如下:

void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */#ifndef STM32F10X_CLRCC->CFGR &= (uint32_t)0xF8FF0000;#elseRCC->CFGR &= (uint32_t)0xF0FF0000;#endif /* STM32F10X_CL */   /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;/* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= (uint32_t)0xFF80FFFF;#ifdef STM32F10X_CL/* Reset PLL2ON and PLL3ON bits */RCC->CR &= (uint32_t)0xEBFFFFFF;/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x00FF0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000;      #else/* Disable all interrupts and clear pending bits  */RCC->CIR = 0x009F0000;#endif /* STM32F10X_CL */#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)#ifdef DATA_IN_ExtSRAMSystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */#endif /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers *//* Configure the Flash Latency cycles and enable prefetch buffer */SetSysClock();    //此函数在该函数末尾
#ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */                   #elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */                     #endif                                                                              }static void SetSysClock(void)
{// 根据宏定义来设置时钟。
    #ifdef SYSCLK_FREQ_HSESetSysClockToHSE();#elif defined SYSCLK_FREQ_24MHzSetSysClockTo24();#elif defined SYSCLK_FREQ_36MHzSetSysClockTo36();#elif defined SYSCLK_FREQ_48MHzSetSysClockTo48();#elif defined SYSCLK_FREQ_56MHzSetSysClockTo56();  #elif defined SYSCLK_FREQ_72MHzSetSysClockTo72();    // 以设置成最大频率72MHZ为例#endif/* If none of the define above is enabled, the HSI is used as System clocksource (default after reset) */
}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 */}
}    

  

  文件"system_stm32f10x.c"的属性默认被设置为只读文件,最好不要更改里面的东西,毕竟启动以及复位之后,最先运行的是这个文件内的函数。

  如果想要更改MCU时钟频率,建议自己写一个函数来进行更改,代码如下:

/*** @brief  配置系统时钟(72MHz)* @param  None* @retval None*/
void RCC_Configuration(void)
{ErrorStatus HSEStartUpStatus;RCC_DeInit();RCC_HSEConfig(RCC_HSE_ON);HSEStartUpStatus = RCC_WaitForHSEStartUp();if(HSEStartUpStatus == SUCCESS) {FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);FLASH_SetLatency(FLASH_Latency_2);// HCLK(AHBCLK) = SYSCLK = 72MHZ
        RCC_HCLKConfig(RCC_SYSCLK_Div1);    // APB2CLK = HCLK = 72MHZ
        RCC_PCLK2Config(RCC_HCLK_Div1);        // APB1CLK = HCLK/4 = 18MHZ
        RCC_PCLK1Config(RCC_HCLK_Div4);        // 选择PLLCLK为输入时钟,PLLMUL9倍频. 8MHZ*9 = 72MHZ
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); RCC_PLLCmd(ENABLE);while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){        ;         }//PLL作为系统时钟的输入
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);while(RCC_GetSYSCLKSource() != 0x08) {                 ;}}
}

  至此,记录完毕。

记录地点:深圳WZ

记录时间:2016年8月16日

转载于:https://www.cnblogs.com/ChYQ/p/5776345.html

Cotex-M3内核STM32F10XX系列时钟及其配置方法相关推荐

  1. STM32系统时钟及配置方法

    什么是时钟 单片机如果要正常运行,时钟信号是必不可少的.作为CPU的脉搏,时钟的快慢决定了CPU的运行速率,执行指令的速度.一般时钟源会被分频器或倍频器分成多种频率的时钟,以满足系统的不同应用. 那么 ...

  2. TI | TM4C系列单片机中断配置方法

    1.问题来源: 在写中断服务函数时,根据手册需要设置为定时器timer0B模式. 但是写入编译时发现,提示如下图错误.编译提示信息没有定义.但是不知道tiva系列的单片机定时器可以自己设置.摸索查看资 ...

  3. linux 实时内核 xenomai 2.6.5 配置方法

    安装前准备 安装包准备:ubuntu 16.04   xenomai 2.6.5 ​ linux kernel 3.18.20 主要参考网址https://rtt-lwr.readthedocs.io ...

  4. STM32F0系列内部高速时钟的配置方法

    这是本人写的的第一篇CSDN博客,虽然近年来浏览很多,但是自己还是没有动手写过.我看到很多朋友都通过写博客的方式来记笔记,觉得这是一个非常不错的方法.最近在公司实习,身边有很多经验丰富的工程师,他们教 ...

  5. Linux服务器NTP客户端时钟同步配置方法

    前提说明:配置客户端NTP时候,必须要有一台时钟服务器,可以是服务器搭建的,也可以是购买的时钟设备.我这里使用临时的时钟服务器IP地址10.10.4.100 步骤如下: 1 首先在客户端服务器中pin ...

  6. 国产数字语音网关鼎信通达DAG系列网关快速配置方法-武汉迈思通信

    DAG2000系列4/8/16/24/32FXS语音网关 快速配置手册 1.WEB登陆 设备Lan口默认IP是192.168.11.1/255.255.255.0,用电脑直连设备Lan口,将电脑IP地 ...

  7. 10G光通信 64B66B编解码 配置方法及其工作原理

    目录 1 配置IP核 1.1 `Page1:GT Selection:` 1.2 `Page2:Line Rate,RefClk Selections: ` 1.3 `Page3:Encoding a ...

  8. JS调用媒体设备失败 --- getUserMedia undefine 问题(各浏览器配置方法)

    解决: getUserMedia undefine 问题 问题: http请求的 chrome,edge, fireFox 等主流浏览器由于安全限制将不会暴露getUserMedia 方法,所以就不能 ...

  9. STM32F1系列HAL库配置系统时钟

    STM32F1系列HAL库配置系统时钟 其实一开始对于时钟我也是知之甚少,在MSP432中我就一直忽视时钟配置,其实也是在STM32学习时落下的病根,现在趁有空补一下. 时钟简单讲解 对于时钟系统,在 ...

最新文章

  1. 克隆Centos 无法上网
  2. STL的Vector, List and Deque
  3. everytime you write on a whiteboard
  4. JavaSE、JavaEE与Spring的概念和异同点剖析
  5. 射灯安装方法图解_射灯更换安装方法图解
  6. php如何记录访问请求类型,检测PHP中的请求类型(GET、POST、PUT或DELETE)
  7. ubunt11 安装mysql_ubuntu 11.10安装mysql
  8. Visual Studio 2005中一个需要小改进的地方
  9. c语言函数与指针,C语言指针与函数篇
  10. BZOJ3421 : Poi2013 Walk
  11. ubuntu16.04 下ROS操作系统学习笔记(一)ROS-kinetic安装
  12. 在Mac上Topaz Gigapixel AI作为Photoshop插件未显示在“文件”->“自动”中的解决方法
  13. 百度网盘python客户端——筑梦之路
  14. 支持ldap的邮箱服务器,U-Mail邮件系统LDAP同步邮箱地址簿教程
  15. Android下红包雨的实现
  16. A股数据分析之收集数据:股票列表和股价
  17. 微信jssdk签名生成代码示例PHP版本
  18. 小米OJ 54(数独游戏)
  19. 一群对J2EE充满激情的兄弟
  20. 小程序基础开发(五):微信支付全套流程

热门文章

  1. 赫夫曼树(Haffman)及其运用
  2. Google的Logo颜色参数
  3. 微信小程序web-view使用audio标签播放音频文件时无法自动播放的问题
  4. HR人力资源管理精粹70则
  5. 有关session生命周期
  6. 接下来或许是一年中跳槽的最佳时间
  7. JS实战面向对象 - 贪吃蛇
  8. linux UVC摄像头驱动 简介
  9. mysql truncated_mysql数据截断
  10. Shell脚本之多重循环