MCU上电到运行的全过程

发布于:2025-09-09 ⋅ 阅读:(27) ⋅ 点赞:(0)

MCU上电到运行的全过程你知道吗??

在聊启动过程前,我们得先明白MCU“断电时”的状态。就像手机没电关机后,CPU、内存、传感器都处于“离线”状态一样,MCU断电时:

核心CPU(中央处理器)停止工作,寄存器里的数据全部丢失;

RAM(随机存储器)就像没有电的黑板,上面的内容(临时数据)全部清空;

Flash(闪存)虽然保存着我们写的程序,但它是“被动存储”,不会主动“叫醒”MCU;

外设(比如串口、ADC、定时器)也处于默认的“关闭”或“初始混乱”状态,无法响应任何指令。

简单说,断电的MCU就是一个“装满了资料(Flash里的程序)但没人指挥、所有设备都停工”的工厂。而“启动过程”,就是给工厂通上电后,从“叫醒管理员(CPU)”到“打开机器(外设)”、“调出生产计划(加载程序)”,最后让工厂正常运转的全过程。

当你给电路板插上电源,或者按下复位键的瞬间,启动过程就开始了,这一步叫做“上电复位”。

1. 复位电路

MCU内部都有一个“复位电路”,它的作用就像闹钟,当电源电压达到MCU能工作的最低值(比如3.3V MCU的阈值可能是2.8V)时,复位电路会给CPU发一个“复位信号”(通常是低电平或高电平脉冲)。

为什么需要复位电路?因为电源上电时电压不是瞬间稳定的,可能会有波动(比如从0V慢慢升到3.3V)。如果电压没稳定就叫醒CPU,CPU可能会“脑子混乱”,执行错误的指令。复位电路会等电压稳定后,再发送复位信号。

有些MCU还支持“手动复位”(比如复位按键),原理和上电复位一样:按下按键时,复位电路会再次发送复位信号,让MCU重新“起床”,相当于“重启”。
在这里插入图片描述

2. 复位后的“第一秒”

当CPU收到复位信号后,会先做一件事:把自己的“工作环境”恢复到“出厂默认状态”。比如:

清空所有寄存器(比如程序计数器PC、堆栈指针SP),让CPU忘记之前的“记忆”;

把程序计数器PC(相当于“当前要执行的指令地址”)设置为一个“默认值”。这个值就是启动过程的“起点地址”,不同厂家的MCU起点地址不同,比如STM32的起点地址是0x00000000,51单片机是0x0000;

关闭所有外设的中断(避免刚起床就被外设“打扰”),只保留复位相关的核心功能。

3.启动模式选择

CPU复位后,知道了“要开始执行指令”,但它还不知道“指令存在哪里”,是存在内部Flash里?还是外部SD卡?或者通过串口下载的临时程序?这就需要“启动模式选择”来决定。

  1. 启动模式

MCU的“启动模式”,本质是选择“程序的存放位置”(专业叫“程序存储器”)。常见的启动模式有3种:

Flash启动模式:从MCU内部的Flash读取程序(最常用的模式,我们写的程序通常烧录在这里);

RAM启动模式:从RAM读取程序(一般用于调试,比如把程序临时加载到RAM里运行,断电后程序会消失);

外设启动模式:从外部设备读取程序(比如从串口、USB、SD卡加载程序,用于批量生产或远程升级)。

为什么需要选择启动模式?比如你开发产品时,需要先在RAM里调试程序(改完代码不用烧录,直接加载到RAM运行,节省时间);产品量产时,就切换到Flash模式(程序存在Flash里,断电不丢失);如果需要给设备远程升级,就用外设启动模式(从网络接收新程序,再写入Flash)。

  1. 如何选择启动模式?

启动模式不是软件设置的,而是通过“硬件引脚”的电平状态决定的。比如STM32的启动模式由BOOT0和BOOT1两个引脚的高低电平决定:

当BOOT0=0、BOOT1=0时,从内部Flash启动;

当BOOT0=1、BOOT1=0时,从系统存储器启动(用于串口下载程序);

当BOOT0=1、BOOT1=1时,从RAM启动。
在这里插入图片描述

这些引脚在MCU上电时会被内部电路检测,CPU根据检测到的电平,确定“从哪个地址开始读取程序”。

4.加载向量表

确定了启动模式后,CPU会去对应的存储器(比如Flash)的“起点地址”(比如0x00000000)读取第一个关键数据,向量表。

  1. 向量表是什么?

向量表其实是一个“地址列表”,里面记录了MCU所有“关键功能”的入口地址,最核心的两个地址是:

栈顶指针(SP)的初始值:RAM里专门划分了一块“栈区”,用于存放临时数据(比如函数参数、局部变量)。向量表的第一个数据就是栈区的“最高地址”(栈顶),CPU会先把这个地址写入堆栈指针SP,相当于“划定临时数据的存放区域”;

复位中断服务程序地址:向量表的第二个数据,是“复位中断服务程序”的入口地址。CPU读取这个地址后,会跳转到这个程序执行。

除了这两个,向量表里还有其他中断服务程序的地址(比如串口中断、定时器中断、ADC中断),但启动阶段只用到“复位中断服务程序”。你可以把向量表理解为:CPU刚起床时,手里拿到的一张“地图”,上面标着“临时物品存放区(栈区)在哪里”,以及“接下来该去哪个办公室(复位中断服务程序)报到”。

  1. 为什么向量表要放在起点地址?

因为CPU复位后,程序计数器PC的默认值就是起点地址(比如0x00000000),它会先读取这个地址的数据。如果向量表不在起点地址,CPU就找不到“栈顶地址”和“复位中断程序地址”,启动过程就会卡住。

有些MCU支持“向量表重映射”(比如STM32),就是可以把向量表从起点地址移到其他地方(比如RAM或Flash的其他区域),但这是启动后的操作,启动阶段向量表必须在起点地址。

5.执行复位中断服务程序

CPU跳转到“复位中断服务程序”后,终于开始执行具体的代码了。这个程序是我们写的吗?不全是。大部分是MCU厂家提供的“启动文件”里的代码,我们也可以根据需求修改。它的核心任务是“初始化硬件”,为后续运行用户程序做准备。

  1. 初始化RAM

RAM是“临时仓库”,断电后数据会丢失,上电后里面是“乱码”(随机数据)。复位中断服务程序会先做一件事:初始化RAM,包括:

把“已初始化的全局变量”从Flash复制到RAM:我们写程序时,定义的全局变量如果赋了初始值(比如int a=10),这些变量会和程序一起存放在Flash里。启动时需要把它们复制到RAM里(因为CPU访问RAM比访问Flash快,而且全局变量需要可修改);

把“未初始化的全局变量”清零:如果全局变量没赋初始值(比如int b),程序会把它们所在的RAM区域清零,避免后续使用时出现随机值。

这一步就像你上班前,先把“临时仓库”里的杂物清理掉,把需要用的物品(已初始化的全局变量)从“长期仓库(Flash)”搬到“临时仓库(RAM)”。

  1. 初始化堆栈

之前CPU已经从向量表拿到了栈顶地址,但还需要初始化“堆区”(如果用了动态内存分配,比如malloc函数)。栈区用于存放函数参数、局部变量,堆区用于存放动态申请的内存(比如程序运行中临时创建的数据)。

复位中断服务程序会设置堆区的起始地址和大小,确保后续程序调用函数、申请动态内存时,有地方存放数据。如果堆栈初始化错误(比如栈区太小),程序运行时会出现“堆栈溢出”,导致MCU死机。

  1. 初始化时钟

MCU的CPU、外设(串口、定时器等)都需要“时钟信号”才能工作,就像机械表需要上发条才有动力。复位后,MCU的时钟默认是“内部低速时钟”(比如STM32的HSI时钟,频率8MHz),这个时钟频率低,适合启动阶段的简单操作,但不适合高性能任务(比如高速串口通信、ADC采样)。

复位中断服务程序会“切换时钟”:启用外部高速时钟(比如STM32的HSE时钟,频率25MHz),然后通过“时钟树”(MCU内部的时钟分配电路),把CPU、外设的时钟频率提升到额定值(比如STM32F103的CPU时钟最高72MHz)。

  1. 初始化关键外设

根据需求,复位中断服务程序还会初始化一些“启动阶段必须用到的外设”,比如:

如果程序需要串口打印启动信息,会初始化串口的波特率、数据位、停止位;

如果需要检测外部传感器,会初始化ADC或I2C接口;

如果需要防止程序跑飞,会初始化看门狗(WatchDog)。如果程序卡住,看门狗会触发复位,让MCU重新启动。

这些外设的初始化不是必须的,取决于你的应用场景。比如一个简单的LED闪烁程序,可能只需要初始化GPIO(通用输入输出口),不需要初始化串口。

  1. 跳转到用户主程序

当所有初始化工作完成后,复位中断服务程序会执行最后一条指令:跳转到用户主程序的main函数。这一步标志着“启动过程结束”,MCU正式进入“工作状态”,开始执行你写的代码(比如控制LED闪烁、读取传感器数据、和手机通信等)。

从这里开始,CPU就完全按照你的指令运行了。启动过程就像“开机自检+环境准备”,main函数就是“正式工作”的开始。

6.启动后的“收尾工作”

启动过程虽然结束了,但MCU还需要处理一些“后续问题”,确保运行稳定。

  1. 中断使能

启动阶段为了避免干扰,CPU会关闭所有外设的中断。进入main函数后,你需要根据需求“使能中断”,比如允许串口接收数据时触发中断、定时器计时到后触发中断、ADC采样完成后触发中断。

中断就像“外设的呼叫铃”:当外设需要CPU处理数据时,会触发中断,CPU会暂停当前正在执行的代码,跳转到“中断服务程序”处理外设的请求,处理完后再回到原来的代码继续执行。如果不使能中断,CPU就只能“轮询”外设(不断询问“你有没有数据要处理”),效率很低。

  1. 看门狗初始化

如果程序运行中出现bug(比如死循环、数组越界),MCU会卡住,无法继续工作。看门狗就是为了解决这个问题:启动后初始化看门狗,程序需要在“规定时间内”给看门狗“喂狗”(发送一个信号);如果程序卡住,没按时喂狗,看门狗会触发复位,让MCU重新启动,恢复正常工作。

看门狗不是启动过程的必须步骤,但对于工业控制、汽车电子等对稳定性要求高的场景,是必不可少的“安全措施”。

  1. 低功耗优化:

如果你的设备用电池供电(比如智能手环、传感器节点),启动后还需要配置“低功耗模式”。MCU支持多种低功耗模式(比如睡眠模式、停机模式、待机模式),在不需要工作时(比如等待传感器数据时),进入低功耗模式,关闭部分时钟和外设,降低功耗,延长电池寿命。

低功耗配置通常在main函数里完成,根据程序的运行逻辑触发(比如每隔10秒唤醒一次,采集数据后再进入低功耗)。

总结MCU启动过程的核心逻辑

  1. 硬件触发阶段:上电→复位电路检测电压→给CPU发复位信号→CPU恢复默认状态;

  2. 模式选择与引导阶段:CPU检测启动模式引脚→确定程序存储器→读取向量表→跳转到复位中断服务程序;

  3. 软件初始化阶段:初始化RAM、堆栈、时钟、关键外设→跳转到main函数→执行用户程序。


网站公告

今日签到

点亮在社区的每一天
去签到