STM32-寄存器时钟配置指南

目录

启动

SystemInit

SetSysClock

 总结


启动

从startup_stm32f0xx.s内的开头的Description可以看到

;* Description        : STM32F051 devices vector table for EWARM toolchain.
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == iar_program_start,
;*                      - Set the vector table entries with the exceptions ISR 
;*                        address
;*                      - Configure the system clock
;*                      - Branches to main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the Cortex-M0 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.

可以得知STM32的启动流程是首先初始化SP(堆栈种指针),初始化PC(程序计数器)指针指向__iar_program_start,设置向量表,初始化时钟系统

可以看到初始化时钟系统是在设置堆栈后,并且运行__iar_program_start设置了硬之后,这是必要的。

startup的汇编内容

这也就是所有MCU启动过程中的第一步:使用汇编语言编写的启动第一部分,设置堆栈和硬件为第二部分的启动铺垫。

第二部是使用C语言编写的启动第二部分

接下来直接跳转到SystemInit

SystemInit

1.在初始化的第一步

void SystemInit (void)
{    /* Set HSION bit */RCC->CR |= (uint32_t)0x00000001;

通过数据手册可以看到

打开了HSI时钟

为什么第一步先要打开HSI时钟呢?

         在许多微控制器中,HSI (High Speed Internal) 时钟通常是第一个被启用的时钟源,这是因为HSI时钟是内置在微控制器内部的,不需要外部晶振或陶瓷谐振器就能工作,因此它是最容易且快速可用的时钟源

2.

/* Reset SW[1:0], HPRE[3:0], PPRE[2:0], ADCPRE, MCOSEL[2:0], MCOPRE[2:0] and PLLNODIV bits */ 
RCC->CFGR &= (uint32_t)0x08FFB80C;
//0000 0100 1000 1111 1111 1011 1000 0000 1100

在时钟配置寄存器中,从低位开始看

SW(00)使用HSI作为系统时钟

SWS(11)不使用系统时钟切换状态

HPRE(0000)SYSCLK不分频

PPRE(0000)HCLK不分频

PLLSRC(1)HSE/PREDIV作为PLL输入时钟

PLLXTPRE(1)HSE 2分频

PLLMUL(1111)PLL倍频系数,PLL输入时钟的16倍频

MCO(100)控制器时钟输出为系统时钟SYSCLK

总体可以看到在systemInit中使用了HSI作为系统时钟,HSE作为PLL输入时钟,HSI提供了即时性,HSE提供了可靠性

3.

  /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= (uint32_t)0xFEF6FFFF;
//1111 1110 1111 0110 1111 1111 1111 1111

从低位开始可以得知

HSION(1)启动HSI振荡器

HSEON(1)启动HSE振荡器

HSEBYP(1)HSE晶体振荡器有旁路

CSSON(0)时钟检测器关闭

PLLON(0)PLL关闭

PLLRDY(1)PLL锁定

注意在这里关闭并且锁定了PLL

4.

  /* Reset HSEBYP bit */RCC->CR &= (uint32_t)0xFFFBFFFF;
//1111 1111 1111 1011 1111 1111 1111 1111

可以看确保HSE振荡器不是在旁路模式下工作,而是使用内部电路来产生时钟信号。

需要使用HSE振荡器作为系统时钟的一部分时。在启动阶段,可能首先使用HSI(高速内部振荡器)作为时钟源,随后配置HSE振荡器,并可能使用HSE作为PLL(锁相环)的输入,以产生更高频率的系统时钟

5.

  /* Reset PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */RCC->CFGR &= (uint32_t)0xFFC0FFFF;

将PLLSRC位清零,意味着PLL的输入时钟将默认为HSI经过预分频后的时钟(如果HSI可用并且已经使能)。
将PL LXTPRE位清零,如果选择了HSE作为PLL输入时钟,那么它不会通过预分频器。
将PLLMUL[3:0]位清零,PLL的乘法因子将被重置为其默认或最小值。 

6.

  /* Reset PREDIV1[3:0] bits */RCC->CFGR2 &= (uint32_t)0xFFFFFFF0;

将PREDIV1[3:0]位清零,将预分频器1的分频比数重置为其最小值或默认值,不进行分频

7.

  /* Reset USARTSW[1:0], I2CSW, CECSW and ADCSW bits */RCC->CFGR3 &= (uint32_t)0xFFFFFEAC;

分别配置了USART,I2C,HDMI CEC, ADC时钟源

PCLK作为USART时钟源

HSI作为I2C1的时钟源

HSI/244作为HDMI CEC时钟源

PCLK 2或4分频作为ADC时钟

8.

  /* Reset HSI14 bit */RCC->CR2 &= (uint32_t)0xFFFFFFFE;

禁用了HSI14

HSI14 和 HSI 不完全相同,尽管它们都是 STM32 微控制器内部集成的 RC(电阻-电容)振荡器,但它们有各自的特点和用途:

HSI (High Speed Internal Oscillator)
HSI 是一个典型的内部振荡器,通常提供大约 8 MHz 或 16 MHz 的时钟频率,具体取决于微控制器的型号。HSI 在上电或复位后默认启用,可以作为系统时钟源,为整个微控制器提供时钟信号。
HSI 通常用于在没有外部时钟源时快速启动系统,或者在低功耗模式下作为时钟源。
HSI14 (High Speed Internal 14 MHz Oscillator)
HSI14 提供一个大约 14 MHz 的时钟频率,专为 USB 和某些高级定时器(如 TIM1 和 TIM8)设计。在 STM32 微控制器中,HSI14 主要用于 USB 全速(Full Speed)应用和高级定时器,因为它们需要一个稳定的时钟源。
HSI14 的主要优点在于它可以直接为 USB 设备提供所需的确切时钟频率,而无需额外的时钟调节或 PLL 放大。
总结来说,HSI 和 HSI14 都是内部振荡器,但它们的频率和用途不同。HSI 更倾向于作为系统时钟源,而 HSI14 则专门用于需要特定时钟频率的外设,如 USB 和某些高级定时器。在某些 STM32 系列中,HSI14 不是默认启用的,需要在软件中显式地配置和启用。

9.

  /* Disable all interrupts */RCC->CIR = 0x00000000;

失能所有的中断

之后就进入下面函数来设置时钟预频率 总线预分频 和 FLASH设置

  /* Configure the System clock frequency, AHB/APBx prescalers and Flash settings */SetSysClock();

SetSysClock

这段代码是STM32微控制器中用于配置系统时钟的一个函数,名为`SetSysClock()`。下面是对这段代码详细步骤的解释:

1. 初始化变量:
   `StartUpCounter` 和 `HSEStatus` 分别用于跟踪HSE启动超时计数和HSE状态。

  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

2. 启用HSE:
   通过设置RCC_CR寄存器的HSEON位来启动高速外部振荡器(HSE)。

  /* Enable HSE */    RCC->CR |= ((uint32_t)RCC_CR_HSEON);

3. 等待HSE就绪:
   使用一个循环检查RCC_CR寄存器的HSERDY位,以确认HSE是否已经稳定。如果HSE在指定时间内未能准备好,`StartUpCounter`将增加,直至达到`HSE_STARTUP_TIMEOUT`常量,此时将退出循环。

do{HSEStatus = RCC->CR & RCC_CR_HSERDY;StartUpCounter++;  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

4. 检查HSE状态:
   如果HSE成功启动,`HSEStatus`设置为0x01,否则设置为0x00。

5. 配置Flash预取缓冲区和等待周期:

  if ((RCC->CR & RCC_CR_HSERDY) != RESET){HSEStatus = (uint32_t)0x01;}else{HSEStatus = (uint32_t)0x00;}  


   如果HSE成功启动,接下来配置Flash访问控制寄存器(FLASH_ACR)以启用预取缓冲区,并设置适当的等待周期。

6. 配置AHB和APB总线时钟:
   设置RCC_CFGR寄存器的HPRE和PPRE位,以确定AHB和APB总线的预分频因子。在这个例子中,HCLK(AHB总线时钟)和PCLK(APB总线时钟)都被设置为与SYSCLK(系统时钟)相同。

/* Enable Prefetch Buffer and set Flash Latency */FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY;/* HCLK = SYSCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;/* PCLK = HCLK */RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;

7. 配置PLL:
   清除RCC_CFGR寄存器中与PLL源选择、PLL输入时钟预分频和PLL倍频因子相关的位。
   配置PLL以使用HSE作为输入时钟源,经过预分频器,并将PLL的倍频因子设置为6,这意味着最终的PLL输出频率将为HSE频率的6倍(假设HSE为8 MHz,PLL输出将为48 MHz)。

  /* PLL configuration = HSE * 6 = 48 MHz */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLMULL6);

8. 启用PLL:

    /* Enable PLL */RCC->CR |= RCC_CR_PLLON;

    通过设置RCC_CR寄存器的PLLON位来启动PLL。

9. 等待PLL就绪:
   使用循环检查RCC_CR寄存器的PLLRDY位,以确认PLL是否已经稳定。

/* Wait till PLL is ready */while((RCC->CR & RCC_CR_PLLRDY) == 0){}

10. 选择PLL作为系统时钟源:
    将RCC_CFGR寄存器的SW位设置为PLL,选择PLL作为系统时钟源。

    /* Select PLL as system clock source */RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;    

11. 等待PLL作为系统时钟源:
    使用循环检查RCC_CFGR寄存器的SWS位,以确认PLL是否已经被选为系统时钟源。

    /* Wait till PLL is used as system clock source */while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)RCC_CFGR_SWS_PLL){}

12. 处理HSE启动失败:
    如果HSE未能启动,函数将到达此处,这里可以添加代码来处理这种错误情况,例如重启系统或进入错误处理程序。

else{ /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error */}  

SetSysClock()函数的主要目的是配置系统时钟,使其能够以期望的频率运行。在这个例子中,它首先启用并确认HSE的运行,然后使用HSE作为PLL的输入,通过PLL生成48 MHz的时钟信号,并最终选择PLL作为系统时钟源,从而为整个微控制器提供一个稳定且足够高的时钟频率。

 总结

可以看到STM32的时钟启动方案是在SystemInit中,首先开启了快速易用的HSI作为系统时钟,并且关闭了所有中断,关闭了HSI14,之后在SetSysClock中重启PLL选择了HSE作为系统时钟。

初始化的后期启用HSE并使用PLL来进一步提高系统时钟频率,这种方案有几个明显的好处:

在STM32的启动方案中,首先使用HSI作为系统时钟,然后在初始化的后期启用HSE并使用PLL来进一步提高系统时钟频率,这种方案有几个明显的好处:

1. 快速启动:
   HSI作为内部RC振荡器,不需要外部元件,上电后立即可用这使得系统可以迅速启动并执行基本的初始化,如设置堆栈、初始化硬件寄存器等,而无需等待外部时钟源稳定。

2. 可靠性与容错性:
   HSI提供了系统启动时的可靠时钟源,即使外部晶振或时钟源出现问题,系统仍然可以使用HSI运行,虽然可能在精度和稳定性上有所折衷,但至少可以确保基本的功能性和安全性

3. 性能提升:
   一旦系统初步初始化完成,可以启用更稳定、精度更高的HSE振荡器,并通过PLL进一步提高时钟频率。这可以显著提高系统的性能,因为PLL可以将时钟频率放大到远高于HSI所能提供的频率,从而允许CPU和外设以更高的速度运行。

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

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

相关文章

Java解析epub电子书文件实战demo

如何使用 Java、Spring Boot 和 Epublib 库解析存储在阿里云对象存储服务(OSS)上的 EPUB 文件。这里将指导您完成设置必要依赖项、配置 OSS 客户端以及编写服务以读取和提取 EPUB 文件章节的全过程。 步骤1:添加依赖项 首先,将 E…

08 字符串和字节串

使用单引号、双引号、三单引号、三双引号作为定界符(delimiter)来表示字符串,并且不同的定界符之间可以相互嵌套。 很多内置函数和标准库对象也都支持对字符串的操作。 x hello world y Python is a great language z Tom said, "Le…

【ESP01开发实例】-ESP-01开发环境搭建与固件烧录

ESP-01开发环境搭建与固件烧录 文章目录 ESP-01开发环境搭建与固件烧录1、ESP-01介绍2、开发环境搭建3、固件下载3.1 使用 Arduino UNO 板对 ESP8266 (ESP-01) 模块进行编程3.2 使用USB 转串口转换器对 ESP8266 (ESP-01) 模块进行编程4、点亮LED本文将详细介绍如何使用 Arduino…

springboot在加了mapper之后报错

springboot在加了mapper之后报错 最后发现是spring boot版本不兼容,spring-boot-starter-parent换成3.0.5之后可以了

Asp .Net Core 系列:详解授权以及实现角色、策略、自定义三种授权和自定义响应

什么是授权(Authorization)? 在 ASP.NET Core 中,授权(Authorization)是控制对应用资源的访问的过程。它决定了哪些用户或用户组可以访问特定的资源或执行特定的操作。授权通常与身份验证(Auth…

【Git-驯化】一文搞懂git中rm命令的使用技巧

【Git-驯化】一文搞懂git中rm命令的使用技巧 本次修炼方法请往下查看 🌈 欢迎莅临我的个人主页 👈这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合,智慧小天地! 🎇 免费获取相关内容文档关注:微信公…

JS+H5在线文心AI聊天(第三方接口)

源码在最后面 调用的不是文心官方接口 可以正常聊天 有打字动画 效果图 源代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-s…

OpenSSL学习笔记及在项目中的使用

OpenSSL官方命令手册&#xff1a;OpenSSL commands - OpenSSL Documentation 参考教程&#xff1a; 操作&#xff1a;OpenSSL的基本使用教程(一&#xff09;_openssl.exe使用教程-CSDN博客 操作&#xff1a;Linux和Shell回炉复习系列文章总目录 - 骏马金龙 - 博客园 (cnblog…

vscode 调试web后端

1、调试环境配置 一、安装python环境管理器 其中要先在vscode选择对应的python环境&#xff0c;最方便的是按照环境管理器后从中选择。其中在【externsions】里面安装python即可。 如下&#xff1a; 二、编写launch.json文件 其中如下&#xff1a; {// Use IntelliSense …

从丢失到找回:2024年U盘数据恢复软件全攻略

优盘作为我们日常短时间存储分享数据来说非常方便&#xff0c;毕竟小巧便携。但是也正因为他小巧数据很容易丢失&#xff0c;如果有备份还好&#xff0c;没有备份就麻烦了。但是只要掌握U盘数据恢复方法就可以缩小我们的损失。 1.福foxit昕数据恢复工具 一键直达>>http…

【算法题】颜色分类,一文彻底搞会!

目录 一、题目描述 二、解题思路 1、什么是荷兰国旗问题&#xff1f; 2、如何解决荷兰国旗问题&#xff1f; 三、参考答案 一、题目描述 颜色分类 给定一个包含红色、白色和蓝色、共n个元素的数组nums &#xff0c;原地对它们进行排序&#xff0c;使得相同颜色的元素相邻&am…

【电源专题】结合锂电池相关资料和华为手机聊聊锂离子电池使用条件限制

在文章:【电源专题】锂电池的特点和工作原理 中我们讲到了一些关于锂电池种类和特点、工作原理等。但是对于锂离子电池使用条件限制却没有介绍,本文基于手机产商 锂离子电池使用条件-电池性能和应用介绍 | 华为官网 (huawei.com)提供的介绍文档再次深入学习锂离子电池的一些特…

浅析JWT原理及牛客出现过的相关面试题

原文链接&#xff1a;https://kixuan.github.io/posts/f568/ 对jwt总是一知半解&#xff0c;而且项目打算写个关于JWT登录的点&#xff0c;所以总结关于JWT的知识及网上面试考察过的点 参考资料&#xff1a; Cookie、Session、Token、JWT_通俗地讲就是验证当前用户的身份,证明-…

【SpringBoot】2 项目搭建

创建项目 1&#xff09;确实本地 jdk 版本 打开命令行窗口&#xff1a;快捷键 Windows R&#xff0c;输入 CMD&#xff0c;敲回车 执行命令&#xff1a;java -version 2&#xff09;在项目 clone 的位置创建 Spring Boot 项目&#xff0c;使用 Maven 进行依赖管理&#xff…

uniapp通过绝对路径解压zpi中的shpe转化为geojson

uniapp通过绝对路径解压zpi中的shpe转化为geojson async fileResult() {const filepath11 /storage/emulated/0/importData/Export_Output_6.zip;// Base64解码函数function base64ToArrayBuffer(base64) {const binaryString atob(base64.split(,)[1]);const len binaryStr…

【计算机网络】DHCP实验

一&#xff1a;实验目的 1&#xff1a;深入理解DHCP&#xff08;动态主机配置协议&#xff09;的工作原理和数据包交换过程。 2&#xff1a;掌握如何通过命令行释放和重新获取IP地址&#xff0c;并通过抓包软件分析DHCP消息的具体内容。 二&#xff1a;实验仪器设备及软件 硬…

人工智能类——计算机科学与技术

计算机科学与技术是一个非常大的门类。目前计算机科学与技术类招生的专业主要有计算机科学与技术、软件工程、网络工程、信息安全、物联网工程等&#xff0c;后面的几个专业是计算机科学与技术的重要分支&#xff0c;而这个门类的其他分支并没有单列出来一个本科专业&#xff0…

前端江湖:从菜鸟到大侠的修炼手册

在这个数字编织的梦幻世界里&#xff0c;前端&#xff0c;这个听起来就带着几分仙气与神秘感的词汇&#xff0c;实则是每一位互联网探险家手中的魔法杖。它不仅连接着代码的冰冷逻辑与用户的炽热情感&#xff0c;更在无数次的点击与滑动间&#xff0c;绘制出一幅幅绚丽多彩的交…

北京率先建设AI原生城市,力争明年推出百个优秀行业大模型产品

7月26日&#xff0c;《北京市推动“人工智能”行动计划&#xff08;2024-2025年&#xff09;》&#xff08;简称《行动计划》&#xff09;正式向社会发布&#xff0c;新京报记者在北京市发展和改革委员会举行的新闻发布会上获悉&#xff0c;北京将率先建设AI原生城市&#xff0…

凸优化笔记-基本概念

原文 文章目录 最小二乘问题 仿射affine hullaffine dimension 凸集锥集超平面和半空间单纯形整半定锥保凸性的操作透视函数 凸函数的条件1阶判定条件2阶判定条件 Epigraph 外图 m i n i m i z e f 0 ( x ) minimize\ \ \ f_0(x) minimize f0​(x) s u b j e c t t o f i ( …