当前位置: 首页 > news >正文

【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库调用,它需要返回堆和栈的边界地址。
http://www.cnnetsun.cn/news/4022904.html

相关文章:

  • 如何在百度中建设网站:从注册域名到SEO优化的全实战指南
  • 网站域名有了 网站如何建设
  • 2026海南直播电商平台卖家报税攻略!平台报税后主播为什么还被查?主播、MCN机构和平台运营涉税问题一次性说清楚
  • 从0到1打造高转化率营销网站的建设流程,揭秘那些90%企业忽略的细节
  • 寻找靠谱娄底网站建设公司揭秘如何打造高转化率的数字化营销网站
  • 揭秘青岛通力建设集团网站背后的真实力量与行业担当
  • Midscene.js视觉自动化测试实战:一句话操控全平台UI
  • 揭秘沛县建设局网站背后的民生温度:一个普通市民眼中的信息透明与城市变迁
  • 深圳网站建设 东毅虎如何以匠心重塑企业数字门面打造极致用户体验与转化
  • 深度解析中国铁路建设投资公司网站熊学军:揭秘高铁背后的硬核力量与行业变革
  • 【TensorRTtSharp v4.0】TensorRT CSharp API v4.0 系列案例总览与学习路线
  • 网页设计与网站建设完全学习手册pdf下载及核心内容深度解析指南
  • 网站建设如何跑单子:从接单到交付的全流程实战指南及核心技巧
  • 清远市建设局网站:揭秘城市发展的数字化引擎与办事指南全解析
  • 深入解析浙江省建设局网站:获取权威资讯、政策解读与办事指南一站式平台推荐
  • 电子商务公司设计网站建设:如何打造高转化率与品牌忠诚度的数字化引擎
  • 深圳夫博网站建设有限公司:如何避开建站陷阱打造高转化官网
  • 揭秘建设企业网站地址背后的商业逻辑与数字化转型真相
  • 专业MT4外汇网站建设指南:从底层架构到用户体验的全方位解析
  • 上海创意网站建设:如何在海量同质化竞争中通过独特设计突围并实现品牌溢价与流量转化
  • 深度揭秘百万网站建设报价背后的真相:为何高端定制网站值得这份投入?
  • HandheldCompanion 入门:给 Windows 掌机补上体感控制、虚拟手柄与性能调校的一站式工具箱
  • 深度揭秘盐亭县建设局网站:一站式了解家乡巨变与政务服务新风采
  • 戴尔电脑重装Windows系统全攻略:从备份到驱动安装
  • 网站正在建设中手机版:一场关于等待、匠心与未来的真诚对话
  • 海城网站制作建设企业级定制化开发解决方案与数字化营销落地指南
  • m4s-converter 免费无损转换工具:B站缓存视频转MP4的完整速通教程
  • 一键彻底卸载Edge:EdgeRemover 脚本使用指南
  • WarcraftHelper魔兽争霸3辅助插件:免费开源,一招解决宽屏适配与帧率解锁难题
  • AI Agent 面试题 424:如何设计Agent的记忆冲突检测和解决机制?