stm32 时钟配置——外部时钟倍频、内部时钟倍频 【worldsing笔记】-程序员宅基地

技术标签: 嵌入式  

stm32可选的时钟源

在STM32中,可以用内部时钟,也可以用外部时钟,在要求进度高的应用场合最好用外部晶体震荡器,内部时钟存在一定的精度误差。

准确的来说有4个时钟源可以选分别是HSI、LSI、HSE、LSE(即内部高速,内部低速,外部高速,外部低速),高速时钟主要用于系统内核和总线上的外设时钟。低速时钟主要用于独立看门狗IWDG、实时时钟RTC。

①、HSI是高速内部时钟,RC振荡器,频率为8MHz,上电后默认的系统时时钟 SYSCLK = 8MHz,Flash编程时钟。

①、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。

③、LSI是低速内部时钟,RC振荡器,频率为40kHz,可用于独立看门狗IWDG、实时时钟RTC。

④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。

 

系统时钟SYSCLK输入

这里重点在高速时钟,因为大部分外设时钟都是用的高速时钟。系统内核和外设时钟的时钟只有一个源,那就是SYSCLK, 即常说的系统时钟, 他是有一个选择器SW来做选择的,有3种选择HSI、HSE和PLL, 上电后默认选择内部HSI, HSI虽然存在精度误差,但是能保证不会挂。这点比AVR单片机做的好一些,AVR单片机时钟一旦配置成外部的,如果外部时钟正常那时无法下载程序的。PLL为锁相环倍频输出,PLL时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,其输出频率最大不得超过72MHz, 也有网有超频工作的,但不提倡。

也就是说系统时钟SYSCLK最终有以下几种选择:

①、SYSCLK = HSI

①、SYSCLK = HSE

③、SYSCLK = PLL

 

image

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

关于PLL锁相环倍频(输入和输出):

将输入时钟乘以一个系数后输出时钟,可以百度PLL原理。

PLL的输入3种选择:

①、PLLi =  HSI /2

①、PLLi =  HSE /2

③、PLLi =  HSE

 

PLL的输出有15种选择: PLLout = PLLi Xn (n = 2…16)

image

 

 

关于USB时钟

STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取(唯一的),,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。

image

 

关于把时钟信号输出到外部

另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。

 image

 

关于系统时钟SYSCLK分配

系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL输出、HSI(8MHz)或者HSE(外部晶振)。系统时钟最大频率为72MHz,供给I2S音频总线和AHB总线时钟。

image

它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用:

①、内核总线:送给AHB总线、内核、内存和DMA使用的HCLK时钟。

②、Tick定时器:通过8分频后送给Cortex的系统定时器时钟。

③、I2S总线:直接送给Cortex的空闲运行时钟FCLK。

④、APB1外设:送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2、3、4使用。

⑤、APB2外设:送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频率72MHz),另一路送给定时器(Timer)1倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2、4、6、8分频。

在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。

需要注意的是定时器的倍频器,当APB的分频为1时,它的倍频值为1,否则它的倍频值就为2。

连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意USB模块虽然需要一个单独的48MHz时钟信号,但它应该不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。

连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口。

对于单片机系统来说,CPU和总线以及外设的时钟设置是非常重要的,因为没有时钟就没有时序。

由于时钟是一个由内而外的东西,具体设置要从寄存器开始。
RCC 寄存器结构,RCC_TypeDeff,在文件“stm32f10x.h”中定义如下: (v3.4库)

1059行->1081行。

  1. typedef struct
  2. {
  3.   __IO uint32_t CR;
  4.   __IO uint32_t CFGR;
  5.   __IO uint32_t CIR;
  6.   __IO uint32_t APB2RSTR;
  7.   __IO uint32_t APB1RSTR;
  8.   __IO uint32_t AHBENR;
  9.   __IO uint32_t APB2ENR;
  10.   __IO uint32_t APB1ENR;
  11.   __IO uint32_t BDCR;
  12.   __IO uint32_t CSR;
  13. #ifdef STM32F10X_CL
  14.   __IO uint32_t AHBRSTR;
  15.   __IO uint32_t CFGR2;
  16. #endif /* STM32F10X_CL */
  17. #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
  18.   uint32_t RESERVED0;
  19.   __IO uint32_t CFGR2;
  20. #endif /* STM32F10X_LD_VL || STM32F10X_MD_VL || STM32F10X_HD_VL */
  21. } RCC_TypeDef;

一般板子上只有8Mhz的晶振,而增强型最高工作频率为72Mhz,显然需要用PLL倍频9倍,这些设置都需要在初始化阶段完成。

 

 

 

使用外部高速HSE时钟,程序设置时钟参数流程:
     1、将RCC寄存器重新设置为默认值      RCC_DeInit;
     2、打开外部高速时钟晶振HSE           RCC_HSEConfig(RCC_HSE_ON);
     3、等待外部高速时钟晶振工作           HSEStartUpStatus = RCC_WaitForHSEStartUp();
     4、设置AHB时钟                          RCC_HCLKConfig;
    5、设置高速AHB时钟                      RCC_PCLK2Config;
    6、设置低速速AHB时钟                   RCC_PCLK1Config;
    7、设置PLL                                 RCC_PLLConfig;
    8、打开PLL                                 RCC_PLLCmd(ENABLE);
    9、等待PLL工作                            while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
   10、设置系统时钟                          RCC_SYSCLKConfig;
   11、判断是否PLL是系统时钟              while(RCC_GetSYSCLKSource() != 0x08)
   12、打开要使用的外设时钟               RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()

为了方便说明,借用一下例程的RCC设置函数,并用中文注释的形式加以说明:

static void RCC_Config(void) { 
/* 这里是重置了RCC的设置,类似寄存器复位 */ 
RCC_DeInit(); 

/* 使能外部高速晶振 */ 
RCC_HSEConfig(RCC_HSE_ON); 

/* 等待高速晶振稳定 */ 
HSEStartUpStatus = RCC_WaitForHSEStartUp(); 

if (HSEStartUpStatus == SUCCESS) 
{ 
    /* 使能flash预读取缓冲区 */ 
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 

    /* 令Flash处于等待状态,2是针对高频时钟的,这两句跟RCC没直接关系,可以暂且略过 */ 
    FLASH_SetLatency(FLASH_Latency_2); 

    /* HCLK = SYSCLK 设置高速总线时钟=系统时钟*/ 
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 

    /* PCLK2 = HCLK 设置低速总线2时钟=高速总线时钟*/ 
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 设置低速总线1的时钟=高速时钟的二分频*/ 
    RCC_PCLK1Config(RCC_HCLK_Div2); 

    /* ADCCLK = PCLK2/6 设置ADC外设时钟=低速总线2时钟的六分频*/ 
    RCC_ADCCLKConfig(RCC_PCLK2_Div6); 

    /* Set PLL clock output to 72MHz using HSE (8MHz) as entry clock */ 
    //这句很关键 
    /* 利用锁相环讲外部8Mhz晶振9倍频到72Mhz */ 
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); 

    /* Enable PLL 使能锁相环*/ 
    RCC_PLLCmd(ENABLE); 

   /* Wait till PLL is ready 等待锁相环输出稳定*/ 
   while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ;

    /* Select PLL as system clock source 将锁相环输出设置为系统时钟 */ 
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 

    /* Wait till PLL is used as system clock source 等待校验成功*/ 
    while (RCC_GetSYSCLKSource() != 0x08);
} 

/* Enable FSMC, GPIOD, GPIOE, GPIOF, GPIOG and AFIO clocks */ 
//使能外围接口总线时钟,注意各外设的隶属情况,不同芯片的分配不同,到时候查手册就可以 
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | 
                         RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG | 
                         RCC_APB2Periph_AFIO, ENABLE); 
} 


 

使用内部高速HSI时钟,程序设置时钟参数流程:
     1、将RCC寄存器重新设置为默认值      RCC_DeInit;
     2、设置AHB时钟                           RCC_HCLKConfig;
     3、设置高速AHB时钟                      RCC_PCLK2Config;
     4、设置低速速AHB时钟                   RCC_PCLK1Config;
    5、设置PLL选择时钟源和倍频数         RCC_PLLConfig(RCC_PLLSource_HSI_Div2, 倍频数); 

6、打开PLL                                 RCC_PLLCmd(ENABLE);
     7、等待PLL工作                            while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
     8、设置系统时钟                           RCC_SYSCLKConfig;
     9、判断是否PLL是系统时钟               while(RCC_GetSYSCLKSource() != 0x08)
   10、打开要使用的外设时钟                 RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()

 

void RCC_Configuration(void){

    /*将外设RCC寄存器重设为缺省值*/
    RCC_DeInit();
 
    /*设置AHB时钟(HCLK)*/ 
    RCC_HCLKConfig(RCC_SYSCLK_Div1);  //RCC_SYSCLK_Div1——AHB时钟= 系统时钟

    /* 设置高速AHB时钟(PCLK2)*/ 
    RCC_PCLK2Config(RCC_HCLK_Div1);   //RCC_HCLK_Div1——APB2时钟= HCLK

    /*设置低速AHB时钟(PCLK1)*/    
    RCC_PCLK1Config(RCC_HCLK_Div2);   //RCC_HCLK_Div2——APB1时钟= HCLK / 2

    /*设置FLASH存储器延时时钟周期数*/
    FLASH_SetLatency(FLASH_Latency_2); //FLASH_Latency_2  2延时周期

    /*选择FLASH预取指缓存的模式*/  
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);       // 预取指缓存使能

    /*设置PLL时钟源及倍频系数*/ 
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_12);        

    /*使能PLL */
    RCC_PLLCmd(ENABLE); 

    /*检查指定的RCC标志位(PLL准备好标志)设置与否*/   
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ;
 
    /*设置系统时钟(SYSCLK)*/ 
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 

    /* PLL返回用作系统时钟的时钟源*/
    while(RCC_GetSYSCLKSource() != 0x08);                 //0x08:PLL作为系统时钟
}

PLL的设定需要在使能之前,一旦PLL使能后参数不可更改。

在STM32中,连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4 。

连接在APB2(高速外设)上的设备有:GPIO_A-E、USART1、ADC1、ADC2、ADC3、TIM1、TIM8、SPI1、ALL。

程序举例:

APB1(低速外设)

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);

APB2(高速外设)

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA  , ENABLE);

 

 

STM32和其它单片机相比时钟更为复杂,就是为了灵活配置,降低功耗,不用的外设可以关闭时钟,看似复杂但是,打开时钟树一看,就是几个根的选择,和几个枝叶的选择。

转载于:https://www.cnblogs.com/worldsing/p/3433529.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30575309/article/details/98232358

智能推荐

解决win10/win8/8.1 64位操作系统MT65xx preloader线刷驱动无法安装_mt65驱动-程序员宅基地

文章浏览阅读1.3w次。转载自 http://www.miui.com/thread-2003672-1-1.html 当手机在刷错包或者误修改删除系统文件后会出现无法开机或者是移动定制(联通合约机)版想刷标准版,这时就会用到线刷,首先就是安装线刷驱动。 在XP和win7上线刷是比较方便的,用那个驱动自动安装版,直接就可以安装好,完成线刷。不过现在也有好多机友换成了win8/8.1系统,再使用这个_mt65驱动

SonarQube简介及客户端集成_sonar的客户端区别-程序员宅基地

文章浏览阅读1k次。SonarQube是一个代码质量管理平台,可以扫描监测代码并给出质量评价及修改建议,通过插件机制支持25+中开发语言,可以很容易与gradle\maven\jenkins等工具进行集成,是非常流行的代码质量管控平台。通CheckStyle、findbugs等工具定位不同,SonarQube定位于平台,有完善的管理机制及强大的管理页面,并通过插件支持checkstyle及findbugs等既有的流..._sonar的客户端区别

元学习系列(六):神经图灵机详细分析_神经图灵机方法改进-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏27次。神经图灵机是LSTM、GRU的改进版本,本质上依然包含一个外部记忆结构、可对记忆进行读写操作,主要针对读写操作进行了改进,或者说提出了一种新的读写操作思路。神经图灵机之所以叫这个名字是因为它通过深度学习模型模拟了图灵机,但是我觉得如果先去介绍图灵机的概念,就会搞得很混乱,所以这里主要从神经图灵机改进了LSTM的哪些方面入手进行讲解,同时,由于模型的结构比较复杂,为了让思路更清晰,这次也会分开几..._神经图灵机方法改进

【机器学习】机器学习模型迭代方法(Python)-程序员宅基地

文章浏览阅读2.8k次。一、模型迭代方法机器学习模型在实际应用的场景,通常要根据新增的数据下进行模型的迭代,常见的模型迭代方法有以下几种:1、全量数据重新训练一个模型,直接合并历史训练数据与新增的数据,模型直接离线学习全量数据,学习得到一个全新的模型。优缺点:这也是实际最为常见的模型迭代方式,通常模型效果也是最好的,但这样模型迭代比较耗时,资源耗费比较多,实时性较差,特别是在大数据场景更为困难;2、模型融合的方法,将旧模..._模型迭代

base64图片打成Zip包上传,以及服务端解压的简单实现_base64可以装换zip吗-程序员宅基地

文章浏览阅读2.3k次。1、前言上传图片一般采用异步上传的方式,但是异步上传带来不好的地方,就如果图片有改变或者删除,图片服务器端就会造成浪费。所以有时候就会和参数同步提交。笔者喜欢base64图片一起上传,但是图片过多时就会出现数据丢失等异常。因为tomcat的post请求默认是2M的长度限制。2、解决办法有两种:① 修改tomcat的servel.xml的配置文件,设置 maxPostSize=..._base64可以装换zip吗

Opencv自然场景文本识别系统(源码&教程)_opencv自然场景实时识别文字-程序员宅基地

文章浏览阅读1k次,点赞17次,收藏22次。Opencv自然场景文本识别系统(源码&教程)_opencv自然场景实时识别文字

随便推点

ESXi 快速复制虚拟机脚本_exsi6.7快速克隆centos-程序员宅基地

文章浏览阅读1.3k次。拷贝虚拟机文件时间比较长,因为虚拟机 flat 文件很大,所以要等。脚本完成后,以复制虚拟机文件夹。将以下脚本内容写入文件。_exsi6.7快速克隆centos

好友推荐—基于关系的java和spark代码实现_本关任务:使用 spark core 知识完成 " 好友推荐 " 的程序。-程序员宅基地

文章浏览阅读2k次。本文主要实现基于二度好友的推荐。数学公式参考于:http://blog.csdn.net/qq_14950717/article/details/52197565测试数据为自己随手画的关系图把图片整理成文本信息如下:a b c d e f yb c a f gc a b dd c a e h q re f h d af e a b gg h f bh e g i di j m n ..._本关任务:使用 spark core 知识完成 " 好友推荐 " 的程序。

南京大学-高级程序设计复习总结_南京大学高级程序设计-程序员宅基地

文章浏览阅读367次。南京大学高级程序设计期末复习总结,c++面向对象编程_南京大学高级程序设计

4.朴素贝叶斯分类器实现-matlab_朴素贝叶斯 matlab训练和测试输出-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏12次。实现朴素贝叶斯分类器,并且根据李航《统计机器学习》第四章提供的数据训练与测试,结果与书中一致分别实现了朴素贝叶斯以及带有laplace平滑的朴素贝叶斯%书中例题实现朴素贝叶斯%特征1的取值集合A1=[1;2;3];%特征2的取值集合A2=[4;5;6];%S M LAValues={A1;A2};%Y的取值集合YValue=[-1;1];%数据集和T=[ 1,4,-1;..._朴素贝叶斯 matlab训练和测试输出

Markdown 文本换行_markdowntext 换行-程序员宅基地

文章浏览阅读1.6k次。Markdown 文本换行_markdowntext 换行

错误:0xC0000022 在运行 Microsoft Windows 非核心版本的计算机上,运行”slui.exe 0x2a 0xC0000022″以显示错误文本_错误: 0xc0000022 在运行 microsoft windows 非核心版本的计算机上,运行-程序员宅基地

文章浏览阅读6.7w次,点赞2次,收藏37次。win10 2016长期服务版激活错误解决方法:打开“注册表编辑器”;(Windows + R然后输入Regedit)修改SkipRearm的值为1:(在HKEY_LOCAL_MACHINE–》SOFTWARE–》Microsoft–》Windows NT–》CurrentVersion–》SoftwareProtectionPlatform里面,将SkipRearm的值修改为1)重..._错误: 0xc0000022 在运行 microsoft windows 非核心版本的计算机上,运行“slui.ex