STM32F103系统时钟配置

时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定CPU速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而单片机有了时钟,才能够运行执行指令,才能够做其他的处理 (点灯,串口,ADC),时钟的重要性不言而喻。

一、STM32F103时钟介绍

STM32F103本身十分复杂,外设非常多 但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费 并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的MCU都是采用多时钟源的方法来解决这些问题。所以便有了STM32F103的时钟系统和时钟树。

1.1 系统时钟

系统时钟(SYSCLK)有多种选择,图中左边的部分就是设置系统时钟使用那个时钟源;

  • HSI振荡器时钟:HSI是高速内部时钟,RC振荡器,频率为8MHz,精度不高;
  • HSE振荡器时钟:HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz
  • PLL时钟;其时钟输入源可选择为HSI/2HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz

系统时钟的右边,则是系统时钟通过AHB预分频器,给相对应的外设设置相对应的时钟频率.

从左到右可以简单理解为 各个时钟源--->系统时钟来源的设置--->各个外设时钟的设置。

在我们使用的STM32F103F103开发板中:

  • OSC32_INOSC32_OUT连接了32.768kHz的晶振,用于给RTC提供时钟信号;
  • OSC_INOSC_OUT连接了8MHz的晶振,作为系统时钟的来源。

Keil编写程序是默认的时钟为72Mhz,其实是这么来的:

  • 外部晶振(HSE)提供的8MHz通过PLLXTPRE分频器后;
  • 进入PLLSRC选择开关;
  • 进而通过PLLMUL锁相环进行倍频(x9)后,为系统提供72MHz的系统时钟(SYSCLK);
  • 之后是AHB预分频器对时钟信号进行分频,然后为低速外设提供时钟。
1.2 USB时钟

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

1.3 时钟输出到外部

STM32F103可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSIHSE、或者系统时钟。可以把时钟信号输出供外部使用。

1.4 外设时钟

系统时钟通过AHB分频器给外设提供时钟,AHB分频器可选择12481664128256512分频。其中AHB分频器输出的时钟送给如下模块使用:

  • SDIO;
  • FSMC;
  • 内核总线:送给AHB总线、核心存、储器和DMA使用的HCLK时钟。;
  • Tick定时器:通过8分频后送给Cortex的系统定时器时钟;
  • 直接送给Cortex的空闲运行时钟FCLK
  • APB1外设:送给APB1分频器。APB1分频器可选择124816分频;
    • 其输出一路供APB1外设使用(PCLK1,最大频率36MHz);
    • 另一路送给通用定时器使用。该倍频器可选择1或者2倍频,时钟输出供定时器2-7使用;
  • APB2外设:送给APB2分频器。APB2分频器可选择124816分频:
    • 其输出一路供APB2外设使用(PCLK2,最大频率72MHz);
    • 另一路送给高级定时器。该倍频器可选择1或者2倍频,时钟输出供定时器1和定时器8使用;
    • 另外APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为2468分频;
  • 经过2分频送至SDIOAHB

需要注意的是,如果APB预分频器分频系数是1,则定时器时钟频率 (TIMxCLK)PCLKx。否则,定时器时钟频率将为APB域的频率的两倍:TIMxCLK = 2xPCLKx

1.4.1 APB1APB2的对应外设

APB1上面连接的是低速外设,包括电源接口、备份接口、CANUSBI2C1I2C2USART2USART3UART4UART5SPI2SP3等;

APB2上面连接的是高速外设,包括UART1SPI1Timer1ADC1ADC2ADC3、所有的普通I/O口(PA-Pg)、第二功能I/O(AFIO)口等。

二、时钟相关寄存器

2.1 时钟控制寄存器(RCC_CR)
2.2 时钟配置寄存器(RCC_CFGR)
2.3 时钟中断寄存器(RCC_CIR)
2.4 APB2外设复位寄存器(RCC_APB2RSTR))
2.5 APB1外设复位寄存器(RCC_APB1RSTR))
2.6 AHB外设使能寄存器(RCC_AHBENR)
2.7 APB2外设时钟使能寄存器(RCC_APB2ENR)
2.8 APB1外设时钟使能寄存器(RCC_APB1ENR)

三、时钟配置源码

3.1 RCC_TypeDeff

RCC寄存器结构RCC_TypeDeff,在文件stm32f10x_map.h中定义如下:

/*------------------------ Reset and Clock Control ---------------------------*/
typedef struct
{vu32 CR;	     // 时钟控制寄存器 ;vu32 CFGR;	 // 时钟配置寄存器 ;vu32 CIR;		 // 时钟中断寄存器 ;vu32 APB2RSTR; // APB2外设复位寄存器 ;vu32 APB1RSTR; // APB1外设复位寄存器 ;vu32 AHBENR;	 // AHB外设时钟使能寄存器 ;vu32 APB2ENR;	 // APB2外设时钟使能寄存器 ;vu32 APB1ENR;	 // APB1外设时钟使能寄存器 ;vu32 BDCR;	 // 备份域控制寄存器 ;vu32 CSR;		 // 控制/状态寄存器 ;
} RCC_TypeDef;#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)#ifdef _RCC#define RCC                 ((RCC_TypeDef *) RCC_BASE)
#endif /*_RCC */

在第二节中我们已经对RCC_TypeDef结构体中定义的大部分结构体进行了详细的介绍,那么我们如何编码去初始化这些寄存器呢?

3.2 RCC初始化

这里我们采用HSE作为系统时钟输出,正常使用的时候也都是使用外部时钟。其初始化流程如下:

(1) APB1外设复位,复位结束;

  • RCC_APB1RSTR寄存器每一位写入1,然后再写入0;

(2) APB2外设复位,复位结束;

  • RCC_APB2RSTR寄存器每一位写入1,然后再写入0;

(3)AHB开启SRAM、闪存(睡眠模式时);

(4)APB1外设时钟关闭;

  • RCC_APB1ENR寄存器每一位写入0;

(5)APB2外设时钟关闭;

RCC_APB2ENR寄存器每一位写入0;

(6)复位MCOUSBPREPLLMULPLLXTRREPLLSRCADCPREPPRE2PPRE1HPRESWPLLONCSSONHSEBYPHSEON

  • RCC_CR寄存器相应位写入0;
  • RCC_CFGR寄存相应位写入0;

(7) 设置:

  • HSEON使能:开启高速外部时钟信号,即设置RCC_CR寄存器的位16为1;
  • 等待HSERDY就绪:即等待RCC_CR寄存器位17置1;
  • 设置APB1APB2AHB分频系数、PLL倍频系数;
    • 系统时钟为72MHzPLL倍频系数设置为9,即RCC_CFGR寄存器位[21:18]设置为0111b
    • AHB预分频器设置为1分频:即RCC_CFGR寄存器位[7:4]设置为0xxxb
    • APB1预分频器由RCC_CFGR寄存器位[10:8]设置;如果设置为2分频,则时钟频率为36MHz
    • APB2预分频器由RCC_CFGR寄存器位[13:11]设置;如果设置为1分频,则时钟频率为72MHz
  • 设置PLLSRC:选择HSE时钟作为PLL输入时钟;
    • 设置HSE时钟作为PLL输入时钟,即RCC_CFGR寄存器位16设置为1;
  • PLL使能:即设置RCC_CR寄存器的位24为1;
  • 等待PLL就绪:即等待RCC_CR寄存器位25置1;
  • 设置SW:系统时钟切换PLL作为系统时钟,即设置RCC_CFGR寄存器的位[1:0]10b
  • 等待PLL切换为系统时钟输入源:即等待RCC_CFGR寄存器的位[3:2]10b
3.2.1 STM32_Clock_Init
/*******************************************************************************************************	   Description:系统时钟初始化PLL        :倍频系数 2~16    *					APB1设置为2分频,APB2设置为1分频,AHB设置为1分频*                  设置PLLCLK作为系统时钟*****************************************************************************************************/void STM32_Clock_Init(u8  PLL){u8 temp=0;RCC_Init();                             //复位并配置向量表RCC->CR |=0x00010000;                   //外部高速时钟使能HSEON:即外部晶振(4MHZ~16MHZ)while(!(((RCC->CR>>17)&0x01)==0x01));   //等待外部时钟就绪RCC->CFGR = 0x00000400;                 //APB1设置为2分频,APB2设置为1分频,AHB设置为1分频PLL-=2;                                 //抵消两个单元RCC->CFGR|=PLL<<18;                     //设置PLL的值2~16      RCC->CFGR|=1<<16;                       //PLLSRC ON  HSE时钟作为PLL输入时钟FLASH->ACR |= 0x32;                     //FLASH两个延时周期RCC->CR|=0x01000000;                    //PLLONwhile(!(((RCC->CR>>25)&0x01)==0x01));   //等待PLL锁定RCC->CFGR|=0x02;                        //PLL作为系统时钟while(temp!=0x02)                       //等待PLL作为系统时钟设置成功{temp = RCC->CFGR>>2;temp&=0x03;}     }

我们只需要在 main函数开始调用该函数,传入参数9,即可设置系统时钟为72MHz

STM32_Clock_Init(9);         	          //系统时钟初始化
3.2.2 RCC_Init
/*******************************************************************************************************	   Description:复位外设,并关断所有中断,同时配置中断向量表*					APB1RST:APB1外设复位寄存器 0:无效      1:复位外设APB1RST:APB2外设复位寄存器 0:无效      1:复位外设AHBENR :AHB 外设时钟使能寄存器 CR      :时钟控制寄存器CFGR    :时钟配置寄存器ICR     :中断标志寄存器*****************************************************************************************************/
void RCC_Init(void)
{RCC->APB1RSTR = 0x00;         //APB1外设初始化复位结束 RCC->APB2RSTR = 0x00;         //APB2外设初始化复位结束RCC->AHBENR   = 0x14;         //睡眠模式时闪存接口电路时钟开启,睡眠模式时SRAM时钟开启,DMA时钟关闭RCC->APB2ENR = 0x00;          //APB2总线上外设时钟关闭RCC->APB1ENR = 0x00;          //APB1总线上外设时钟关闭RCC->CFGR    &= 0xF8000000;   //复位SW[3:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0],PLLSRC,PLLXTPRE,PLLMUL[3:0],USBPRE  RCC->CR      &= 0xFEF2FFFF;   //复位HSEON,CSSON,PLLON,HSEBYP    RCC->CIR      = 0x00000000;   //关闭所有中断/********** 配置中断向量表 ***********************/#ifdef VECT_TAB_RAMNVIC_SetVectorTable(0x20000000,0x00);#elseNVIC_SetVectorTable(0x08000000,0x00);#endif
}
3.2.3 NVIC_SetVectorTable
/*******************************************************************************************************	   Description:设置向量表偏移地址NVIC_VectorTable:基址Offset:       偏移量****************************************************************************************************/
void NVIC_SetVectorTable(u32 NVIC_VectorTable,u32 Offset)
{SCB->VTOR = NVIC_VectorTable|(Offset&(u32)0x1FFFFF80);   //设置NVIC的向量表偏移寄存器,用于标识向量表是在CODE区,还是在RAM区
}

四、源码下载

源码下载路径:stm32f103

参考文章

[1] STM32F103时钟系统讲解

[2] Mini2440裸机开发之系统时钟配置

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/475515.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年 Web3开发学习路线全指南

Web3是一个包含了很多领域的概念&#xff0c;不讨论币圈和链圈的划分&#xff0c;Web3包括有Defi、NFT、Game等基于区块链的Dapp应用的开发&#xff1b;也有VR、AR等追求视觉沉浸感的XR相关领域的开发&#xff1b;还有基于区块链底层架构或者协议的开发。 这篇文章给出的学习路…

CTF--php伪协议结合Base64绕过

Base64绕过 在ctf中&#xff0c;base64是比较常见的编码方式&#xff0c;在做题的时候发现自己对于base64的编码和解码规则不是很了解&#xff0c;并且恰好碰到了类似的题目&#xff0c;在翻阅了大佬的文章后记录一下&#xff0c;对于base64编码的学习和一个工具 base64编码是…

Linux 命令之 tar

文章目录 1 tar 命令介绍2 压缩与解压缩2.1 压缩2.2 解压 4 高级用法4.1 排除目录4.2 显示进度4.2.1 脚本解压缩4.2.2 命令解压缩4.2.3 压缩进度 1 tar 命令介绍 常见的压缩包有 .tar.gz、.tar.xz、.tar.bz2&#xff0c;以及 .rar、.zip、.7z 等压缩包。 常见的 tar 选项&#…

Jenkins修改LOGO

重启看的LOGO和登录页面左上角的LOGO 进入LOGO存在的目录 [roottest-server01 svgs]# pwd /opt/jenkins_data/war/images/svgs [roottest-server01 svgs]# ll logo.svg -rw-r--r-- 1 jenkins jenkins 29819 Oct 21 10:58 logo.svg #jenkins_data目录是我挂载到了/opt目录&…

【大模型】LLaMA: Open and Efficient Foundation Language Models

链接&#xff1a;https://arxiv.org/pdf/2302.13971 论文&#xff1a;LLaMA: Open and Efficient Foundation Language Models Introduction 规模和效果 7B to 65B&#xff0c;LLaMA-13B 超过 GPT-3 (175B)Motivation 如何最好地缩放特定训练计算预算的数据集和模型大小&…

vue添加LCD字体(液晶字体)数字美化,前端如何引用LCD字体液晶字体,如何转换?@font-face 如何使用?

文章目录 一、效果二、下载字体格式【[https://www.dafont.com/theme.php?cat302&text0123456789](https://www.dafont.com/theme.php?cat302&text0123456789)】三、下载后&#xff0c;解压后都是.ttf文件&#xff0c;在【[https://www.fontsquirrel.com/tools/webfo…

【大数据学习 | Spark】关于distinct算子

只有shuffle类的算子能够修改分区数量&#xff0c;这些算子不仅仅存在自己的功能&#xff0c;比如分组算子groupBy&#xff0c;它的功能是分组但是却可以修改分区。 而这里我们要讲的distinct算子也是一个shuffle类的算子。即可以修改分区。 scala> val arr Array(1,1,2,…

Qt桌面应用开发 第五天(常用控件 自定义控件)

目录 1.QPushButton和ToolButton 1.1QPushButton 1.2ToolButton 2.RadioButton和CheckBox 2.1RadioButton单选按钮 2.2CheckBox多选按钮 3.ListWidget 4.TreeWidget控件 5.TableWidget控件 6.Containers控件 6.1QScrollArea 6.2QToolBox 6.3QTabWidget 6.4QStacke…

Excel - VLOOKUP函数将指定列替换为字典值

背景&#xff1a;在根据各种复杂的口径导出报表数据时&#xff0c;因为关联的表较多、数据量较大&#xff0c;一行数据往往会存在三个以上的字典数据。 为了保证导出数据的效率&#xff0c;博主选择了导出字典code值后&#xff0c;在Excel中处理匹配字典值。在查询百度之后&am…

ctfshow-web入门-SSRF(web351-web360)

目录 1、web351 2、web352 3、web353 4、web354 5、web355 6、web356 7、web357 8、web358 9、web359 10、web360 1、web351 看到 curl_exec 函数&#xff0c;很典型的 SSRF 尝试使用 file 协议读文件&#xff1a; urlfile:///etc/passwd 成功读取到 /etc/passwd 同…

【vmware+ubuntu16.04】ROS学习_博物馆仿真克隆ROS-Academy-for-Beginners软件包处理依赖报错问题

首先安装git 进入终端&#xff0c;输入sudo apt-get install git 安装后&#xff0c;创建一个工作空间名为tutorial_ws&#xff0c; 输入 mkdir tutorial_ws#创建工作空间 cd tutorial_ws#进入 mkdir src cd src git clone https://github.com/DroidAITech/ROS-Academy-for-Be…

AI数字人视频小程序:引领未来互动新潮流

当下&#xff0c;随着人工智能技术的不断创新发展&#xff0c;各类AI系统已经成为了创新市场发展的重要力量&#xff0c;AI文案、AI数字人、AI视频等&#xff0c;为大众带来更加便捷的创作方式&#xff0c;AI成为了一个全新的风口&#xff0c;各种AI红利持续释放&#xff0c;市…

leetcode400第N位数字

代码 class Solution {public int findNthDigit(int n) {int base 1;//位数int weight 9;//权重while(n>(long)base*weight){//300n-base*weight;base;weight*10;}//n111 base3 weight900;n--;int res (int)Math.pow(10,base-1)n/base;int index n%base;return String…

MySQL扩展varchar字段长度能否Online DDL

目录 问题场景 Online DDL 简介 场景复现 DBdoctor快速识别 Online DDL 总结 问题场景 在MySQL数据库中&#xff0c;DDL变更可以通过两种算法实现&#xff1a;Copy算法和In-Place算法。Copy算法会复制整个表&#xff0c;这可能导致长时间的写入阻塞&#xff0c;从而严重影…

【WPF】Prism学习(九)

Prism Dependency Injection 1.Container Locator 1.1. Container Locator的引入&#xff1a; Container Locator是在Prism 8.0版本中新引入的一个特性。它的目的是为了帮助Prism框架摆脱对CommonServiceLocator的依赖&#xff0c;并解决一些必须回退到ServiceLocator模式的内…

.NET 9与C# 13革新:新数据类型与语法糖深度解析

记录&#xff08;Record&#xff09;类型 使用方式&#xff1a; public record Person(string FirstName, string LastName); 适用场景&#xff1a;当需要创建不可变的数据结构&#xff0c;且希望自动生成 GetHashCode 和 Equals 方法时。不适用场景&#xff1a;当数据结构需…

3C产品说明书电子化转变:用户体验、环保与商业机遇的共赢

在科技日新月异的当代社会&#xff0c;3C产品&#xff08;涵盖计算机类、通信类和消费类电子产品&#xff09;已成为我们日常生活中不可或缺的重要元素。与此同时&#xff0c;这些产品的配套说明书也经历了一场从纸质到电子化的深刻变革。这一转变不仅体现了技术的飞速进步&…

GIT 入门详解指南

前言&#xff1a; 注&#xff1a;本博客仅用于记录本人学习过程中对git的理解&#xff0c;仅供学习参考&#xff0c;如有异议请自行查资料求证 安装 使用git之前必须完成git的安装&#xff0c;Git 目前支持 Linux/Unix、Solaris、Mac和 Windows 平台上运行 git 安装教程 基本…

【数据结构】用四个例子来理解动态规划算法

1. 动态规划 动态规划&#xff08;Dynamic Programming, DP&#xff09;是一种通过将复杂问题分解为更小的子问题来求解的算法设计思想&#xff0c;一般用于求解具有最优子结构和重叠子问题性质的问题。动态规划的核心在于&#xff1a;&#xff08;1&#xff09;最优子结构--问…

前端两大利器:Vue与TypeScript的渊源

Vue 在前端领域占据着重要地位&#xff0c;是最受欢迎的前端框架之一。它被广泛应用于各种类型的 Web 应用开发&#xff0c;从简单的小型项目&#xff0c;如个人博客、公司宣传网站等&#xff0c;到复杂的大型企业级应用&#xff0c;如电商平台、金融系统等。例如&#xff0c;许…