OpenMCU(五):STM32F103时钟树初始化分析

news2025/4/24 4:11:02

概述

        本文主要描述了STM32F103初始化过程系统时钟的初始化,主要描述了系统时钟的初始化,AHB总线时钟,APB总线时钟等的初始化。

硬件板卡3d图

时钟树

STM32F103的时钟树,如下所示:

时钟源选择

从STM32F103的时钟树框图,我们可以看到:

1、有可选的1路高速外部时钟接口,作为系统时钟的时钟源;

2、1路32.768的可选低速时钟,作为系统RTC和watchdog的时钟源;

3、1路内部的可选8M 高速时钟,作为系统时钟的时钟源;

系统时钟选择

根据时钟树所示,可选的系统的时钟选择,如下所示:

1、内部8M的HSI直接作为系统的时钟源,如果使用HSI作为系统时钟源的话,最大SYSCLK只能输出到64MHz;

2、HSI或者HSE的通过PLL的倍频后,作为系统时钟源;

3、HSE的输出,直接作为系统的时钟源;

通过系统时钟源的来源描述,系统的时钟源可以根据硬件板卡的制作情况,进行选择;作者自己设计的PCB板子上,因为没有连接外部晶振,因此将HSI作为系统的时钟源选择。后续的时钟初始化代码分析,会讲解怎么将HSI设置为系统的时钟源;

其他外设时钟

根据STM32F103的时钟树,其他外设控制器的时钟的来源如下所示:

1、USB控制器的时钟,直接来源于PLLCLK,然后经过USB预分频,最终达到48M的时钟输出,作为USB控制器的时钟;

2、I2S音频控制器的时钟,直接来源于SYSCLK, 和SYSCLK的时钟相同;

3、SDIO, FSMC, HCLK 等时钟,直接来自于AHB总线的时钟输出;

4、剩余外设的时钟自于APB1或者APB2,这里不再这里详细描述;

时钟初始化设置

由于作者自己设计的硬件板子,使用了内部的8M作为整个CPU的时钟源,因此,下面以使用内部8M的高速时钟的情况,进行源码讲解,设置源码如下所示:

void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef clkinitstruct = {0};
  RCC_OscInitTypeDef oscinitstruct = {0};

  /* Configure PLL ------------------------------------------------------*/
  /* PLL configuration: PLLCLK = (HSI / 2) * PLLMUL = (8 / 2) * 16 = 64 MHz */
  /* PREDIV1 configuration: PREDIV1CLK = PLLCLK / HSEPredivValue = 64 / 1 = 64 MHz */
  /* Enable HSI and activate PLL with HSi_DIV2 as source */
  oscinitstruct.OscillatorType  = RCC_OSCILLATORTYPE_HSI;     /* HSI作为系统时钟源 */
  oscinitstruct.HSEState        = RCC_HSE_OFF;                /* 关闭HSE时钟 */
  oscinitstruct.LSEState        = RCC_LSE_OFF;                /* 关闭LSE时钟 */
  oscinitstruct.HSIState        = RCC_HSI_ON;                 /* 开启HSI时钟 */
  oscinitstruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  oscinitstruct.HSEPredivValue    = RCC_HSE_PREDIV_DIV1;
  oscinitstruct.PLL.PLLState    = RCC_PLL_ON;
  oscinitstruct.PLL.PLLSource   = RCC_PLLSOURCE_HSI_DIV2;
  oscinitstruct.PLL.PLLMUL      = RCC_PLL_MUL16;
  if (HAL_RCC_OscConfig(&oscinitstruct)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }

  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers 将PLL的输出,作为系统时钟*/
  clkinitstruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  clkinitstruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  clkinitstruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  clkinitstruct.APB2CLKDivider = RCC_HCLK_DIV1;
  clkinitstruct.APB1CLKDivider = RCC_HCLK_DIV2;
  if (HAL_RCC_ClockConfig(&clkinitstruct, FLASH_LATENCY_2)!= HAL_OK)
  {
    /* Initialization Error */
    while(1);
  }
}

        由于作者为了减少PCB板子的尺寸,因此在设计过程中,硬件上没有接外部晶振和32.768的低速晶振。因此只能使用内部HSI作为时钟源,但是在使用HSI作为时钟源时,系统的时钟最大只能设置到64MHz;

代码主要逻辑如下:

1、将HSI的晶振作为系统的晶振输入;

2、关闭HSE时钟源;

3、关闭LSE时钟源;

4、计算出SYSCLK = HSI /2 * PLL_MUl16 = 8/2 * 16 = 64M;

5、调用HAL_RCC_OscConfig()接口,设置系统时钟源;

6、选择PLLCLK的输出,最为系统时钟(64M);

总结

        本文主要描述了,在STM32F103 CPU初始化过程中,系统时钟的初始化。虽然,我们可以利用ST提供的上位机图形化工具进行时钟配置,简单的勾选就可以产生我们需要的代码。但是,作为一个嵌入式开发程序员,我觉得,还是有必要去分析源码,了解CPU的内部原理和HAL层代码,这样才能根据自己产品的实际需求情况,设计出更具有性价比的产品。

链接

yanl1229/STM32F103

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

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

相关文章

ISIS报文

IS-IS 报文 目录 IS-IS 报文 一、报文类型与功能 二、报文结构解析 三、核心功能特性 四、典型应用场景 五、抓包数据分析 六、总结 IS-IS(中间系统到中间系统)协议报文是用于链路状态路由协议中网络设备间交换路由信息的关键载体,其设…

首屏加载时间优化解决

🤖 作者简介:水煮白菜王(juejin/csdn同名) ,一位前端劝退师 👻 👀 文章专栏: 高德AMap专栏 ,记录一下平时学习在博客写作中记录,总结出的一些开发技巧✍。 感…

RabbitMQ--延迟队列事务消息分发

目录 1.延迟队列 1.1应用场景 1.2利用TTL死信队列模拟延迟队列存在的问题 1.3延迟队列插件 1.4常见面试题 2.事务 2.1配置事务管理器 3.消息分发 3.1概念 3.2应用场景 3.2.1限流 3.2.2负载均衡 1.延迟队列 延迟队列(Delayed Queue),即消息被发送以后, 并…

Linux服务器组建与管理

#!/bin/bash #判断是否是root用户if [ "$USER" ! "root" ]; then echo "不是root用户,无法进行安装操作" exit 1 fi#关闭防火墙systemctl stop firewalld && systemctl disable firewalld && echo "防火墙已经关…

设计模式 Day 2:工厂方法模式(Factory Method Pattern)详解

继 Day 1 学习了单例模式之后,今天我们继续深入对象创建型设计模式——工厂方法模式(Factory Method)。工厂方法模式为对象创建提供了更大的灵活性和扩展性,是实际开发中使用频率极高的一种设计模式。 一方面,我们将简…

自动驾驶浪潮下,HMI 设计如何保障安全与便捷?

自动驾驶系统与 HMI 设计的关联性 自动驾驶系统涵盖了一系列复杂的传感器技术、算法以及执行机构。从激光雷达、摄像头等环境感知传感器,到用于处理海量数据的人工智能算法,再到控制车辆行驶的动力与转向执行系统,各部分协同工作&#xff0c…

瑞昱RTD2556QR显示器驱动芯片

一、概述 RTD2556QR芯片是由Realtek公司精心研发的一款高性能显示驱动芯片,专为满足现代显示设备对高分辨率、多功能接口及稳定性能的需求而设计。该芯片凭借其卓越的技术特性和广泛的应用领域,在显示驱动市场中占据重要地位。它集成了多种先进的功能模…

rustdesk 客户端使用

配置中继服务器 RustDesk 搭建-CSDN博客 配置客户端,服务端(控制方,被控方) 1.下载rustdesk.exe(windows为例) 2.完成后如下 3.配置

碳化硅 MOSFET三相逆变电路损耗新算法

基 于 碳 化 硅 MOSFET三相逆变电路损耗新算法 摘 要 提出了一种三相逆变电路功率开关器件损耗计算的新方法.为了达到将高频电力电子电路和实时仿真算 法 相 结 合 应 用 于 嵌 入 式 实 时 仿 真 平 台 的 目 的 ,针 对 工 程 应 用 中 逆 变 器 损 耗 计 算 的 实…

增加等IO状态的唤醒堆栈打印及缺页异常导致iowait分析

一、背景 在之前的博客 在计算进程D状态持续时间及等IO的时间遇到的一处问题-CSDN博客 里,我们修复了一处在抓取D状态及等IO状态堆栈的监控程序的一处时间计算bug,在这篇博客里,我们进一步丰富监控程序,在进程iodelay被唤醒时&am…

新能源汽车空调系统(R134A)性能评估(一)

国内外主流空调系统厂家:贝尔、德尔福、空调国际、法雷奥、电装、松芝、杰信、新电、豫新等 泛亚汽车的空调电子部是比较优秀的整车空调研发团队。 空调系统综合试验台架是一套由试验室、风量测定装置、空气调和器、空气温度测定装置、湿度测定装置、加热器试验辅助…

Ubuntu 22.04安装MongoDB:GLM4模型对话数据收集与微调教程

在Ubuntu 22.04安装MongoDB Community Edition的教程请点击下方链接进行参考: 点击这里获取MongoDB Community Edition安装教程 今天将为大家带来如何微调GLM4模型并连接数据库进行对话的教程。快跟着小编一起试试吧~ 1. 大模型 ChatGLM4 微调步骤 1.1 从 github…

可编程增益放大器(PGA)在智能传感器自调节系统中的角色

在电子电路设计中,放大器芯片作为信号处理的核心器件,其性能直接影响系统整体表现。然而面对运算放大器、功率放大器、仪表放大器等众多类型,工程师常陷入选型困惑。作为国内领先的半导体解决方案提供商,华芯邦深耕放大器芯片领域…

微信登录、商品浏览前瞻

一.业务效果 二.所需技术

浙大研究团队揭示电场调控5-HT1AR的分子机制

本期介绍的文章题为 “Structural Insight into the Inactive/Active States of 5‑HT1AR and Molecular Mechanisms of Electric Fields in Modulating 5‑HT1AR” 。近期发表于JCIM。通过分子动力学模拟,探究 5-羟色胺 1A 受体(5-HT1AR) 在非活性 / 活性状态的构象…

视频AI赋能水利行业生态治理,水电站大坝漂浮物实时监测与智能预警方案

水电站大坝周边水域垃圾漂浮物不仅影响水质,还可能对大坝设施运行、水生态环境造成威胁。传统依靠人工巡检的方式效率低、存在监测盲区,难以实时全面地掌握漂浮物情况。借助EasyCVR视频汇聚平台与TSINGSEE青犀AI算法中台构建智能化监测方案,能…

flink 分组窗口聚合 与 窗口表值函数聚合 的区别

警告:分组窗口聚合已经过时。推荐使用更加强大和有效的窗口表值函数聚合。 参考官方文档 在 Apache Flink 中,分组窗口聚合(Group Window Aggregation) 和 窗口表值函数聚合(Windowing TVF Aggregation)…

阿里云Tair KVCache:打造以缓存为中心的大模型Token超级工厂

一、Tair KVCache 简介 Tair KVCache 是阿里云瑶池旗下云数据库 Tair 面向大语言模型推理场景推出的 KVCache 缓存加速服务。 随着互联网技术的演进与流量规模的激增,缓存技术逐渐成为系统架构的核心组件。该阶段催生了 Redis 等开源缓存数据库,阿里巴巴…

通过TIM+DMA Burst 实现STM32输出变频且不同脉冲数量的PWM波形

Burst介绍: DMA控制器可以生成单次传输或增量突发传输,传输的节拍数为4、8或16。 为了确保数据一致性,构成突发传输的每组传输都是不可分割的:AHB传输被锁定,AHB总线矩阵的仲裁器在突发传输序列期间不会撤销DMA主设备…

[Effective C++]条款26:尽可能延后变量定义的出现时间

. 在C中,尽可能延后变量定义的出现时间,主要原因是为了提供代码的可读性,减少不必要的开销以及避免潜在的错误。 1、代码执行过程中抛出异常 如果在代码开头定义了变量,但在后续代码中抛出了异常,可能导致变量在未被使…