思澈面试笔记-外设

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# 嵌入式外设高频问点

这份笔记按外设分类整理:GPIO、UART、I2C、SPI、PWM、ADC、定时器、中断、DMA。每章都包含概念、面试问法、常见追问和排查思路。

## 1. 外设问题的通用排查思路

嵌入式外设调试不要一上来就改代码,建议按下面顺序:

1. 看原理图:确认引脚、供电、电平、上下拉、外设连接。
2. 看芯片手册:确认引脚复用、寄存器、时序、最大频率。
3. 看代码配置:确认时钟、GPIO 模式、外设参数、初始化顺序。
4. 看运行现象:日志、返回值、状态寄存器、中断标志。
5. 看信号:万用表、示波器、逻辑分析仪。
6. 做最小 Demo:把问题从大工程中抽离出来。
7. 降低复杂度:降低频率、关闭 DMA、改成轮询、缩短线长。

面试表达:

> 外设问题我会把硬件、配置和时序分开排查。先确认供电、接线和引脚复用,再确认外设参数和初始化顺序。如果通信类外设异常,会用逻辑分析仪看是否有时钟、数据和 ACK;如果是电平或 PWM 问题,会用示波器确认波形。

## 2. GPIO

### GPIO 是什么?

GPIO 是 General Purpose Input Output,通用输入输出引脚。MCU 可以把它配置成输入、输出、复用功能、模拟输入等模式。

常见用途:

- 控制 LED。
- 读取按键。
- 控制继电器、蜂鸣器、电源使能。
- 作为 SPI 片选、屏幕复位、模块使能。
- 作为外部中断输入。

### GPIO 常见模式

| 模式 | 作用 |
| --- | --- |
| 输入模式 | 读取外部高低电平 |
| 输出模式 | 输出高低电平 |
| 复用功能 | 连接到 UART、SPI、I2C、PWM 等外设 |
| 模拟模式 | 用于 ADC 或降低数字输入功耗 |
| 上拉输入 | 默认拉高,适合按键接地 |
| 下拉输入 | 默认拉低,适合按键接 VCC |
| 开漏输出 | 只能主动拉低,需要上拉电阻 |
| 推挽输出 | 可以主动输出高电平和低电平 |

### 高频问点:推挽输出和开漏输出有什么区别?

推挽输出:

- 可以主动输出高电平和低电平。
- 驱动能力较强。
- 常用于 LED、普通数字输出。

开漏输出:

- 只能主动拉低,不能主动拉高。
- 高电平依赖上拉电阻。
- 多个设备可以共享一根线。
- 常用于 I2C、线与逻辑、电平转换。

面试答法:

> 推挽输出能主动输出高低电平,适合普通 GPIO 控制。开漏输出只能拉低,释放时靠上拉电阻变高,适合 I2C 这类多设备共享总线的场景。

### 高频问点:上拉和下拉有什么用?

输入引脚如果没有确定电平,会处于悬空状态,读到的值可能随机变化。

上拉:

- 默认高电平。
- 常见于按键另一端接地。

下拉:

- 默认低电平。
- 常见于按键另一端接 VCC。

面试答法:

> 上拉和下拉用于给输入引脚一个默认电平,避免悬空。比如按键接地时,引脚可以配置上拉,未按下读高电平,按下读低电平。

### 高频问点:LED 点不亮怎么排查?

排查顺序:

1. 看原理图,确认 LED 是高电平点亮还是低电平点亮。
2. 确认 GPIO 引脚号是否正确。
3. 确认 GPIO 时钟是否开启。
4. 确认 GPIO 配置为输出模式。
5. 确认是否被复用为其他功能。
6. 用万用表测引脚电压。
7. 确认限流电阻和 LED 方向。

面试表达:

> LED 不亮我不会只看代码,还会先确认硬件连接。有些板子 LED 是低电平点亮,如果代码输出高电平反而是熄灭。然后检查 GPIO 时钟、输出模式、引脚号和复用配置。

### 高频问点:按键为什么要消抖?

机械按键按下和释放时,触点会在短时间内多次抖动,导致程序检测到多次按下。

消抖方法:

- 延时消抖。
- 状态机消抖。
- 定时扫描。
- 硬件 RC 滤波。

简单软件消抖:

```c
if (key_read() == 0) {
delay_ms(20);
if (key_read() == 0) {
// 确认按下
}
}

更好的方式:

在实际项目中,延时消抖简单但会阻塞。更推荐用定时器周期扫描或状态机方式,避免影响主循环或其他任务。

3. UART

UART 是什么?

UART 是异步串口通信接口,不需要共享时钟线,通信双方约定相同的波特率和帧格式。

常见用途:

  • 打印调试日志。
  • 和 GPS、蓝牙、4G、Wi-Fi 模块通信。
  • 和上位机交互。
  • Bootloader 下载。

UART 帧格式

常见格式:起始位 + 数据位 + 校验位 + 停止位

例如 115200 8N1 表示:

  • 波特率:115200
  • 数据位:8 位
  • 校验位:None
  • 停止位:1 位

高频问点:UART 的 TX/RX 怎么连接?

一般交叉连接:

  • MCU TX 接对方 RX。
  • MCU RX 接对方 TX。
  • GND 必须共地。

面试答法:

UART 是点对点异步通信,TX/RX 通常要交叉连接,并且双方必须共地。还要注意电平匹配,比如 MCU 常见 TTL 3.3V,而不是 RS232 电平。

高频问点:串口乱码怎么办?

常见原因:

  1. 波特率不一致。
  2. 数据位、停止位、校验位不一致。
  3. MCU 时钟配置错误,导致实际波特率偏差。
  4. 电平不匹配,例如 RS232 和 TTL 混用。
  5. 串口工具编码或换行显示问题。

排查:

  • 确认双方都是 115200 8N1
  • 检查系统时钟和 UART 分频。
  • 降低波特率测试。
  • 用逻辑分析仪测实际波特率。

高频问点:串口没有输出怎么办?

排查顺序:

  1. 确认 USB 转串口是否正常。
  2. 确认 TX/RX 是否接反。
  3. 确认 GND 是否共地。
  4. 确认串口号和波特率。
  5. 确认 GPIO 复用功能是否配置正确。
  6. 确认 UART 外设时钟是否开启。
  7. 确认代码真的调用了发送函数。
  8. 用示波器看 TX 引脚是否有波形。

高频问点:轮询、中断、DMA 接收有什么区别?

轮询:

  • 程序一直查询状态寄存器。
  • 简单但浪费 CPU。
  • 适合简单 Demo 或低速场景。

中断:

  • 收到数据触发中断。
  • CPU 不需要一直等待。
  • 适合不定长、小数据量。

DMA:

  • 外设和内存直接搬运数据。
  • CPU 负担低。
  • 适合高速或大量数据。
  • 配合空闲中断常用于 UART 不定长接收。

面试答法:

简单场景可以用轮询,实际项目更常用中断或 DMA。UART 大量数据接收时,DMA 可以减少 CPU 搬运开销;不定长协议常配合 UART idle 中断判断一帧结束。

高频问点:UART 丢数据怎么办?

可能原因:

  • 中断处理太慢。
  • 没有及时读取接收寄存器。
  • 接收缓冲区太小。
  • 波特率过高。
  • 关闭中断时间过长。
  • DMA 缓冲区处理不及时。
  • 协议没有流控。

解决思路:

  • 使用环形缓冲区。
  • 使用 DMA。
  • 增大缓冲区。
  • 缩短中断处理。
  • 降低波特率。
  • 使用硬件流控 RTS/CTS。

4. I2C

I2C 是什么?

I2C 是双线同步串行总线,只需要两根线:

  • SCL:时钟线。
  • SDA:数据线。

特点:

  • 多主多从,但常见项目中一个主机多个从机。
  • 通过设备地址区分不同从设备。
  • SCL/SDA 通常是开漏结构,需要上拉电阻。

高频问点:I2C 为什么需要上拉电阻?

I2C 总线通常采用开漏输出,设备只能主动拉低,不能主动拉高。高电平依赖上拉电阻。

没有上拉电阻会导致:

  • 总线无法稳定为高。
  • 起始、停止条件异常。
  • ACK 异常。
  • 设备读不到。

面试答法:

I2C 使用开漏结构,是为了让多个设备可以共享总线,任何设备都可以拉低 SDA/SCL。总线释放后需要靠上拉电阻变成高电平,所以没有上拉会导致通信失败。

高频问点:I2C 的 7 位地址和 8 位地址有什么区别?

I2C 设备地址通常是 7 位。传输时最低位作为读写位,所以有些手册会给出 8 位地址。

例如:

  • 7 位地址:0x3C
  • 写地址:0x78
  • 读地址:0x79

如果驱动 API 要求传 7 位地址,却传了 8 位地址,就会读不到设备。

面试答法:

I2C 地址问题很常见。我要先确认驱动函数需要 7 位地址还是左移后的 8 位地址,再和芯片手册对应。很多设备读不到就是因为地址位数理解错了。

高频问点:I2C 读寄存器的一般流程是什么?

常见流程:

  1. 主机发送设备地址 + 写。
  2. 发送寄存器地址。
  3. 重新开始。
  4. 主机发送设备地址 + 读。
  5. 读取数据。
  6. 最后一个字节发送 NACK。
  7. 停止。

面试答法:

很多 I2C 传感器不是直接读数据,而是先写入寄存器地址,再重新开始读数据。这个 repeated start 流程要符合芯片手册。

高频问点:I2C 设备读不到怎么排查?

排查顺序:

  1. 确认供电和 GND。
  2. 确认 SDA/SCL 接线。
  3. 确认是否有上拉电阻。
  4. 确认地址是 7 位还是 8 位。
  5. 降低速率到 100 kHz。
  6. 使用 I2C scanner 扫描地址。
  7. 用逻辑分析仪看是否有起始信号、地址、ACK。
  8. 查看设备是否需要上电延时或复位。
  9. 检查总线是否被某个设备拉低。

高频问点:I2C 总线被拉低怎么办?

可能原因:

  • 从设备异常,SDA 一直拉低。
  • 主机复位时从设备还处于传输中。
  • 上拉过弱或短路。
  • 引脚模式配置错误。

恢复方法:

  • 重新初始化 I2C 外设。
  • 手动用 GPIO 产生若干个 SCL 脉冲释放从设备。
  • 复位从设备。
  • 断电重启。

5. SPI

SPI 是什么?

SPI 是同步串行通信接口,常见信号:

  • SCLK:时钟。
  • MOSI:主机输出,从机输入。
  • MISO:主机输入,从机输出。
  • CS / NSS:片选。

特点:

  • 全双工。
  • 速度较快。
  • 没有统一的设备地址,通过 CS 选择设备。
  • 协议细节由具体设备决定。

高频问点:SPI 的四种模式是什么?

SPI 模式由 CPOL 和 CPHA 决定。

  • CPOL:时钟空闲电平。
  • CPHA:在哪个边沿采样数据。
模式 CPOL CPHA
Mode 0 0 0
Mode 1 0 1
Mode 2 1 0
Mode 3 1 1

面试答法:

SPI 通信必须保证主从双方的 CPOL 和 CPHA 一致,否则采样边沿错误,数据会错位或完全错误。调试 SPI 时我会优先查设备手册确认模式。

高频问点:SPI 为什么需要 CS?

SPI 没有 I2C 那样的地址机制,主机通过 CS 选择具体从设备。

注意:

  • 一个从设备通常对应一个 CS。
  • 通信开始前拉低 CS,结束后拉高 CS。
  • 有些设备要求一帧传输过程中 CS 不能抖动。

高频问点:SPI 屏幕不显示怎么排查?

排查顺序:

  1. 检查供电和背光。
  2. 检查 RST、DC、CS 引脚。
  3. 检查 SCLK、MOSI 是否接对。
  4. 确认 SPI 模式和频率。
  5. 确认初始化命令是否匹配屏幕驱动芯片。
  6. 确认颜色格式和分辨率。
  7. 降低 SPI 频率测试。
  8. 用逻辑分析仪查看是否有数据发送。

高频问点:SPI Flash 读写要注意什么?

常见注意点:

  • 写数据前需要发送 Write Enable。
  • 写入后要等待 Busy 位清除。
  • 擦除按扇区或块进行。
  • Flash 写入只能把 1 写成 0,不能直接把 0 写成 1,需要擦除。
  • 页写不能跨页或跨页要拆分。

面试答法:

SPI Flash 不是普通 RAM,写入前要擦除,写入后要等待忙状态结束。页写和扇区擦除都要按芯片手册处理,否则会出现数据不完整或写失败。

6. PWM

PWM 是什么?

PWM 是 Pulse Width Modulation,脉宽调制。它通过改变高电平持续时间占整个周期的比例,控制平均输出效果。

核心参数:

  • 频率:周期长短。
  • 占空比:高电平时间占周期比例。
  • 分辨率:占空比可调精度。

用途:

  • LED 调光。
  • 电机调速。
  • 舵机控制。
  • 蜂鸣器发声。

高频问点:PWM 频率和占空比怎么计算?

定时器频率:

1
timer_clk = input_clk / (prescaler + 1)

PWM 频率:

1
pwm_freq = timer_clk / (period + 1)

占空比:

1
duty = compare / (period + 1)

示例:

如果定时器输入 72 MHz,预分频 71,则计数频率为 1 MHz。周期 999,PWM 频率就是 1 kHz。

高频问点:PWM 控制 LED 亮度的原理是什么?

LED 实际上快速亮灭,人眼看到的是平均亮度。占空比越高,平均亮度越高。

面试答法:

PWM 并不是输出真正的模拟电压,而是快速切换高低电平,通过占空比改变平均能量。LED 调光、电机调速都常用这种方式。

高频问点:舵机 PWM 有什么特点?

常见舵机控制周期约 20 ms,脉宽一般在 0.5 ms 到 2.5 ms 之间,对应不同角度。

注意:

  • 舵机更关注脉宽,不只是占空比。
  • 不同舵机范围可能不同。

7. ADC

ADC 是什么?

ADC 是 Analog to Digital Converter,模数转换器,用于把模拟电压转换成数字值。

用途:

  • 读取电池电压。
  • 读取电位器。
  • 读取温度、光照、压力等模拟传感器。
  • 检测按键电阻分压。

高频问点:ADC 分辨率是什么意思?

分辨率表示 ADC 输出数字值的位数。

  • 10 位:0 到 1023。
  • 12 位:0 到 4095。
  • 16 位:0 到 65535。

电压换算:

1
voltage = adc_value / (2^bits - 1) * vref

12 位、参考电压 3.3V:

1
voltage = adc_value / 4095 * 3.3

高频问点:ADC 数值不稳定怎么办?

可能原因:

  • 输入信号本身有噪声。
  • 参考电压不稳定。
  • 采样时间太短。
  • 输入阻抗太高。
  • PCB 布线干扰。
  • 没有滤波电容。
  • 引脚没有配置成模拟模式。

解决方法:

  • 多次采样取平均。
  • 中值滤波。
  • 增加 RC 滤波。
  • 延长采样时间。
  • 稳定参考电压。
  • 做 ADC 校准。

高频问点:ADC 采样时间为什么重要?

ADC 内部采样电容需要时间充电。如果输入阻抗高或采样时间太短,采样电容还没稳定,转换结果就会偏差。

面试答法:

ADC 不只是读一个电压值,还涉及采样保持过程。输入阻抗较高时需要更长采样时间,否则采样电容充电不足,结果会偏低或不稳定。

8. 定时器

定时器能做什么?

常见用途:

  • 周期中断。
  • PWM 输出。
  • 输入捕获。
  • 输出比较。
  • 编码器接口。
  • 计数外部脉冲。
  • 超时检测。

高频问点:定时器周期怎么计算?

1
2
timer_freq = timer_clk / (prescaler + 1)
period_time = (auto_reload + 1) / timer_freq

例如:

  • 定时器时钟 72 MHz。
  • prescaler = 7199。
  • timer_freq = 10 kHz。
  • auto_reload = 9999。
  • 周期 = 1 s。

高频问点:SysTick 和普通定时器有什么区别?

SysTick:

  • Cortex-M 内核自带。
  • 常用于系统节拍、延时、RTOS tick。

普通定时器:

  • MCU 外设。
  • 功能更丰富,如 PWM、输入捕获、编码器。

9. 中断

中断是什么?

中断是 CPU 暂停当前执行流程,转去处理更紧急事件的机制。

常见中断源:

  • GPIO 外部中断。
  • UART 接收中断。
  • 定时器溢出中断。
  • DMA 完成中断。
  • ADC 转换完成中断。

高频问点:中断处理函数里应该注意什么?

原则:

  • 快进快出。
  • 清除中断标志。
  • 不做耗时操作。
  • 不做长时间阻塞。
  • 少用 printf
  • 不随意申请动态内存。
  • 与主循环共享变量时考虑 volatile 和临界区。

面试答法:

中断里只做必要处理,例如读取状态、清除标志、保存数据、设置事件标志。复杂逻辑放到主循环或任务中处理,这样能减少中断延迟。

高频问点:中断优先级有什么用?

中断优先级决定多个中断同时发生时谁先执行,以及高优先级中断是否能抢占低优先级中断。

注意:

  • 优先级配置错误可能导致实时性问题。
  • 在 RTOS 中,中断优先级还要满足系统 API 调用限制。

10. DMA

DMA 是什么?

DMA 是 Direct Memory Access,直接内存访问。它允许外设和内存之间直接搬运数据,减少 CPU 参与。

常见用途:

  • UART 大量接收。
  • SPI 屏幕刷屏。
  • ADC 多通道采样。
  • I2S 音频数据。

高频问点:DMA 有什么优缺点?

优点:

  • 降低 CPU 占用。
  • 适合大数据量和高速传输。
  • 可以配合中断处理半完成和完成事件。

缺点:

  • 配置复杂。
  • 缓冲区生命周期要保证。
  • cache 一致性要注意。
  • 不适合特别小的数据传输时滥用。

高频问点:DMA 普通模式和循环模式有什么区别?

普通模式:

  • 传输指定长度后停止。
  • 适合一次性发送或接收。

循环模式:

  • 传输到末尾后回到缓冲区开头继续。
  • 适合 ADC 连续采样、UART 环形接收。

高频问点:UART DMA 接收不定长数据怎么做?

常见方法:

  • DMA 负责持续接收数据。
  • UART idle 中断判断一帧结束。
  • 在 idle 中断中计算接收长度。
  • 通知任务或主循环处理数据。

面试答法:

UART 不定长接收常用 DMA + idle 中断。DMA 负责搬数据,空闲中断表示一段时间没有新字节,可以认为一帧结束,然后根据 DMA 剩余计数计算本帧长度。

11. 外设对比速记

外设 线数 是否同步 常见用途 高频问题
GPIO 1 LED、按键、控制信号 上下拉、复用、有效电平
UART 2 日志、模块通信 波特率、TX/RX、共地
I2C 2 传感器、EEPROM 上拉、地址、ACK
SPI 4+ 屏幕、Flash CPOL/CPHA、CS、频率
PWM 1 定时器输出 LED、电机、舵机 频率、占空比、分辨率
ADC 1 模拟采样 电压、传感器 参考电压、噪声、采样时间

12. 面试高频综合题

题目:I2C 和 SPI 怎么选?

答法:

I2C 线少,只需要 SDA 和 SCL,适合低速传感器和多个从设备共享总线,但速度相对较低,依赖上拉电阻,抗干扰能力和线长有限。SPI 速度更高,适合屏幕、Flash、ADC 等高速设备,但线更多,每个设备通常需要独立 CS。选择时要看速度、引脚数量、设备数量和协议复杂度。

题目:为什么通信外设要看逻辑分析仪?

答法:

因为软件日志只能说明驱动层认为自己做了什么,逻辑分析仪能看到总线上真实发生了什么。比如 I2C 有没有 ACK、SPI 模式是否错位、UART 波特率是否正确,都可以通过波形确认。

题目:外设初始化一般包括哪些步骤?

答法:

一般包括打开时钟、配置 GPIO 复用、设置外设参数、配置中断或 DMA、清除状态标志、使能外设。不同外设还需要按芯片手册执行特定初始化时序。

题目:为什么同一段代码换板子就不工作?

可能原因:

  • 引脚定义不同。
  • 外设时钟不同。
  • 电源电压不同。
  • 外部上拉/下拉不同。
  • 晶振频率不同。
  • 外设地址或芯片型号不同。
  • 复位和启动电路不同。

面试答法:

换板子后我会先对照原理图和 board 配置,确认引脚、时钟、电源、外设型号和地址是否一致。嵌入式代码和硬件强相关,不能只看软件逻辑。

1