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

发布者:MysticMoon最新更新时间:2016-12-26 来源: eefocus关键字:Cotex-M3内核  STM32F10XX系列  时钟  配置方法 手机看文章 扫描二维码
随时随地手机看文章

一、背景
  最近做个项目,需要使用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_CL
      RCC->CFGR &= (uint32_t)0xF8FF0000;    #else
      RCC->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_ExtSRAM
        SystemInit_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_SRAM
      SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal 

SRAM. */                   
    #else
      SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal 

FLASH. */                     
    #endif                                                                              

                                  }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
      SetSysClockTo72();    // 以设置成最大频率72MHZ为例
    #endif
     
     /* If none of the define above is enabled, the HSI is used as System clock
        source (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) {         
        ;
        }
    }
}

 

  至此,记录完毕。


关键字:Cotex-M3内核  STM32F10XX系列  时钟  配置方法 引用地址:Cotex-M3内核STM32F10XX系列时钟及其配置方法

上一篇:STM32 之 NVIC(中断向量、优先级) 简述
下一篇:Stm32 debug停留在"BKPT 0xAB"或者"SWI 0xAB"的解决办法

推荐阅读最新更新时间:2024-03-16 15:27

基于内插和QLA技术的并行DDS的实现
1 引 言 直接数字频率合成技术(Direel Digital FrequencySynthesis,DDS)称为第三代频率合成技术,他利用正弦信号的相位与时间呈线性关系的特性,通过查表的方式得到信号的瞬时幅值,从而实现频率合成。这种方法不仅可以产生不同频率的正弦波,而且具有超宽的相对带宽,超高的变频速率,超细的分辨率以及相位的连续性和产生任意波形(AWG)的特点。 目前所使用的大部分DDS结构,在相位累加模块和相位幅度转换模块均采用了流水线技术和某些压缩算法等,但都不能从根本上解决DDS的输出频率受外部时钟频率约束的瓶颈以及波形的输出质量受查找表容量限制的问题。因此在对DDS的结构进行深入研究的基础上,我们在相位累加器部分以
[应用]
DDR测试--SDRAM时钟分析案例
前个周末接到了一个朋友的电话,询问我如果内存有问题,需要测试哪些项目?对于这个很常见的问题,我习惯性的回答他先测量内存时钟和读写时序看看,然后结束了通话。没过一会,我那朋友又打过来,告诉我他遇到一个怪事,他用探头点测内存时钟时,系统的程序不卡了,可以顺利启动并运行。听到这个描述,我顿时感兴趣了,开始仔细询问待测试的电路和测试仪器。 待测试的电路板的内存控制器为A公司的ARM架构的MCU,内存为Micron的SDRAM,内存时钟频率为100MHz,测试仪器为某200M带宽示波器,探头为示波器标配的无源探头。在以往的探头培训中,我曾多次给客户讲探头的重要性,在我的幻灯片中有以下几句话: 在把探头连接到电路上时,可能会发生下面三种情况
[测试测量]
DDR测试--SDRAM<font color='red'>时钟</font>分析案例
对MSP430F5438的时钟及uart配置
对MSP430F5438的时钟及uart配置 在使用的过程中,一直认为比较简单,也一直没有深究,忽然这几天卡壳了,出现问题是操作UART发送出的数据给232显示,并不是想得到的数据。这里涉及了两个地方,一是时钟配置,二是对UART的配置。 时钟配置 需求:考虑到功耗及使用场景,MCLK=2M,SMCLK=1M,ACLK=32768 P7SEL |= BIT0 + BIT1; //开XT1 __bis_SR_register( SCG0 ); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set low
[单片机]
STM32时钟系统
在STM32上如果不使用外部晶振,OSC_IN和OSC_OUT的接法 如果使用内部RC振荡器而不使用外部晶振,请按照下面方法处理: 1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。 2)对于少于100脚的产品,有2种接法: 2.1)OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能。 2.2)分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面2.1)节省2个外部电阻。 使用HSE时钟,程序设置时钟参数流程: 1、将RCC寄存器重新设置为默认值 RCC_DeInit; 2、
[单片机]
STM32<font color='red'>时钟</font>系统
Exynos4412芯片的时钟管理单元
本章介绍Exynos4412芯片的时钟管理单元(CMU)。CMU控制锁相环(PLL)并为Exynos4412芯片中的各个IP、总线和模块产生时钟。它们还与电源管理单元(PMU)通信,以便在进入某个低功耗模式之前停止时钟,以通过时钟切换来降低功耗。 1.Exynos4412芯片的时钟体系介绍 对于PC机来说,CPU、内存、主板、声卡、显卡等等,这些功能部件由不同的芯片组成,在实体上是相互独立的。在嵌入式系统里,一块芯片往往集成了多种功能,比如Exynos4412上面既有CPU,还有音频/视频接口、LCD接口、GPS等模块。这类芯片被称为SoC,即System on Chip,译为芯片级系统或片上系统。在Exynos 4412
[单片机]
Exynos4412芯片的<font color='red'>时钟</font>管理单元
MSP430单片机的PCF8563时钟芯片C语言驱动程序
#define NOP _NOP();_NOP() #define NowSec cNowTime #define NowMin cNowTime #define NowHour cNowTime #define NowDate cNowTime #define NowMonth cNowTime #define NowYear cNowTime #define SetSec cSetTime #define SetMin
[单片机]
8位数码管电子时钟仿真图及程序源代码
利用8位数码管显示时间,原理与4位数码管显示的基本一样 仿真图: 程序源代码: 本程序已经通过在线软件仿真和硬件制作. org 0000h ;程序开始入口地址 sjmp main ;跳转至主程序 org 000bh ;T0中断入口地址 ljmp inti0 ;跳转至T0中断程序 org 001bh ;T1中断入口地址 ljmp inti1 ;跳转至T1中断程序 org 0030h main:mov tmod,#11h ;设T0、T1为模式1 mov ie,#8ah ;开T0、T1允许中断 mov th0,#4ch ;赋T0 50ms初值 mov tl0,#00h mov th1,#4ch ;赋T1 50ms初值 mov
[单片机]
8位数码管电子<font color='red'>时钟</font>仿真图及程序源代码
MSP430X5XX的时钟系统与低功耗模式
引言:全新改版,关于MSP430x5xx时钟系统与低功耗模式介绍。用到低功耗的时候,不得不仔细的看文档,做比较实验,真繁琐。 430系列单片机中有各种时钟信号,第一次接触免不了一头雾水。而且如果想发挥430低功耗的优势,就不得不对它的时钟系统(Unified Clock System)有所了解。 1. 时钟模块总览 这是MSP430X5XX的时钟系统框图。乍一看很复杂,不过简化之后就清楚多了 整个系统主要分为左右两大块,左边是时钟源模块,右边是时钟调整模块。 左边的模块 XT1、内建时钟(DCO)、XT2用来产生时钟源,也就是右边最终输出的时钟信号的基准信号。 而时钟调整模块负责将源时钟信号选通、分频输出成系统使
[单片机]
MSP430X5XX的<font color='red'>时钟</font>系统与低功耗模式
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved