技术术语 | 全称 | 核心定义 | 主要特点 | 典型应用场景 | 技术优势 | 局限性 | 数据断电 / 上电保存性 |
---|---|---|---|---|---|---|---|
Flash Memory(闪存) | Flash Memory | 非易失性存储芯片,可电擦除和重写,兼具 ROM 的非易失性和一定的可改写性 | 1. 非易失性,断电数据不丢失 2. 可多次擦写(数万至数百万次) 3. 读写速度快于传统 ROM 4. 分 NOR Flash(随机访问)和 NAND Flash(块访问) |
1. U 盘、SD 卡、固态硬盘(SSD) 2. 智能手机、平板电脑的存储芯片 3. 嵌入式系统程序存储(路由器、智能手表) |
1. 无需电池维持数据 2. 擦写速度和耐用性优于早期存储介质 3. 体积小、功耗低,容量可做大 |
1. 擦写次数有限,长期使用可能老化 2. 单字节写入速度较慢(尤其 NAND 类型) 3. 成本高于传统 ROM |
非易失性:断电后数据永久保存,上电后可正常读取,无上电丢失问题。 |
ARM | Advanced RISC Machine(进阶精简指令集机器) | 基于 RISC 架构的处理器设计方案,提供高效低功耗的计算能力 | 1. 采用精简指令集,执行效率高 2. 功耗低,散热性能好 3. 架构可授权定制,支持 32/64 位运算 4. 兼容性强,支持多操作系统 |
1. 智能手机、平板处理器(高通骁龙、华为麒麟) 2. 嵌入式设备(智能家居、物联网传感器) 3. 移动终端(笔记本、智能手表)、汽车电子 |
1. 低功耗适合移动设备 2. 架构灵活,可按需定制 3. 生态成熟,应用广泛 |
1. 高性能计算领域(如服务器)略逊于 x86 2. 高端型号成本较高 |
本身不存储数据:ARM 是处理器,负责数据运算,不直接存储数据,数据存储依赖外部介质(如 Flash、RAM 等),因此不存在 “上电丢失数据” 的问题。 |
ROM | Read-Only Memory(只读存储器) | 早期非易失性存储介质,数据通常出厂前写入,正常使用中不可修改 | 1. 非易失性,断电数据永久保存 2. 结构简单,制造成本低 3. 读取速度快,稳定性高 |
1. 早期计算机 BIOS 芯片 2. 家电固定程序(洗衣机、微波炉控制逻辑) 3. 游戏卡带、光盘等一次性写入介质 |
1. 数据稳定性极高,不易受干扰 2. 制造成本低,适合大规模生产 |
1. 数据一旦写入难以修改(需特殊设备) 2. 灵活性差,无法适应程序更新 |
非易失性:数据由工厂预先写入,断电后永久保存,上电后可直接读取,无上电丢失问题。 |
EEPROM | Electrically Erasable Programmable Read-Only Memory(电可擦除可编程只读存储器) | 可通过电信号多次擦除和改写的非易失性存储,ROM 的升级类型 | 1. 非易失性,断电数据不丢失 2. 可字节级擦写(无需整块擦除) 3. 擦写无需特殊设备,仅需电信号 4. 擦写次数约 10 万次 |
1. 主板 BIOS 设置存储 2. 智能卡、IC 卡数据存储 3. 工业设备参数配置(传感器校准值) 4. 汽车电子故障码、用户设置 |
1. 可局部修改数据,灵活性高 2. 擦写操作简单,无需额外设备 3. 数据保存时间长(可达 10 年以上) |
1. 存储容量小(几 KB 到几 MB) 2. 擦写速度较慢,不适合大量写入 3. 成本高于普通 ROM |
非易失性:数据通过电信号写入后,断电不丢失,上电后可正常读取,无上电丢失问题。 |
RAM | Random Access Memory(随机存取存储器) | 易失性存储介质,用于临时存放处理器正在使用的数据和程序,读写速度极快 | 1. 易失性,断电后数据立即丢失 2. 读写速度极快(纳秒级),远高于 Flash/EEPROM 3. 支持随机访问(任意地址直接读写) 4. 按技术分 DRAM(动态)和 SRAM(静态) |
1. 计算机内存(DDR4/DDR5) 2. 手机运行内存(LPDDR5) 3. 处理器缓存(SRAM,如 CPU 三级缓存) 4. 嵌入式设备临时数据缓冲区 |
1. 读写速度极快,匹配处理器运算需求 2. 支持高频随机访问,适合临时数据处理 |
1. 易失性,断电数据丢失(需依赖外部存储持久化) 2. 容量成本高于 Flash(同等容量价格更高) 3. DRAM 需定期刷新,消耗额外功耗 |
易失性:依赖持续供电维持数据,断电后数据立即丢失,上电后需重新从外部存储(如 Flash)加载数据,存在 “上电丢失数据” 的特性。 |
1. pflash 分区(非易失性,断电数据保留)
存放程序代码、只读数据,特点是只读 / 少写、断电不丢失,是程序的 “静态基础”:
分区名称 | 作用说明 | 核心特性 |
---|---|---|
.text(函数) |
存放编译后的机器指令(程序的执行逻辑,如函数体、算法流程的二进制代码) | - 程序启动后,CPU 从这里取指令执行 - 只读,运行时不可修改 |
.rodata |
存放只读数据(全局 const 常量、字符串字面量,如 const int a = 10; ) |
- 只读,防止程序意外篡改数据 - 直接存储在 pflash,节省 RAM 空间 |
2. ram 分区(易失性,断电数据丢失)
存放动态数据、运行时临时空间,特点是可读写、断电清空,是程序的 “动态工作区”:
分区名称 | 作用说明 | 核心特性 |
---|---|---|
.bss |
存放未显式初始化的全局 / 静态变量(默认值为 0,如 int global_var; ) |
- 程序加载时,系统自动清零 - 仅占内存 “地址空间”,不占可执行文件体积 |
.data |
存放显式初始化的全局 / 静态变量(如 int global_var = 10; ) |
- 程序加载时,从可执行文件中加载初始值 - 运行时可修改,属于 “动态数据” |
.Stack(栈区) |
存放函数调用的临时数据(局部变量、函数参数、返回地址等) | - 自动管理:函数调用时分配,返回时释放 - 空间小、速度快,遵循 “后进先出(LIFO)” |
.Heap(堆区) |
存放动态分配的内存(如 C malloc 、C++ new 申请的内存) |
- 手动管理:程序员控制分配(malloc )和释放(free )- 空间灵活,按需扩容(但需注意内存泄漏) |
.Reg(寄存器区域) |
处理器最核心的临时存储(存放运算中间值、指令指针、函数调用上下文) | - 速度极快(比 RAM 快数倍) - 数量少(几十个通用寄存器),硬件 / 编译器自动调度 |
3. 程序运行流程(pflash ↔ ram 协同)
- 启动阶段:程序从
pflash
的.text
段开始执行(CPU 读取指令),rodata
提供只读常量支持。 - 运行阶段:
- 全局变量(
.bss
/.data
)、局部变量(.Stack
)、动态内存(.Heap
)在ram
中动态分配 / 使用; - 寄存器(
.Reg
)作为 “高速中转站”,衔接 CPU 运算与内存数据,加速程序执行。
- 全局变量(
4. 关键设计逻辑
- “静态存储(pflash) + 动态存储(ram)” 分离:既保证程序 / 常量的 “持久化”(断电不丢),又满足运行时数据的 “灵活性”(可读写、动态分配)。
- 不同分区的 “管理方式” 差异:
.Stack
自动管理(简单但空间有限)、.Heap
手动管理(灵活但需警惕泄漏)、.bss
/.data
关联全局变量生命周期。
F1
1.产品介绍
我们使用stm32f103c8t6系列测试
Commercial Product Code(商用产品型号) | Core(内核) | Frequency (MHz)(频率) | Flash (Kbytes)(闪存容量) | RAM (Kbytes)(随机存取存储器容量) | Package(封装) |
---|---|---|---|---|---|
STM32F103C8T6 | Cortex - M3 | 72 | 64 | 20 | LQFP48 |
Flash 存储器(ROM)
STM32F103C8T6 的 Flash 存储器起始地址为 0x08000000,大小为 0x10000(16 进制),即 65536 字节(10 进制),也就是 64KB。Flash 存储器用于存储程序代码和常量数据。
65536/1024=64KB
SRAM(RAM)
STM32F103C8T6 的 SRAM 起始地址为 0x20000000,大小为 0x5000(16 进制),即 20480 字节(10 进制),也就是 20KB。SRAM 用于存储运行时的数据和变量。
20480/1024=20kb
BOOT1 | BOOT0 | 启动模式 | 说明 | 0x00000000 映射地址 | 0x00000004 映射地址 |
---|---|---|---|---|---|
X | 0 | 主闪存存储器 | 主闪存存储器被选为启动区域(最常使用) | 0x08000000 | 0x08000004 |
0 | 1 | 系统存储器 | 系统存储器被选为启动区域 | 0x1FFFF000 | 0x1FFFF004 |
1 | 1 | 内置 SRAM | 内置 SRAM 被选为启动区域 | 0x20000000 | 0x20000004 |
我们下面只介绍主闪存存储器启动方式
- 内核类型:M3/M4/M7
- 复位后第一步:从地址
0x00000000
取出 堆栈指针 MSP 初始值(栈顶地址 ) - 复位后第二步:从地址
0x00000004
取出 程序计数器 PC 初始值(复位向量 ) - 流程走向:Reset → 获取 MSP 值(
0x00000000
)→ 获取 PC 值(0x00000004
)→ Reset_Handler
- 初始化 MSP:从 0X0800 0000 获取初始主堆栈指针值,为系统运行准备栈空间
- 初始化 PC:从 0X0800 0004 获取复位向量,指向程序执行起点
- 设置堆栈大小:通过
Heap_Size
(堆)、Stack_Size
(栈)定义堆和栈的内存分配 - 初始化中断向量表:基于
__Vectors
定义,建立中断服务程序映射关系 - 调用初始化函数:可选执行如
SystemInit
,完成系统时钟、总线等基础配置 - 调用 __main:借助标准 C 库函数,完成全局变量初始化等准备工作,最终进入
main
函数,是 STM32 程序执行前的 “启动引导” 逻辑 ,参考资料为《STM32 启动文件浅析.pdf》 ,用于理解 STM32 程序从复位到main
执行的底层流程 。
2.仿真
定时器
定时器3 PSC:7200-1 ARR:10000-1 CCR=ARR/2=5000
定时器定时时间:T=(7200*10000) / 72000 000=1s
PWM占空比:Duty=5000/10000=50%
PWM频率:F=72000 000 /7200 / 10000 =1HZ 或者 F=1/T=1/1=1HZ
A.时钟配置
B.寄存器
查看寄存器的值,可以看到寄存器的值和我们设置的值一样。
定时器从0开始,所以寄存器差看出来差一;
C.逻辑分析仪
这里使用 GPIOx_IDR.y 语法,其中 x 表示 A~G 端口,y 表示 0~15 号引脚,点击 Enter 后,Keil 会自动帮我们完成引脚地址设置:
仿真设置
在图中,选择:Use Simulator,即使用软件仿真。选择:Run to main(),即跳过汇编代码,直接跳转到 main 函数开始仿真。设置下方的:Dialog DLL分别为:DARMSTM.DLL和 TARMSTM.DLL,Parameter 均为:-pSTM32F103C8,用于设置支持 STM32F103C8 的软硬件仿真(即可以通过 Peripherals 选择对应外设的对话框观察仿真结果)。最后点击 OK,完成设置
配置好的图:
开始我尝试使用了软件仿真,但是一直不能显示出来,(如果有大佬的话,可以指点一下,解决了少打了一个L,上面图片已经更新),我们最后选择了硬件仿真。
注意:硬件仿真,需要我们连接上我们的板子,并把程序下载进去。
A:找型号
填写如我们的上面的表中就欧克了。
可以参考我的:
3.内存
在startup_stm32f103xb.s文件里:
Stack_Size EQU 0x00000400--》1024MB=1kB--》栈
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x00000200 --》500MB堆
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit