STM32F103系统时钟配置

news2024/11/24 6:14:24

时钟是单片机运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是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;                    //PLLON
	 while(!(((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_RAM
	      NVIC_SetVectorTable(0x20000000,0x00);
	   #else
	      NVIC_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.coloradmin.cn/o/2244845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙进阶篇-Math、Date

“在科技的浪潮中&#xff0c;鸿蒙操作系统宛如一颗璀璨的新星&#xff0c;引领着创新的方向。作为鸿蒙开天组&#xff0c;今天我们将一同踏上鸿蒙基础的探索之旅&#xff0c;为您揭开这一神奇系统的神秘面纱。” 各位小伙伴们我们又见面了,我就是鸿蒙开天组,下面让我们进入今…

RAID存储技术 详解

RAID&#xff08;Redundant Array of Independent Disks&#xff0c;独立磁盘冗余阵列&#xff09;是一种将多个物理硬盘组合为一个逻辑存储单元的技术。它通过分布数据、冗余校验和容错能力&#xff0c;提高存储系统的性能、可靠性和容量利用率。 以下从底层原理和源代码层面…

MTK主板定制_联发科主板_MTK8766/MTK8768/MTK8788安卓主板方案

主流市场上的MTK主板通常采用联发科的多种芯片平台&#xff0c;如MT8766、MT6765、MT6762、MT8768和MT8788等。这些芯片基于64位Cortex-A73/A53架构&#xff0c;提供四核或八核配置&#xff0c;主频可达2.1GHz&#xff0c;赋予设备卓越的计算与处理能力。芯片采用12纳米制程工艺…

免费微调自己的大模型(llama-factory微调llama3.1-8b)

目录 1. 名词/工具解释2. 微调过程3. 总结 本文主要介绍通过llama-factory框架&#xff0c;使用Lora微调方法&#xff0c;微调meta开源的llama3.1-8b模型&#xff0c;平台使用的是趋动云GPU算力资源。 微调已经经过预训练的大模型目的是&#xff0c;通过调整模型参数和不断优化…

MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?

MySQL中的InnoDB存储引擎支持四种事务隔离级别&#xff0c;这些级别定义了事务在并发环境中的行为和相互之间的可见性。以下是这四种隔离级别的名称以及它们之间的区别&#xff1a; 读未提交&#xff08;Read Uncommitted&#xff09; 特点&#xff1a;这是最低的隔离级别&…

【YOLOv10改进[注意力]】引入并行分块注意力PPA(2024.3.16) + 适于微小目标

本文将进行在YOLOv10中引入并行分块注意力PPA魔改v10 的实践,文中含全部代码、详细修改方式。助您轻松理解改进的方法。 一 HCF 论文题目:Hierarchica

共建智能软件开发联合实验室,怿星科技助力东风柳汽加速智能化技术创新

11月14日&#xff0c;以“奋进70载&#xff0c;智创新纪元”为主题的2024东风柳汽第二届科技周在柳州盛大开幕&#xff0c;吸引了来自全国的汽车行业嘉宾、技术专家齐聚一堂&#xff0c;共襄盛举&#xff0c;一同探寻如何凭借 “新技术、新实力” 这一关键契机&#xff0c;为新…

在ubuntu下,使用Python画图,无法显示中文怎么解决

1.首先需要下载中文字体&#xff0c;推荐simsun&#xff0c;即宋体&#xff0c;地址如下 https://www.freefonts.io/download/simsun/ 2.下载完要把字体文件放进字体目录&#xff0c;具体方法如下&#xff1b; a.创建字体目录&#xff1a;sudo mkdir -p /usr/share/fonts/truet…

鸿蒙实战:使用显式Want启动Ability

文章目录 1. 实战概述2. 实现步骤2.1 创建鸿蒙应用项目2.2 修改Index.ets代码2.3 创建SecondAbility2.4 创建Second.ets 3. 测试效果4. 实战总结5. 拓展练习 - 启动文件管理器5.1 创建鸿蒙应用项目5.2 修改Index.ets代码5.3 测试应用运行效果 1. 实战概述 本实战详细阐述了在 …

《Python浪漫的烟花表白特效》

一、背景介绍 烟花象征着浪漫与激情&#xff0c;将它与表白结合在一起&#xff0c;会创造出别具一格的惊喜效果。使用Python的turtle模块&#xff0c;我们可以轻松绘制出动态的烟花特效&#xff0c;再配合文字表白&#xff0c;打造一段专属的浪漫体验。 接下来&#xff0c;让…

springboot中设计基于Redisson的分布式锁注解

如何使用AOP设计一个分布式锁注解&#xff1f; 1、在pom.xml中配置依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.3.26</version></dependency><dependenc…

绕过CDN寻找真实IP

在新型涉网案件中&#xff0c;我们在搜集到目标主站之后常常需要获取对方网站的真实IP去进一步的信息搜集&#xff0c;但是现在网站大多都部署了CDN&#xff0c;将资源部署分发到边缘服务器&#xff0c;实现均衡负载&#xff0c;降低网络堵塞&#xff0c;让用户能够更快地访问自…

【Redis】redis缓存击穿,缓存雪崩,缓存穿透

一、什么是缓存&#xff1f; 缓存就是与数据交互中的缓冲区&#xff0c;它一般存储在内存中且读写效率高&#xff0c;提高响应时间提高并发性能&#xff0c;如果访问数据的话可以先访问缓存&#xff0c;避免数据查询直接操作数据库&#xff0c;造成后端压力过大。 但是可能会面…

linux复习5:C prog

编辑 缩排 为了使C源代码更加整洁易读&#xff0c;可以使用一些工具来自动格式化代码&#xff0c;例如cb&#xff08;C程序美化器&#xff09;、bcpp&#xff08;C美化器&#xff09;和indent等。 编译 编译并链接C文件 gcc hello.c -o hello 将 hello.c 编译并链接成可执行文…

uni-app快速入门(十)--常用内置组件(下)

本文介绍uni-app的textarea多行文本框组件、web-view组件、image图片组件、switch开关组件、audio音频组件、video视频组件。 一、textarea多行文本框组件 textarea组件在HTML 中相信大家非常熟悉&#xff0c;组件的官方介绍见&#xff1a; textarea | uni-app官网uni-app,un…

世界坐标系、相机坐标系、图像物理坐标系、像素平面坐标系

坐标系及其转换在计算机视觉领域占据核心地位。理解如何从一个坐标系转换到另一个坐标系&#xff0c;不仅是理论上的需要&#xff0c;也是实际应用中不可或缺的技能。 一、世界坐标系的定义 世界坐标系是一个全局的坐标系统&#xff0c;用于定义场景中物体的位置。在这个坐标…

机器学习笔记——聚类算法(Kmeans、GMM-使用EM优化)

本笔记介绍机器学习中常见的聚类算法&#xff08;Kmeans、GMM-使用EM优化&#xff09;。 文章目录 聚类K-Means工作原理特点 K-Medoids工作原理特点 Mini-Batch K-Means工作原理特点 K-Means&#xff08;重要&#xff09;工作原理特点 总结K的选值1. 肘部法则&#xff08;Elbow…

浅议Flink中的通讯工具: Akka

在Flink中&#xff0c;各个组件之间需要频繁交换数据和控制信息。Flink选择了基于Actor模型的Akka框架作为通信基础。 Akka是什么 Actor模型 Actor模型是用于单个进程中并发的场景。 在Actor模型中&#xff1a; ActorSystem负责管理actor生命周期 将每个实体视为独立的 Ac…

如何在react中使用react-monaco-editor渲染出一个编辑器

一、效果展示 二、基于vite配置 1.首先安装react-monaco-editor和monaco-editor包 npm add react-monaco-editor npm i monaco-editor 2.其次创建一个单独的文件&#xff08;此处是tsx、直接用app或者jsx也行&#xff09; import { useState, useEffect } from react impo…

孙玲:从流水线工人到谷歌程序员

这是《开发者说》的第24期&#xff0c;本期我们邀请的开发者是孙玲&#xff0c;她出生于湖南娄底一个贫穷的农村家庭&#xff0c;2009年高考落榜&#xff0c;她去了深圳一家电子厂&#xff0c;在流水线上给电池喷码&#xff0c;每天12个小时轮班&#xff0c;月薪2300&#xff0…