STM32-寄存器时钟配置指南

news2024/9/19 10:03:54

目录

启动

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://www.coloradmin.cn/o/1952410.html

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

相关文章

【中项第三版】系统集成项目管理工程师 | 第 11 章 规划过程组⑤ | 11.13 - 11.14

前言 第11章对应的内容选择题和案例分析都会进行考查,这一章节属于10大管理的内容,学习要以教材为准。本章上午题分值预计在15分。 目录 11.13 制定预算 11.13.1 主要输入 11.13.2 主要输出 11.14 规划质量管理 11.14.1 主要输入 11.14.2 主要工…

MySQL查询优化 limit 100000,10加载很慢该怎么优化

需求:查询19年以后发布的商品 数据库表结构如下: 目前数据量:264751 优化前执行时间:0.790s 优化后执行时间:0.467s select id,no,title,cart_title,cid_name from tb_item where id > (select id from tb_item …

Redis 缓存

安装 安装 Redis 下载: Releases tporadowski/redis (github.com) winr ----services.msc-----将redis 设置为手动(只是学习,如果经常用可以设置为自动) 安装 redis-py 库 pip install redis-py Redis 和 StrictRedis redis-py 提供 Redis 和 Str…

记忆注意力用于多模态情感计算!

记忆注意力用于多模态情感计算! 目录 情感计算 一、概述 二、研究背景 三、模型结构和代码 六、数据集介绍 七、性能展示 八、复现过程 九、运行过程 模型总结 本文所涉及所有资源均在传知代码平台可获取。 情感计算 近年来,社交媒体的快速扩张推动了用户…

跨境电商独立站:Shopify/Wordpress/店匠选哪个?

在面对不断增加的平台运营压力时,不少跨境电商的商家逐渐将注意力转向建立自己的独立站。据《中国跨境出口电商发展报告(2022)》所示,中国拥有的独立站数量在2022年已接近20万个,这表明独立站已成为卖家拓展海外市场的…

构建现代数据湖

现代数据湖是一半数据仓库和一半数据湖,对所有事情都使用对象存储。使用对象存储来构建数据仓库是通过 Open Table Formats OTF) 实现的,例如 Apache Iceberg、Apache Hudi 和 Delta Lake,这些规范一旦实现,就可以无缝…

800以内的蓝牙耳机推荐有哪些?四款优选精品百元蓝牙耳机推荐

面对市场上琳琅满目的品牌和型号,如何选择一款性价比高、功能全面的蓝牙耳机成为了一个让人头疼的问题,尤其是在众多的百元价位段的蓝牙耳机,800以内的蓝牙耳机推荐有哪些?作为一个选蓝牙耳机的过来人,我总结了四款优选…

一个极简的 vuedraggable 示例

https://andi.cn/page/621613.html

代码随想录算法训练营第 25 天 | LeetCode491.递增子序列 LeetCode46.全排列 LeetCode47.全排列ii

代码随想录算法训练营 Day25代码随想录算法训练营第 25 天 | LeetCode491.递增子序列 LeetCode46.全排列 LeetCode47.全排列ii 目录 代码随想录算法训练营前言LeetCode491.递增子序列LeetCode46.全排列LeetCode47.全排列ii 一、LeetCode491.递增子序列1.题目链接2.思路3.题解 …

React Native在移动端落地实践

在移动互联网产品迅猛发展的今天,技术的不断创新使得企业越来越注重降低成本、提升效率。为了在有限的开发资源下迅速推出高质量、用户体验好的产品,以实现公司发展,业界催生了许多移动端跨平台解决方案。这些方案不仅简化了开发流程&#xf…

轻松学EntityFramework Core--模型创建

一、使用代码优先(Code-First)创建模型 Code-First 方法是 EF Core 提供的一种用于定义模型的方式,它允许开发人员通过编写 C# 类来定义数据库模式,再通过迁移命令生成数据库表。下面我们来一起看一下代码优先如何使用。 1.1、创…

Collention集合基础知识

Array 数组是一种连续的内存空间存储相同数据类型数据的线性数据结构 数组获取其他元素的地址值 寻址公式 a[i] baseaddress i*datatypesize 为什么数组索引从0开始 从1开始不行吗 从0开始寻址公式 a[i] baseaddress i*datatypesize 从1开始寻址公式 a[i] baseadd…

利用GPT4o Captcha工具和AI技术全面识别验证码

利用GPT4o Captcha工具和AI技术全面识别验证码 🧠🚀 摘要 GPT4o Captcha工具是一款命令行工具,通过Python和Selenium测试各种类型的验证码,包括拼图、文本、复杂文本和reCAPTCHA,并使用OpenAI GPT-4帮助解决验证码问…

yolov5-7在opencv里跑自己的onnx模型

先把模型放在如下目录 运行如下代码 import cv2 import numpy as npclass Onnx_clf:def __init__(self, onnx:strdnn_model1/plane02.onnx, img_size640, classlist:list[plane]) -> None: func: 读取onnx模型,并进行目标识别para onnx:模型路径img_size:输出图片大小,和模…

Codeforces Round 962 (Div. 3) D. Fun (数学,暴力枚举)

非常好题目,使我思考良多。 经典的数学问题,题目给出了两道数学式子,当然就是要让我们推啊。 首先纠正一个错误,当我发现了这两个式子能凑出来平方式的时候我就想着去用两个式子来互相简化,但其实这样存在以下一个错误…

数据增强和数据平衡

数据增强(Data Augmentation) 数据增强是一种通过对数据进行变换来增加数据多样性的方法。它可以提高模型的泛化能力,特别是在图像和文本处理任务中。 原理 通过数据增强技术,生成更多样本,提高模型的泛化能力。例如…

Github个人网站搭建详细教程【Github+Jekyll模板】

文章目录 前言一、介绍1 Github Pages是什么2 静态网站生成工具3 Jekyll简介Jekyll 和 GitHub 的关系 4 Mac系统Jekyll的安装及使用安装Jekyll的简单使用 二、快速搭建第一个Github Pages网站三、静态网站模板——Chirpy1 个人定制 四、WordPress迁移到Github参考资料 前言 23…

chrome浏览器驱动(所有版本)

chrome浏览器驱动 114之前版本 https://chromedriver.storage.googleapis.com/index.html 125以后 125以后版本下载链接在此,只有后面status是绿色对勾的才可以下载,驱动大版本一致就可以使用,不需版本号一模一样;下载所需版本只…

STM32智能工业监控系统教程

目录 引言环境准备智能工业监控系统基础代码实现:实现智能工业监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:工业监控与优化问题解决方案与优化收尾与总结 1. 引言 智能工业监控系统通…

Java集合框架2024最通俗易懂(图片超全)

集合 1.1、定义 集合就是类型统一的数据组合而成的数据结构,该数据结构可以任意的改变长度。 1.3、Set Set数据存储结构,无序,且不可以重复,元素可以为null,但是也只能出现一次,如下图: 1.3.1、HashSe…