第四章 底层硬件接口与驱动开发:I2C、SPI、UART 协议、中断处理

章节导读:固件开发中,对底层总线协议(I2C、SPI、UART)的理解程度直接决定面试深度。本章聚焦“协议特性+驱动实现+中断协同”三位一体的回答框架,帮你从“会用函数”升级到“能设计驱动”。
面试问题 1. 协议特性 速率/总线/主从 2. 驱动实现 寄存器/轮询/中断 3. 中断处理 上下文/锁/性能 4. 完整回答 先协议后中断 回答框架图

面试问答卡片

卡片1:I2C 与 SPI 协议区别及驱动设计

面试问题请对比 I2C 和 SPI 协议,并说明在固件中如何实现一个简单的 SPI 驱动。
考察点协议基本原理理解(总线拓扑、速率、同步/异步);驱动分层思路(硬件抽象层 → 传输层 → 应用层);对中断/轮询的选择。
回答框架1. 对比要点:I2C 半双工、2线、多主机、速率较低;SPI 全双工、4线、一主多从、速率高。2. 驱动实现步骤:配置 GPIO 复用为 SPI 引脚 → 初始化 SPI 外设时钟和寄存器 → 实现收发函数(轮询或 DMA)→ 封装成读写 API。3. 中断场景:大批量传输时使用。
示例回答“I2C 用 SDA+SCL 两线实现多从机通信,速率通常 100k~400kHz;SPI 用 MOSI/MISO/SCK/CS 四线,全双工可达数十 MHz。实现 SPI 驱动时,我先配置时钟和引脚复用,初始化 SPI 控制寄存器,然后封装发送字节和接收字节的轮询函数,上层调用时传递片选信号和数据缓冲区。若数据量大,改用中断或 DMA 释放 CPU。”
可能追问• 如何解决 I2C 总线冲突?
• SPI 支持多从机时片选如何管理?
• 你的驱动如何支持异步操作?
避坑提醒❌ 不要只背协议表格,要体现“为什么会选择某协议”的工程判断。
✅ 提到“根据速率和引脚数选型”,并在驱动中说明临界区保护。

卡片2:UART 中断处理与环形缓冲区设计

面试问题如何在 UART 驱动中利用中断和环形缓冲区实现高效收发?
考察点中断处理流程;环形缓冲区数据结构设计;临界区保护;避免数据丢失或覆盖。
回答框架1. 数据结构:定义环形缓冲区结构体(head、tail、count、数组)。2. 发送中断:将待发数据写入缓冲区,使能 TX 空中断,在 ISR 中从缓冲区取出字节发送。3. 接收中断:ISR 中将硬件 RDR 数据存入接收缓冲区,更新索引。4. 同步保护:ISR 内关中断或使用原子操作更新索引,主循环以读缓冲区方式消费。
示例回答“我定义一个 uint8_t 数组和读写指针作为环形缓冲区。接收中断到来时,将字节写入缓冲区并移动写指针(循环回绕),若缓冲区满则丢包。发送时,主程序先把数据压入缓冲区,然后开启 TX 空中断,ISR 从缓冲区取出一个字节写到硬件寄存器,直至缓冲区空。所有指针更新在关中断状态下完成,保证原子性。”
可能追问• 环形缓冲区判空判满怎么实现?
• 多个中断优先级如何配置?
• 中断栈溢出如何处理?
避坑提醒❌ 避免设计为“一个字节一个中断”,高频时性能极差。
✅ 推荐使用 FIFO 模式或 DMA+半满中断,并说明缓冲区大小与波特率的匹配关系。

卡片3:中断延迟与实时性优化

面试问题如何测量并优化固件中的中断响应延迟?请结合一个具体外设说明。
考察点中断延迟概念(硬件延迟+软件开销);测量方法(GPIO 示波器/逻辑分析仪);优化手段——最小化 ISR 长度、优先级抢占、上下文切换成本。
回答框架1. 定义延迟:从硬件触发到 ISR 第一条指令执行的时间。2. 测量:在 ISR 入口/出口翻转 GPIO,用示波器看脉冲宽度。3. 优化方向:ISR 内只做必要操作(存取数据、清标志),耗时任务放入任务或下半部(如 FreeRTOS 的信号量通知任务)。4. 优先级:高实时中断配置为最高优先级,避免被低优先级 ISR 阻塞。
示例回答“针对 SPI 接收,我在 ISR 入口 set 一个 GPIO,出口 clear,用示波器测得延迟约 0.5 μs。优化时,我把数据解析逻辑移到了任务中,ISR 只把原始数据放入环形缓冲区并发送信号量。同时把该中断优先级设为最高,并确保 ISR 内不调用任何可能阻塞的函数。优化后延迟降至 0.3 μs。”
可能追问• 中断嵌套如何影响延迟?
• 如果中断频率很高怎么办?
• 如何用 DMA 降低中断频率?
避坑提醒❌ 别只说“关中断时间过长”,却没给具体数据。
✅ 最好提供量化结果(如优化前/后延迟对比),并提到示波器或逻辑分析仪的实际使用经验。

项目案例:多传感器数据采集固件 (I2C + SPI + UART + 中断)

项目名称工业环境监测模块——多传感器数据采集与上报
业务背景为工厂生产线设计一个温湿度、振动、烟雾监测节点,通过 UART 上报到上位机,要求实时性高、数据不丢包。
规模指标• 传感器数:3 个 (I2C 温湿度、SPI 振动、UART 烟雾)
• 采样频率:温湿度 10Hz,振动 100Hz,烟雾 1Hz
• 固件代码量:~3500 行 C
• 内存:SRAM 64KB,Flash 256KB
技术栈STM32L4 + HAL 库 + FreeRTOS;I2C 轮询 + SPI DMA + UART 中断 + 环形缓冲区(每个外设独立缓冲区)
核心难点1. 振动传感器 SPI 速率 10MHz,DMA 传输时 CPU 还需处理其他中断。
2. UART 接收中断频率高,环形缓冲区临界区保护需用关中断而非信号量(避免死锁)。
3. 三个传感器数据时间戳对齐,需利用 SysTick 同步。
面试高频追问• 为什么 SPI 用 DMA 而 I2C 用轮询?
• 环形缓冲区大小如何确定?
• 如果 UART 中断丢失一个字节,你怎么排查?
• 如何测试固件在最大负载下的稳定性?
可迁移回答话术“我根据传感器数据速率和 CPU 负载计算了缓冲区大小。例如 UART 烟雾传感器 1Hz 发送 20 字节,波特率 115200,中断频率不高,缓冲区设为 256 字节足够。而 SPI 振动速率高,使用 DMA 环形双缓冲 + 半传输中断,将数据拷贝到处理任务中。关键技巧:关中断做缓冲区指针更新,保证 ISR 与任务之间不冲突。”
中断处理方案 延迟来源? 数据安全? 性能瓶颈? 硬件+软件开销 临界区+环形缓冲 ISR精简+DMA 追问路径:由浅入深
💡 学霸笔记:底层接口面试高频方向——“协议对比+驱动分层+中断与 DMA 选择+环形缓冲区设计”。准备一个完整的项目案例(如上面的工业监测),能覆盖所有考点。
⚠️ 常见误区:不要花太多时间背寄存器名字,面试官更看重“为什么这么设计”。例如:SPI 驱动用轮询还是中断,取决于数据速率和 CPU 负载,回答时要给出判断依据。