news 2026/8/14 13:19:21

【STM32】02.外设+时钟树+启动文件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【STM32】02.外设+时钟树+启动文件

一、什么是外设?

可以把STM32芯片想象成一台微型的电脑:

内核: 就像是电脑的CPU,负责执行代码和进行运算。

外设: 就像电脑的屏幕、键盘、风扇等,负责各种功能模块。

学习STM32开发,本质上就是学习如何配置和使用这些丰富的外设来实现你想要的功能。

二、STM32常见的外设分类与举例

STM32的外设非常丰富,可以大致分为以下几类:

外设类别

子类型

功能描述

通信接口

UART

异步串口通信,基础通信方式,用于连接GPS模块、蓝牙模块、电脑串口调试等场景。

I2C

双向两线制串行总线,适用于连接多个低速设备,如温湿度传感器、加速度计、EEPROM存储器等。

SPI

高速全双工串行总线,支持高速数据传输,常用于连接Flash存储器、SD卡、显示屏、无线模块等。

USB

通用串行总线,支持USB设备(被电脑识别)、USB主机(连接U盘)或USB OTG(角色切换)模式。

CAN

控制器局域网总线,具备强抗干扰能力和可靠性,主要应用于汽车和工业领域。

以太网

提供有线网络连接功能,满足需要网络通信的嵌入式设备需求。

定时器

基本定时器

用于产生精确延时和定时中断。

通用定时器

功能丰富,支持基本定时、PWM输出(控制舵机、直流电机速度、LED亮度调节)、输入捕获(测量脉冲宽度、频率,如编码器信号)、输出比较(产生特定频率和占空比的波形)。

高级定时器

功能最强大,适用于电机控制、数字电源等复杂领域,可生成带死区控制的互补PWM信号。

模拟外设

ADC

模数转换器,将外部模拟电压信号(如传感器输出)转换为数字值,供内核处理,例如读取电位器位置、光照强度、温度传感器电压。

DAC

数模转换器,将数字值转换为模拟电压输出,可用于生成特定波形(如正弦波、三角波)。

比较器

快速比较两个模拟电压大小,输出数字信号(高/低),常用于过流保护、阈值检测等场景。

数据管理

DMA

直接存储器访问,可在不占用CPU的情况下在外设和内存之间直接搬运数据,例如ADC转换完成后自动将数据传输至RAM数组,提升系统效率。

输入/输出

GPIO

通用输入输出端口,可配置为输入模式(读取按键状态)、输出模式(控制LED亮灭)或复用为其他外设功能(如UART的TX引脚)。

安全与保护

看门狗

独立定时器,用于监测程序运行状态。程序正常时需定期“喂狗”,若程序崩溃无法喂狗,看门狗会自动复位芯片,使系统恢复。

三、时钟树和系统结构

时钟树可以理解为一个“时钟信号的配送网络”。它有几个关键的“水源”(时钟源),通过一系列的“开关和阀门”(多路选择器、分频器、倍频器)将不同频率和特性的时钟信号“配送”到各个“用水单位”(内核、外设等),使这些“用水单位”(内核、外设等)能正常工作。控制这些“开关和阀门”的模块称之为时钟控制RCC。

在《STM32F10xxx参考手册中文版.pdf》第 56 页有对时钟树的详细介绍:

在我们使用 STM32CubeMX 新建工程时,其实已经对这个时钟树进行配置了。

下面为STM32CubeMX配置时钟树后生成的代码入口函数(了解就行)

四、STM32F10xxx系统结构框图

了解完时钟树后,我们就可以大概了解芯片的系统结构了。在《STM32F10xxx数据手册》第11页有对STM32F10xxx系统结构框图有描述。

五、启动文件作用

启动文件是用汇编语言编写的,是芯片上电后执行的第一段代码,奠定了整个程序运行的基石。
注意:不同型号的STM32芯片,启动文件不全一样。

六、启动文件的核心作用

这个文件主要完成以下关键任务:
  1. 初始化堆栈指针
  2. 构建中断向量表
  3. 执行系统初始化
  4. 跳转到主程序
  5. 提供中断服务程序的默认入口

七、详细代码分析

1. 堆栈配置

Stack_Size EQU 0x400 ; 定义栈大小为 1KB AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size ; 栈顶地址,初始化MSP的值 __initial_sp
  • EQU: 类似于C语言的 #define,定义常量。
  • AREA: 声明一个段。STACK是段名,NOINIT表示不初始化为0,READWRITE可读可写,ALIGN=3表示按8字节对齐。
  • SPACE: 分配一段指定大小的内存空间。
  • __initial_sp: 链接器会使用这个符号的值作为主堆栈指针的初始值。
同理,堆区配置:
Heap_Size EQU 0x200 ; 定义堆大小为 512字节 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit
  • 堆用于动态内存分配(如malloc、free)。

2. 中断向量表

这是启动文件最核心的部分。
AREA RESET, DATA, READONLY EXPORT __Vectors __Vectors DCD __initial_sp ; 地址0: 初始栈顶地址 DCD Reset_Handler ; 地址4: 复位中断服务程序 DCD NMI_Handler ; 地址8: NMI Handler DCD HardFault_Handler ; 地址12: Hard Fault Handler ... ; 更多系统异常 DCD WWDG_IRQHandler ; 外部中断0 (Window Watchdog) DCD PVD_IRQHandler ; 外部中断1 (PVD) ... ; 所有外部中断
  • AREA RESET, DATA, READONLY: 定义一个名为RESET的只读数据段,存放向量表。
  • EXPORT __Vectors: 导出__Vectors符号,让链接器知道向量表的起始位置。
  • DCD: 分配一个32位的字(4字节)内存,并初始化。
  • 向量表结构:
    • 第一个条目必须是初始栈顶指针。Cortex-M内核上电后,首先从地址0x00000000取出这个值赋给MSP。
    • 第二个条目是复位向量,即Reset_Handler的地址。上电后,内核从地址0x00000004取出这个值,并跳转到该地址执行。
    • 后续条目依次是各种异常和中断的入口地址。

3. 复位中断服务程序

这是上电后执行的第一段代码
Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
  • PROC/ENDP: 定义一个过程(函数)。
  • [WEAK]: 弱定义。如果别处没有定义同名的强符号,则使用此定义。这里允许用户在C代码中自己实现一个Reset_Handler。
  • IMPORT: 声明外部符号,类似于C语言的extern。
  • 执行流程:
  1. LDR R0, =SystemInit: 将SystemInit函数的地址加载到寄存器R0。
  2. BLX R0:跳转并执行SystemInit()。这个函数通常由ST提供,在system_stm32f1xx.c中,它负责配置时钟、初始化等关键系统配置。不过用STM32CubeMX生成工程时,时钟配置已经在SystemClock_Config()函数中实现,SystemInit()函数不做配置了。
  3. LDR R0, =__main: 将__main的地址加载到R0。注意:这个__main不是你的C代码里的main函数,它是C库中的一个函数,由编译器提供。
  4. BX R0: 跳转到__main。
    • __main会完成以下工作:
      • 复制初始化数据从Flash到SRAM(例如,初始化全局变量)。
      • 将未初始化的内存区域清零(例如,.bss段)。
      • 调用C库初始化(如果使用)。
      • 最后,调用用户的main()函数。

4. 默认中断服务程序

NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ; 无限循环 ENDP HardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] B . ENDP ...
  • 对于所有异常和中断,这里都提供了一个默认实现:一个什么都不做的无限循环(B .)。
  • 它们都被标记为[WEAK]。这意味着,如果你在C代码中自己实现了一个同名的函数(例如 void TIM2_IRQHandler(void) { ... }),链接器会优先使用你的函数,从而覆盖这个默认的空实现。这就是我们自定义中断服务函数的方式(函数名不能改,但是函数里面执行的代码我们可自定义)。

5. 堆栈初始化(用于非微库)

IF :DEF:__MICROLIB ... ; 如果使用微库,直接使用上面定义的符号 ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap LDR R0, = Heap_Mem ; 返回堆起始地址 LDR R1, =(Stack_Mem + Stack_Size) ; 返回栈结束地址 LDR R2, = (Heap_Mem + Heap_Size) ; 返回堆结束地址 LDR R3, = Stack_Mem ; 返回栈起始地址 BX LR ENDIF
  • 这部分是为了支持标准的C库(而非微库Microlib)进行堆栈初始化。
  • __user_initial_stackheap 函数会被C库调用,它需要返回堆和栈的边界地址。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/14 13:19:09

如何在百度中建设网站:从注册域名到SEO优化的全实战指南

本文关键词:是在百度中建设网站说实话,提起在百度中建设网站,很多初入互联网圈子的朋友可能脑子里会闪过好几个念头:是得花一大笔钱找广告商吗?是不是得懂很深奥的代码?还是说只要我网站做得好看,百度就会自动把我捧上天?如果你也有这些困惑,那这篇分享就是专门为你写…

作者头像 李华
网站建设 2026/8/14 13:18:58

网站域名有了 网站如何建设

拿到一个心仪的域名,那种感觉就像是你终于买下了那块地皮,站在空旷的荒地上,看着蓝天白云,心里既兴奋又茫然。兴奋的是,这片天地终于属于你了,以后你想建什么都可以;茫然的是,手里攥着这张“地契”,脑子里却全是问号:接下来该怎么办?是不是找个人给我盖个房子?这房…

作者头像 李华
网站建设 2026/8/14 13:18:54

2026海南直播电商平台卖家报税攻略!平台报税后主播为什么还被查?主播、MCN机构和平台运营涉税问题一次性说清楚

随着海南自贸港封关筹备工作持续推进,叠加金税四期全域数字化监管落地,一套全新的税务监管体系正在重塑海南直播电商、跨境电商行业的财税规则。不同于以往 “以票控税” 的传统征管模式,当前海南税务系统已经打通电商平台订单数据、资金流水…

作者头像 李华
网站建设 2026/8/14 13:18:42

从0到1打造高转化率营销网站的建设流程,揭秘那些90%企业忽略的细节

现在的商业环境,就像一场没有硝烟的战争。如果你还觉得只要有个网站摆在那儿,客户就会自动找上门,那只能说是太天真了。我见过太多老板,花了几万块甚至十几万找人做网站,结果上线后不仅没有流量,连个咨询电话都没有。最后只能感叹:“这钱扔水里还能听个响,做网站纯属打…

作者头像 李华
网站建设 2026/8/14 13:18:35

寻找靠谱娄底网站建设公司揭秘如何打造高转化率的数字化营销网站

在这个移动互联网铺天盖地的时代,很多老板都有一个误区,觉得建网站就是找个技术员敲敲代码,或者套个模板随便填填内容就能了事。但如果你真的这么想,那你可能正在悄悄地把你的客户推给竞争对手。今天,我想和大家掏心窝子聊聊,为什么选择一家真正懂业务、懂技术的娄底网站…

作者头像 李华
网站建设 2026/8/14 13:16:35

揭秘青岛通力建设集团网站背后的真实力量与行业担当

在这个互联网信息爆炸的时代,我们每天似乎都在与屏幕打交道。尤其是对于从事建筑、工程、房地产以及相关产业链的朋友们来说,寻找一家靠谱的合作伙伴,往往不仅仅是看几张精美的效果图,或者听几句天花乱坠的承诺。真正决定一家企业能否走得远、走得稳的,往往是那些藏在细节…

作者头像 李华