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

智能推荐

linux devkmem 源码,linux dev/mem dev/kmem实现访问物理/虚拟内存-程序员宅基地

文章浏览阅读451次。dev/mem: 物理内存的全镜像。可以用来访问物理内存。/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。调试嵌入式Linux内核时,可能需要查看某个内核变量的值。/dev/kmem正好提供了访问内核虚拟内存的途径。现在的内核大都默认禁用了/dev/kmem,打开的方法是在 make menuconfig中选中 device drivers --> ..._dev/mem 源码实现

vxe-table 小众但功能齐全的vue表格组件-程序员宅基地

文章浏览阅读7.1k次,点赞2次,收藏19次。vxe-table,一个小众但功能齐全并支持excel操作的vue表格组件_vxe-table

(开发)bable - es6转码-程序员宅基地

文章浏览阅读62次。参考:http://www.ruanyifeng.com/blog/2016/01/babel.htmlBabelBabel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行// 转码前input.map(item => item + 1);// 转码后input.map(function (item) { return item..._让开发环境支持bable

FPGA 视频处理 FIFO 的典型应用_fpga 频分复用 视频-程序员宅基地

文章浏览阅读2.8k次,点赞6次,收藏29次。摘要:FPGA视频处理FIFO的典型应用,视频输入FIFO的作用,视频输出FIFO的作用,视频数据跨时钟域FIFO,视频缩放FIFO的作用_fpga 频分复用 视频

R语言:设置工作路径为当前文件存储路径_r语言设置工作目录到目标文件夹-程序员宅基地

文章浏览阅读575次。【代码】R语言:设置工作路径为当前文件存储路径。_r语言设置工作目录到目标文件夹

background 线性渐变-程序员宅基地

文章浏览阅读452次。格式:background: linear-gradient(direction, color-stop1, color-stop2, ...);<linear-gradient> = linear-gradient([ [ <angle> | to <side-or-corner>] ,]? &l..._background线性渐变

随便推点

【蓝桥杯省赛真题39】python输出最大的数 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析-程序员宅基地

文章浏览阅读1k次,点赞26次,收藏8次。第十三届蓝桥杯青少年组python编程省赛真题一、题目要求(注:input()输入函数的括号中不允许添加任何信息)1、编程实现给定一个正整数N,输出正整数N中各数位最大的那个数字。例如:N=132,则输出3。2、输入输出输入描述:只有一行,输入一个正整数N输出描述:只有一行,输出正整数N中各数位最大的那个数字输入样例:

网络协议的三要素-程序员宅基地

文章浏览阅读2.2k次。一个网络协议主要由以下三个要素组成:1.语法数据与控制信息的结构或格式,包括数据的组织方式、编码方式、信号电平的表示方式等。2.语义即需要发出何种控制信息,完成何种动作,以及做出何种应答,以实现数据交换的协调和差错处理。3.时序即事件实现顺序的详细说明,以实现速率匹配和排序。不完整理解:语法表示长什么样,语义表示能干什么,时序表示排序。转载于:https://blog.51cto.com/98..._网络协议三要素csdn

The Log: What every software engineer should know about real-time data's unifying abstraction-程序员宅基地

文章浏览阅读153次。主要的思想,将所有的系统都可以看作两部分,真正的数据log系统和各种各样的query engine所有的一致性由log系统来保证,其他各种query engine不需要考虑一致性,安全性,只需要不停的从log系统来同步数据,如果数据丢失或crash可以从log系统replay来恢复可以看出kafka系统在linkedin中的重要地位,不光是d..._the log: what every software engineer should know about real-time data's uni

《伟大是熬出来的》冯仑与年轻人闲话人生之一-程序员宅基地

文章浏览阅读746次。伟大是熬出来的  目录  前言  引言 时间熬成伟大:领导者要像狼一样坚忍   第一章 内圣外王——领导者的心态修炼  1. 天纵英才的自信心  2. 上天揽月的企图心  3. 誓不回头的决心  4. 宠辱不惊的平常心  5. 换位思考的同理心  6. 激情四射的热心  第二章 日清日高——领导者的高效能修炼  7. 积极主动,想到做到  8. 合理掌控自己的时间和生命  9. 制定目标,马..._当狼拖着受伤的右腿逃生时,右腿会成为前进的阻碍,它会毫不犹豫撕咬断自己的腿, 以

有源光缆AOC知识百科汇总-程序员宅基地

文章浏览阅读285次。在当今的大数据时代,人们对高速度和高带宽的需求越来越大,迫切希望有一种新型产品来作为高性能计算和数据中心的主要传输媒质,所以有源光缆(AOC)在这种环境下诞生了。有源光缆究竟是什么呢?应用在哪些领域,有什么优势呢?易天将为您解答!有源光缆(Active Optical Cables,简称AOC)是两端装有光收发器件的光纤线缆,主要构成部件分为光路和电路两部分。作为一种高性能计..._aoc 光缆

浏览器代理服务器自动配置脚本设置方法-程序员宅基地

文章浏览阅读2.2k次。在“桌面”上按快捷键“Ctrl+R”,调出“运行”窗口。接着,在“打开”后的输入框中输入“Gpedit.msc”。并按“确定”按钮。如下图 找到“用户配置”下的“Windows设置”下的“Internet Explorer 维护”的“连接”,双击选择“自动浏览器配置”。如下图 选择“自动启动配置”,并在下面的“自动代理URL”中填写相应的PAC文件地址。如下..._設置proxy腳本