硬件基础:认识MCU/CPU、总线与外设
做嵌入式开发,说白了就是跟芯片打交道。你写的每一行代码,最终都要落到硬件上执行。我记得刚入行那会儿,拿到一块新板子就急着写代码,结果连GPIO都点不亮——后来才发现,我连芯片用的是AHB还是APB总线都没搞清楚。
这一章,咱们就把这些基础概念捋清楚。别觉得枯燥,这些是后面所有实战的根基。
1. MCU与CPU:核心的大脑
先说说MCU和CPU的区别。很多人混着用,其实不对。
- CPU(中央处理器)——就是芯片里负责运算和控制的那个核心。它执行指令,处理数据。
- MCU(微控制器)——把CPU、内存、各种外设接口集成在一个芯片上。说白了,MCU = CPU + 存储器 + 外设。
我做过一个项目,用STM32F103控制电机。当时选型时就在想:用MCU还是MPU?后来发现,对于这种实时控制场景,MCU更合适——功耗低、启动快、外设丰富。你想想看,如果只是点个灯、读个传感器,搞个带Linux的MPU,那不是杀鸡用牛刀吗?
核心要点:嵌入式驱动开发,我们主要面对的是MCU。你需要关注的是它的内核架构(ARM Cortex-M、RISC-V等)、主频、中断控制器、存储器映射。
2. 总线系统:AHB与APB
MCU内部,CPU和外设之间怎么通信?靠总线。ARM Cortex-M系列常用的总线有两条:AHB和APB。
| 特性 | AHB(高级高性能总线) | APB(高级外设总线) |
|---|---|---|
| 速度 | 高(通常与CPU同频) | 低(分频后) |
| 数据宽度 | 32/64/128位 | 8/16/32位 |
| 挂载设备 | Flash、SRAM、DMA、高速外设 | GPIO、UART、SPI、I2C、定时器 |
| 协议复杂度 | 复杂(支持流水线、突发传输) | 简单(地址+数据两阶段) |
为什么会这样设计?我个人的理解是:成本与性能的平衡。AHB跑得快,但电路面积大、功耗高;APB结构简单,适合那些不需要高速通信的外设。你想想,GPIO翻转一次也就几兆赫兹,没必要挂在AHB上浪费资源。
实战经验:我在调试一个I2C传感器时,发现通信总超时。查了半天,原来是APB时钟分频配错了,导致I2C模块时钟只有几百千赫兹。嗯,这种坑踩过一次就记住了——外设时钟源一定要先确认。
3. 常见外设:GPIO、UART、SPI、I2C
这些是嵌入式开发最常用的外设接口。咱们一个一个说。
3.1 GPIO——最基础的数字接口
GPIO(通用输入输出)可以配置成输入、输出、复用功能。说白了,就是芯片的“手脚”。
- 输出模式:推挽、开漏。推挽能输出高低电平,开漏需要外部上拉。
- 输入模式:浮空、上拉、下拉。我习惯用上拉输入,省得悬空时电平乱跳。
- 复用功能:比如把某个引脚配置成UART的TX/RX。
3.2 UART——异步串行通信
UART(通用异步收发器)只需要两根线:TX和RX。没有时钟线,靠波特率同步。我曾经用UART调试一个GPS模块,波特率设错了,打印出来全是乱码——后来用示波器量了一下,才发现模块默认是9600,我配成了115200。
3.3 SPI——高速同步通信
SPI(串行外设接口)有四根线:SCK、MOSI、MISO、CS。全双工,速度快。适合SD卡、显示屏、ADC这类设备。注意:SPI有四种模式(时钟极性和相位),主从设备必须匹配。
3.4 I2C——两线制总线
I2C(集成电路总线)只需要SDA和SCL两根线,支持多主多从。每个设备有唯一地址。速度比SPI慢,但节省引脚。我做过一个项目,挂了5个I2C传感器,地址冲突了——后来用了一个多路复用器才搞定。
避坑指南:我曾经在I2C通信中忘记加外部上拉电阻,结果总线一直低电平,设备无法响应。记住:I2C是开漏输出,必须要有上拉电阻(通常4.7kΩ)。
4. 数据手册与参考手册的阅读方法
这是嵌入式工程师的必修课。拿到一份几百页的PDF,怎么快速找到你需要的信息?
- 先看芯片概览——了解芯片有哪些外设、多少引脚、封装类型。
- 找到存储器映射——外设寄存器的基地址都在这里。比如GPIOA的基地址是0x40020000。
- 定位外设章节——比如你要用UART,直接跳到UART章节。
- 看寄存器描述——每个寄存器有哪些位、什么功能、复位值是多少。
- 参考时序图——特别是SPI和I2C,时序图能帮你理解通信过程。
我的习惯:拿到新芯片,我会先打印一份存储器映射表贴在工位上。写驱动时,随时对照寄存器地址,省得翻来翻去。
5. 知识结构图:硬件基础全景
下面这张图,把本章的核心知识点串起来了。你可以把它当作一个“硬件地图”,以后写驱动时,随时回来对照。
6. 阅读手册的实战技巧
最后,分享几个我这些年积累的读手册技巧:
- 先粗后细——第一遍只看目录和概览,知道手册里有什么。第二遍再细读你需要的外设章节。
- 关注寄存器复位值——很多坑都出在“我以为复位值是0,其实是1”。
- 善用搜索——PDF里搜关键词,比如“GPIO_CRL”、“波特率”、“中断”。
- 对照代码看手册——我习惯打开一个参考工程,一边看手册一边看代码,理解更透彻。
小技巧:把手册中常用的寄存器地址、位定义截图保存,或者做成一个速查表。写驱动时直接复制粘贴,省时省力。