datasheet

单片机入门学习八 STM32单片机学习五 时钟系统

2019-07-12来源: eefocus关键字:单片机  STM32  时钟系统

单片机学习除了了解该篇 单片机入门学习五 STM32单片机学习二 跑马灯程序衍生出的stm32编程基础 中的基础外,我们还需要有时钟的概念,本篇将记录 stm32的时钟系统。


1、STM32时钟介绍 

下面这幅图时stm32的时钟系统框图 

时钟系统框图

1)蓝底框表示 时钟源,即: 

①HSI是高速内部时钟,RC振荡器,频率为8MHz。 

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

③LSI是低速内部时钟,RC振荡器,频率为40kHz。(WDG看门狗 使用该时钟源) 

④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。(RTC实时时钟 使用该时钟源) 

⑤PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。 

其中HSE和LSE是通过单片机外部的晶振输入的,一共四个管脚,HSE的输入管脚是OSC_IN和OSC_OUT(通常为8M), 

LSE的输入管脚对应的引脚为OSC32_IN和OSC32_OUT(32.768kHz) 

2)梯形表示 选择器,例如: 

 梯形 

梯形表示 SYSCLK系统时钟的来源可以使HSI RC、PLLCLK、HSE Osc(即HSI振荡器时钟、HSE振荡器时钟、PLL时钟) 

3)绿色方框 表示 预分频器(prescaler) 

4)该图片如何看,比如下图: 

预分频说明

按照上图深红色 的路线来解释:PLL的时钟源 经过前面的选择器 假设为8MHz,经过PLL 9倍频后 PLLCLK的频率为72MHz,则经过选择器 SYSCLK(系统时钟)频率为72MHz,经过AHB分频器 1分频后 HCLK输出频率72MHz,经过APB1分频器 2分频后 PCLK1频率为36MHz; 经过APB2分频器 1分频后 PCLK2频率为72MHz。 

5)时钟输出MCO脚(PA8),可以选择PLL输出的2分频、HSI、HSE或者系统时钟。 

 MCO 

6)任何一个外设在使用之前,必须首先使能其相应的时钟。 

7)需要记住几个重要的时钟 

- SYSCLK(系统时钟) 

- AHB总线时钟 

- APB1总线时钟(低速),速度最高到36MHz 

- APB2总线时钟(高速),速度最高到72MHz 

- PLL时钟 

下面贴一张《STM32中文手册》中的时钟图,该图和上面的图表示的意思是一致的,我们看看官方是如何展示 时钟框图的。 


时钟图

2、(时钟控制)RCC寄存器


typedef struct

{

  __IO uint32_t CR;        //HSI,HSE,CSS,PLL等的使能和就绪标志位 

  __IO uint32_t CFGR;      //PLL等的时钟源选择,分频系数设定

  __IO uint32_t CIR;       //清除/使能 时钟就绪中断

  __IO uint32_t APB2RSTR;  //APB2线上外设复位寄存器

  __IO uint32_t APB1RSTR;  //APB1线上外设复位寄存器

  __IO uint32_t AHBENR;    //DMA,SDIO等时钟使能

  __IO uint32_t APB2ENR;   //APB2线上外设时钟使能

  __IO uint32_t APB1ENR;   //APB1线上外设时钟使能

  __IO uint32_t BDCR;      //备份域控制寄存器

  __IO uint32_t CSR;       //控制状态寄存器

} RCC_TypeDef;


上面是RCC寄存器的结构体定义,结构体中的每个变量的每一位代表什么需要我们参考《STM32中文手册》第6章的6.3小节 RCC寄存器描述来了解,现仅对一个变量CR贴出 参考手册 的描述,其余的就不列出了,参考手册即可。 

CR


3、系统时钟初始化 

上面仅仅是对 时钟控制器 做了一个概念性的介绍,在编写程序时我们一般不直接操作 RCC_TypeDef结构体,而是调用相应的库函数来编程。 

在此我们先看一下 库函数中 系统默认如何初始化这些 寄存器的,我们先看一段汇编程序,我们知道c中默认的程序入口是main函数,那main函数的如何调用的呢,我们先来看如下程序(该程序在startup_stm32f10x_hd.s中可以找到):


; Reset handler

Reset_Handler   PROC

EXPORT  Reset_Handler             [WEAK]

IMPORT  __main

IMPORT  SystemInit

LDR     R0, =SystemInit

BLX     R0               

LDR     R0, =__main

BX      R0

ENDP


从上面的程序中可以看出 在main函数调用前,调用了SystemInit函数,该函数的定义可以在system_stm32f10x.c中找到,源码如下:


#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

/* #define SYSCLK_FREQ_HSE    HSE_VALUE */

 #define SYSCLK_FREQ_24MHz  24000000

#else

/* #define SYSCLK_FREQ_HSE    HSE_VALUE */

/* #define SYSCLK_FREQ_24MHz  24000000 */ 

/* #define SYSCLK_FREQ_36MHz  36000000 */

/* #define SYSCLK_FREQ_48MHz  48000000 */

/* #define SYSCLK_FREQ_56MHz  56000000 */

#define SYSCLK_FREQ_72MHz  72000000

#endif


/*!< Uncomment the following line if you need to use external SRAM mounted

     on STM3210E-EVAL board (STM32 High density and XL-density devices) or on 

     STM32100E-EVAL board (STM32 High-density value line devices) as data memory */ 

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)

/* #define DATA_IN_ExtSRAM */

#endif


/*******************************************************************************

*  Clock Definitions

*******************************************************************************/

#ifdef SYSCLK_FREQ_HSE

  uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_24MHz

  uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_36MHz

  uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_48MHz

  uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_56MHz

  uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */

#elif defined SYSCLK_FREQ_72MHz

  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */

#else /*!< HSI Selected as System Clock source */

  uint32_t SystemCoreClock         = HSI_VALUE;        /*!< System Clock Frequency (Core Clock) */

#endif


__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};


static void SetSysClock(void);


/**

  * @brief  Setup the microcontroller system

  *         Initialize the Embedded Flash Interface, the PLL and update the 

  *         SystemCoreClock variable.

  * @note   This function should be used only after reset.

  * @param  None

  * @retval None

  */

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 

}


/**

 * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.

 * @param  None

 * @retval None

  */

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();

#endif


/* If none of the define above is

[1] [2]

关键字:单片机  STM32  时钟系统

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/ic467532.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32学习笔记之基础介绍(一)(时钟源,系统时钟)
下一篇:STM32时钟系统以及配置及源码分析

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

模拟量数据的采集过程解析

单片机的ADC接口属于模数转换接口,将外部的模拟量信号转化为数字信号,单片机属于数字器件,需将模拟信号转化为数字信号才能够为单片机处理。目前市场的很多单片机都自带ADC转换接口,若无ADC转换接口,可以使用ADC数模转换芯片外扩。ADC模块是将模拟信号转化位数字信号,数字信号用0和1表示,ADC模块有参考电压,假设给的参考电压是5V,ADC是12位的(几位表示用二进制几位数存储模拟量转化后的数字量,12位的ADC则可储存数字量范围为:(二进制)000000000000~111111111111,转换为十进制数字范围为0~2^12即0~4095。也就是说把参考电压分为2^12份即4096份,最小分辨率为VREF/4096。也就是说
发表于 2019-07-13
模拟量数据的采集过程解析

单片机入门学习十三 STM32单片机学习十 通用定时器

本篇重点记录的是STM32F1的通用定时器。 STM32F103ZE有8个定时器,其中2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5),2个基本定时器(TIM6、TIM7)。下表是对这8个定时器的详细描述。定时器种类 位数 计数器模式 产生DMA请求 捕获/比较通道 互补输出 特殊应用场景高级定时器(TIM1,TIM8) 16 向上、向下、向上/下 可以 4 有 带死区控制盒紧急刹车,可应用于PWM电机控制通用定时器(TIM2~TIM5) 16 向上、向下、向上/下 可以 4 无 通用。定时计数,PWM输出,输入捕获,输出比较基本定时器(TIM6,TIM7) 16 向上、向下
发表于 2019-07-12
单片机入门学习十三 STM32单片机学习十 通用定时器

51单片机与蓝牙模块连接

不久前开始学习使用蓝牙模块,在模块与51单片机连接的过程中出现了非常多的问题,我想应该也是很多新手和我一样会遇到这样的问题,因此特地写这篇文章,想分享下在学习过程中遇到的问题以及解决方法。此次学习用到模块是HC-06蓝牙模块,如下图:该模块某宝有售,价格约为20RMB。某宝上的HC-06有两种,分别是带引脚和不带引脚的,建议新手购买带引脚的。我从试验开始到成功,一共使用了四块蓝牙模块。第一次买的是带引脚的,但是模块本身是坏的;第二次买的是不带引脚的,但是由于自身的焊功有限,导致模块损坏,无法使用;第三次是朋友送的蓝牙4.0,由于某些原因无法使用,在此也特别感谢朋友送我蓝牙;第四次购买,就是上图所示的蓝牙,才最终完成了试验。总结
发表于 2019-07-11
51单片机与蓝牙模块连接

单片机中工程的文件结构分析

一直以来都是在原有的工程上直接新建自己的模块文件,现在一到自己新建工程的时候就出现了各种的链接错误(当然我这里说的是多文件的工程,单文件工程不会出现链接错误的),平常接触的51,32,飞思卡尔K66等芯片都的工程都有自己的工程结构。简单的51来说一般都是单文件的工程,毕竟本身的资源不多,引脚定义也少。如果你的工程在各模块编译没有错的情况下,link时出现错误或警告,一定是文件结构有问题。通俗来讲就是乱定义。这里以51为例提供一种常用的工程结构定义,绝对不会出错。/*新建工程后,建立一个总的.h文件可以,暂且命名为include.h。include.h下包含工程下所有的.h文件(包括所需的C库.h和各模块的.h)关于寄存器的定义
发表于 2019-07-09

学好单片机必须要了解的8个电路设计

单片机上拉电阻的选择 大家可以看到复位电路中电阻R1=10k时RST是高电平 ,而当R1=50时RST为低电平,很明显R1=10k时是错误的,单片机一直处在复位状态时根本无法工作。出现这样的原因是由于RST引脚内含三极管,即便在截止状态时也会有少量截止电流,当R取的非常大时,微弱的截止电流通过就产生了高电平。LED串联电阻的计算问题通常红色贴片LED:电压1.6V-2.4V,电流2-20mA,在2-5mA亮度有所变化,5mA以上亮度基本无变化。 端口出现不够用的情况这时可以借助扩展芯片来实现,比如三八译码器74HC138来拓展。 滤波电容滤波电容分为高频滤波电容和低频滤波电容。1、高频滤波电容一般
发表于 2019-07-08
学好单片机必须要了解的8个电路设计

STM32开发笔记71: 解决FreeRTOS任务的内存分配问题

单片机型号:STM32F091RCT6在使用FreeRTOS进行程序设计时,遇到任务不能运行的问题,具体程序如下: DebugOutput("启动USB通讯线程...rnrn"); osThreadDef(usbTask, StartUsbTask, osPriorityNormal, 0, 128); usbTaskHandle = osThreadCreate(osThread(usbTask), NULL); DebugOutput("启动雷达红外通讯线程...rnrn"); osThreadDef(irdaTask, St
发表于 2019-07-13

小广播

何立民专栏

单片机及嵌入式宝典

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

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved