前言

当我们使用STM32时候,会写代码和使用库函数了,也能实现一些简单的现象了,但至于代码为什么这样写,以及为什么这样写对应的设备就能被驱动起来,我们有没有去思考过为什么,也就是它原理是什么,如果你只知道这样写但是不知道为什么这样写,那么这个文章就会很好的帮助你从0到1理解STM32芯片工作的底层逻辑,如果你知道了为什么这样写,那么这篇文章同样的也能帮助你从另外一个角度更加深刻STM32工作原理

我们知道在我们用标准库开发STM32时候,总是会写一大段初始代码,也就是使能一个外设挂载的总线的时钟,然后再定义结构体,赋值结构体变量,最后初始化结构体,不论我们做什么事情,只要用到了外设我们都会以这种形式书写,但是具体为什么要这样书写,这样书写的原理是什么呢,在本文中我将详细讲解该部分的原理,让读者从根本上理解STM32初始代码的底层原理以及逻辑,本文我将分为两个板块来叙述

  • STM32芯片的工作原理与流程
  • STM32时钟编程原理:使能时钟与初始化结构体原理与必要性

一、STM32芯片的工作原理与流程

如下图所示,这个是STM32内部的一个大概形象化图,其芯片工作流程可以细分为下面4个部分:

  1. 上电瞬间的检查与配置
  2. 程序存储与加载
  3. 指令执行
  4. 外设交互
    在这里插入图片描述

上电瞬间的检查与配置
芯片上电瞬间,电源管理单元(PWR)会先检测电压是否稳定(比如确保 3.3V 供电正常),如果电压不够,会触发 “欠压保护”,不让芯片启动(避免损坏),当电源检查没问题且稳定后,时钟控制器(RCR)会默认开启内部低速时钟模式(芯片出产时候就配置好的也就是脉冲是8MHZ(一般来说)),最后触发复位信号,内核CPU就能开始干活了

程序存储与加载
当用户编写的程序代码烧入后将会存放在 Flash 闪存中,然后再等到系统上电或复位后,内核CPU就会从 Flash 指定地址读取复位向量(代码写入的入口),初始化堆栈指针和程序计数器(清空RAM里面的东西)),然后开始执行引导程序或用户程序。
指令执行
执行完程序存储与加载,由于前面的前置工作做好了(知道了代码在哪里,清空了RAM区域),下面就要开始正式执行代码了,
内核CPU通过 I-Bus(指令总线)从 Flash 取指令(获取一条条用户的程序代码),经译码器解析后,由算术逻辑单元(ALU)、寄存器组等执行运算(CPU开始工作了),并通过 D-Bus(数据总线)与 RAM 交换数据(在程序执行的过程中产生的中间变量,以及代码运行到哪一块了防止CPU运行代码到一半去执行函数调用和中断处理后回来不知道代码执行到哪里了)。

Flash 闪存区是一种非易失性存储介质,在嵌入式系统中常用于存储程序代码、固件以及需要永久保存的数据。它的特点是断电后数据不会丢失,且可以进行多次擦写操作。与 RAM(随机存取存储器)相比,Flash 的读写速度相对较慢,但具有更高的稳定性和持久性,因此适合存放系统启动程序、应用程序等核心内容。

RAM(随机存取存储器)是 STM32 中的 “临时工作台”,主要用来存放正在处理的数据和运行中的程序片段,它主要用以下几个作用

  • 临时存放计算过程中的数据:比如程序里定义的变量(如温度值temp=25)、函数调用时的参数(如sum(1,2)中的1和2)、运算的中间结果(如算3+5时的8),都会暂时存在 RAM 里。因为 CPU 读取 / 修改 RAM 里的数据速度非常快,适合频繁读写的场景。
  • 运行需要高速执行的程序代码:然程序默认存在 Flash 里(长期存储),但如果某段代码需要极致速度(比如实时控制电机的算法),可以把它 “加载” 到 RAM 中执行 —— 因为 RAM 的读写速度比 Flash 快很多
  • 提供堆栈空间(程序运行的 “临时记忆”):
    1.栈(Stack):存放函数调用时的返回地址、局部变量(比如函数里定义的int a=0),确保程序执行完一个函数后能回到正确位置(CPU执行代码执行到一半去执行中断或函数代码去了,回来后知道代码运行到哪了,然后继续运行剩下代码)。
    2/堆(Heap):用于动态内存分配(比如malloc函数申请的空间),需要手动申请和释放

外设交互:
当你代码里面用到了STM32芯片上的外设时候,内核CPU将会通过总线矩阵(Bus Matrix)连接 AHB或者APB1和APB2 总线(具体哪个总线看你用到的外设在哪个总线上),控制该总线上挂载的外设(如 GPIO、定时器(TIM)、串口(USART)、ADC 等外设)。如果外设中运用到了中断,那么外设就会通过中断(NVIC)机制向内核请求处理事件,让CPU先别工作了,让对应的外设硬件去干活实现异步操作。当干完回来继续执行CPU获取的剩下代码(如果你代码用到了通信协议那么芯片就会通过 SPI、I2C、USB 等外设接口,实现与外部设备的数据传,具体执行顺序看你代码顺序)

以上就是STM32从上电——烧入——执行代码——出现对应现象的基本工作流程
了解完上面的东西后我们再来了解一下,时钟编程是在干嘛,彻底弄懂初始化外设的一大堆步骤流程的底层逻辑原理

二、STM32时钟编程原理:使能时钟与初始化结构体原理与必要性

我们先来看下面这一串代码
在这里插入图片描述
可以清楚的知道,这个代码是在使能GPIOA的PA0引脚,它做了两件事,第一件就是使能GPIOA时钟,第二件就是通过结构体来初始化GPIOA
下面我们再来看这一段代码
在这里插入图片描述
可以清楚知道,这个是在配置一个定时器然后开启定时器的一个中断,红色框部分可以跟上面我们第一段代码是不是很类似呢?它也是干了两件事,第一件事情是先使能定时器3时钟,第二件事情通过结构体初始化了定时器3。

综上的两段代码,都在驱动外设时候干了两件事,第一件先使能外设的时钟,第二件通过结构体初始化外设(这里的外设就是你要用的模块如上面的GPIOA和定时器3)
那么我们现在思考一下为什么要进行这样的一个编程配置,为什么不这样就不能驱动这个外设了呢?而答案就是接下来我要说的这个时钟编程
在具体讲时钟编程之前,首先我们先了解下面一些概念

晶振:晶振是一种会产生固定频率的周期性电信号(比如 8MHz、16MHz)的元件。,它决定了CPU执行代码的一个速度,它同时是STM32芯片里面的一个时间基准,它通过稳定的频率信号让 CPU 和外设 “按统一节奏工作”,是保证 STM32 功能准确、稳定运行的核心元件。没有晶振,STM32芯片就无法精确控制时间和数据传输

还记得我们一开始说的STM32芯片工作的流程原理吗,也就是画红线这一块在这里插入图片描述
要让CPU干活工作就要有一个脉冲信号,可以说CPU动力的来源就是这个脉冲信号,脉冲越大,CPU工作的就越快,我们知道我们驱动的所有外设是由我们软件驱动CPU再由CPU通过配置寄存器等一系列操作最后去驱动这个外设的,可以理解为驱动外设时候也需要一个动力源,当外设收到CPU给的脉冲动力时候,它就能干活了,而这个动力源就是CPU给的脉冲,而CPU脉冲的来源就是STM32芯片内部或者外部的时钟源(内部时钟源包括:HSI,LSI;外部时钟源包括:HSE,LSE)

在这里插入图片描述

可以理解为我们在驱动一个外设时候做的第一件事也就是先使能这个外设的时钟的目的就是在让CPU给这个外设脉冲也就是给它一个动力,这就是为什么我们再驱动外设时候基本上都要写上一个类似于这样的代码

在这里插入图片描述

再搞清楚这个后,下面我们再来搞清楚第二件事情为什么要用利用结构体初始化外设
我们以上面代码的定时器3模块为例子,来说一下为什么要利用结构体初始化

我们先看下面这个定时器3的形象图

在这里插入图片描述

RCR重复计数器一般只有高级定时器有,但是为了更加完整解释定时器框图,我们假设定时器3也有这个东西

我们看它内部电路的一个基本框图,它的基本电路可以理解为是一个开关,一个时基单元(预分频器+CNT计数器+自动重装载寄存器)组成的,也就是我们要让它工作起来我们只需要打开开关,然后配置好PSC分频器,,CNT计数器,自重重装载寄存器和RCR重复计数器就好了,那么理解完这个后我们回到一开始定时器那块例子的代码(看蓝色部分)
在这里插入图片描述
我们把它们单独拿出来,可以清楚的知道这四个函数分别对应了对PSC分频器,自重重装载寄存器,CNT计数器,和RCR重复计数器的配置,我们利用结构体对它进行初始化赋值配置的步骤就对应了对定时器外设这个电路一些模块的配置操作(至于为什么要用结构体,而不是直接采取单纯的变量然后赋值操作是因为,结构体更加方便管理,一个结构体里面可以有很多个变量,而且它们类型不一样,而且定义完结构体后,查找结构体里面变量成员就很方便了)
在这里插入图片描述

然后在这里插入图片描述
这个函数的调用就对应了刚刚定时器形象图里面的打开开关步骤了,这就详细完整的解释了,我们为什么驱动一个外设时候要那么大费周章写那么多代码了。

最后让我们再来理一下思路逻辑,进行总结,还是以这个定时器3驱动为例子

在这里插入图片描述

首先我们开启定时器3时钟,目的就是为了提供定时器形象图里面最左边的那个脉冲信号,然后我们进行了定时器的时机单元的参数配置(也就是结构体参数赋值配置初始化)对应定时器形象图里面的对PSC分频器,自重重装载寄存器,CNT计数器,和RCR重复计数器的配置,然后配置完后我们调用了在这里插入图片描述
就是把我们赋值的参数写入定时器里面,然后我们再打开定时器的开关也就是对应的代码里面的闭合时基单元的开关

通过这个例子,我们同样的可以知道,当我们驱动其他外设时候,对它进行的一些类似于定时器这样驱动的代码时候实际上也就是分别对应它这个外设原理图里面的给一个脉冲,然后配置这个外设原理图的一些电路什么的

总结

综上所述,本文围绕 STM32 芯片的工作原理与时钟管理展开了详细解析。从芯片上电后的电压检测、时钟启动到 CPU 执行程序的完整流程,清晰呈现了内核与 Flash、RAM 及外设的交互机制,揭示了中断处理的底层逻辑。同时,深入探讨了时钟系统的核心作用,包括内外部时钟源(HSI、HSE 等)的特性以及晶振对系统稳定性的关键影响,并结合 GPIO 与定时器驱动实例,阐明了外设初始化中时钟使能与结构体配置的必要性。通过本文的梳理,读者可从底层逻辑层面理解 STM32 代码设计的缘由,为进一步的开发应用奠定坚实基础。
(觉得本文有用的,不妨点个赞让更多开发者看到这份底层原理的梳理~您的认可就是持续分享技术干货的动力!)

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐