嵌软面试——通信协议
一、UART/USART
Q1: UART的通信帧格式是怎样的?
答案:
每帧数据包含:起始位(1位,低电平)
数据位(5~9位,通常8位)
校验位(可选,奇偶校验)
停止位(1~2位,高电平)
示例:
起始位(0) + 数据位(0x55) + 无校验 + 停止位(1)
Q2: 为什么UART是“异步”通信?
答案:
无时钟线(SCL),依赖双方预设的波特率(Baud Rate)同步采样数据。
每个数据帧通过起始位重新同步时序。
1. 同步(Synchronous)
定义:任务按顺序执行,必须等待前一个任务完成后才能开始下一个任务。
特点:
阻塞式:调用方必须等待被调用方的结果返回后才能继续执行。
顺序性强:任务严格按照代码编写的顺序执行。
简单直观:逻辑清晰,易于理解和调试。
例子:
同步函数调用:函数A调用函数B,必须等B执行完毕并返回结果后,A才能继续。
排队取餐:必须等前一个人取完餐,才能轮到你。
2. 异步(Asynchronous)
定义:任务可以独立执行,调用方无需等待被调用方的结果,而是通过回调、事件或通知等方式在完成后处理结果。
特点:
非阻塞式:调用方发起请求后可以继续执行其他任务,无需等待。
并发性高:适合处理耗时操作(如网络请求、文件读写)。
复杂度高:需要通过回调、Promise、async/await等机制处理结果。
例子:
异步编程:JavaScript中的
setTimeout
、Ajax请求。点餐后拿号:下单后可以去做其他事,餐好了会通知你。
它们的核心区别在于任务执行的顺序性和依赖性,以及是否需要等待
2. 硬件设计
Q3: UART最少需要几根线?电平标准有哪些?
答案:
最少 2根线(TX发送、RX接收),全双工通信。
电平标准:
TTL UART:3.3V/5V(MCU直接使用)
RS232:±12V(长距离,需电平转换芯片如MAX232)
RS485:差分信号(抗干扰,多设备共享总线)
Q4: 如何实现UART的长距离通信(>1m)
答案:
转换为RS485(差分信号,抗干扰,支持千米级传输)或光隔离(防高压干扰)。
3. 软件实现
Q5: UART如何检测数据传输错误?
答案:
奇偶校验:检查数据位中“1”的个数是否符合奇/偶规则。
帧错误:停止位未检测到高电平。
溢出错误:接收缓冲区未及时读取,新数据覆盖旧数据。
Q6: UART接收数据时如何避免溢出?
答案:
使用FIFO或DMA减少CPU中断负载。
提高中断优先级,及时读取接收缓冲区(如STM32的
HAL_UART_Receive_IT()
)。
Q7: 为什么调试日志常用UART而不用SPI/I2C?
答案:
UART连接简单(仅需TX/RX),无需时钟同步,适配大多数终端工具(如PuTTY)。
SPI/I2C需协议解析,适合设备间通信,不适合人机交互。
Q8: UART的波特率误差允许范围是多少?
答案:
通常要求误差<3%(如9600bps时,实际波特率需在9312~9888bps之间)。
误差过大会导致采样点偏移,数据错位。
Q9: USART和UART的区别是什么?
答案:
UART:纯异步(无时钟线)。
USART:可配置为同步模式(带SCLK时钟线)或异步模式(同UART)。
同步模式:常用于高速通信或需要严格时序的场景(如SPI兼容模式)。
Q10: USART的同步模式下,时钟(SCLK)由谁提供?
答案:
主设备提供时钟(类似SPI),从设备根据时钟边沿采样数据。
Q11: USART的硬件流控(Hardware Flow Control)是什么?
答案:
通过RTS(Request to Send)和CTS(Clear to Send)信号线控制数据流,防止缓冲区溢出。
应用场景:高速通信(如GPS模块连续输出数据)。
Q12: 如何用USART模拟SPI?
答案:
配置USART为同步主模式(SCLK输出),通过TX发送数据,RX接收数据(半双工SPI)。
Q13: 什么场景下会选择USART而非UART?
答案:
需要同步通信(如驱动SPI设备但硬件SPI引脚不足)。
需要硬件流控(如高速Modem通信)。
面试技巧
举例说明:
“我在项目中用UART连接GPS模块(NMEA-0183协议),波特率9600,无校验位。遇到数据丢失后,发现是MCU中断优先级过低,改用DMA解决。”陷阱问题:
“UART能实现多设备通信吗?”
可以,但需软件协议(如MODBUS)或硬件切换(如多路复用器)。
“USART的同步模式和SPI有何区别?”
USART同步模式通常为半双工,SPI为全双工;SPI有CS片选信号,USART无。
二、IIC协议
1. 核心特性
两根线:
SCL(Serial Clock):时钟线,由主设备控制。
SDA(Serial Data):双向数据线。
多主多从:支持多个主设备(通过仲裁机制避免冲突)。
半双工:同一时刻只能发送或接收数据。
地址寻址:每个从设备有唯一7位或10位地址。
2. 关键问题
Q1: I2C的起始(START)和停止(STOP)条件如何定义?
答案:
START:SCL高电平时,SDA从高→低跳变。
STOP:SCL高电平时,SDA从低→高跳变。
Q2: I2C的7位地址格式是怎样的?如何区分读/写操作?
答案:
地址位(7位) + 读写位(1位):
0
:主设备写数据到从设备。1
:主设备从从设备读数据。
示例:地址0x68(7位:1101000)的写操作字节为
0xD0
(11010000)。
Q3: 为什么I2C需要上拉电阻?阻值如何计算?
答案:
原因:I2C设备为开漏输出(只能拉低,不能主动拉高),需外部电阻提供高电平。
计算:
最小值:
Rp(min) = (Vdd - Vol) / Iol
(避免电流过大)。最大值:
Rp(max) = tr / (0.8473 × Cbus)
(满足上升时间)。
典型值:3.3V系统常用3.3kΩ~4.7kΩ(标准模式100kHz)。
Q4: I2C总线电容过大会导致什么问题?如何解决?
答案:
问题:信号上升时间变长,可能违反时序(如SCL频率高时采样错误)。
解决:
减小上拉电阻(但需注意驱动能力)。
使用I2C缓冲器(如PCA9515)隔离电容。
Q5: I2C如何实现多主设备仲裁?
答案:
线与逻辑:所有主设备监听SDA,若发现自身发送的电平与总线实际电平不一致(即其他主设备拉低),则退出竞争。
仲裁过程:从地址位开始比较,低电平优先。
Q6: I2C总线上拉电阻接3.3kΩ,但通信失败,可能原因?
答案:
总线电容过大(如导线过长、设备过多),导致上升时间不足。
从设备地址冲突或未响应。
主设备未正确处理ACK/NACK。
Q7: I2C的完整数据传输流程是怎样的?
答案:
主设备发送START条件。
发送从设备地址 + 读写位。
从设备回复ACK(拉低SDA)。
传输数据(每字节后跟ACK/NACK)。
主设备发送STOP条件。
Q8: 如何用代码实现I2C的起始信号?
void I2C_Start() {SDA_High(); // SDA=1SCL_High(); // SCL=1Delay();SDA_Low(); // SDA=0 (START)Delay();SCL_Low(); // SCL=0
}
Q9: I2C从设备无ACK响应,如何排查?
答案:
检查从设备地址是否正确(示波器抓取地址字节)。
确认从设备供电和复位正常。
检查总线是否被意外拉低(如设备故障导致SDA锁死)。
Q10: I2C适合哪些场景?举例说明。
答案:
低速、省引脚的设备:传感器(BME280)、EEPROM(AT24C02)、RTC(DS3231)。
多设备共享总线:如一块PCB上挂载多个传感器。
Q11: I2C和SPI在驱动OLED时如何选择?
答案:
I2C:引脚少(仅2线),但速率低(通常≤400kHz),适合小屏或静态显示。
SPI:速率高(可达MHz级),适合刷新率高的动态显示。
Q12: I2C和UART谁更适合长距离通信?
答案:
UART+RS485:更适合长距离(差分信号抗干扰)。
I2C通常用于板内通信(<1m),长距离需加缓冲器。
Q13: “I2C总线上拉电阻用1kΩ行不行?
答案:
需计算:若总线电容大(如100pF),1kΩ可能导致上升时间不足(标准模式要求tr≤1μs)。
Q14: “I2C可以热插拔吗?”
答案:
不推荐!热插拔可能导致总线电平紊乱,需设计热插拔保护电路(如TI的I2C缓冲器)。
三、SPI协议
1. 核心特性
全双工通信:数据同时收发(MOSI和MISO独立)。
同步时钟:主设备控制SCLK,严格时序同步。
四线制(标准SPI):
SCLK:时钟线(主→从)。
MOSI(Master Out Slave In):主设备发送,从设备接收。
MISO(Master In Slave Out):从设备发送,主设备接收。
CS/SS(Chip Select):片选信号(低电平有效,每个从设备独立一根)。
Q1: SPI的四种工作模式(CPOL/CPHA)是什么?如何选择?
答案:
CPOL(Clock Polarity):时钟空闲状态。
0
:SCLK空闲时为低电平。1
:SCLK空闲时为高电平。
CPHA(Clock Phase):数据采样边沿。
0
:在SCLK的第一个边沿(上升或下降)采样。1
:在SCLK的第二个边沿采样。
Q2: SPI是全双工还是半双工?为什么?
答案:
全双工,因为MOSI和MISO可同时传输数据(主设备发送时,从设备也可回复)
Q3: SPI最多能接多少个设备?如何扩展?
答案:
理论限制:受主设备CS引脚数量限制(通常MCU提供4~8个专用CS)。
扩展方法:
译码器扩展(如74HC138):用3个GPIO生成8个CS信号(
2^N
扩展)。菊花链(Daisy Chain):所有从设备共享CS,数据级联(需设备支持,如某些ADC)。
SPI切换器(如模拟开关ADG704):动态切换总线路径
Q4: SPI的片选信号(CS)可以共用吗?为什么?
答案:
不能共用(除非菊花链模式),因为:
所有从设备的MISO会冲突(多个输出短路)。
主设备无法区分数据来源。
Q5: SPI长距离通信(>10cm)需要注意什么?
答案:
降低SCLK频率(减少信号失真)。
使用差分SPI(如LVDS)或加缓冲器(如SN74LVC4245)。
缩短走线长度,避免平行布线(减少串扰)。
Q6: SPI的时钟频率如何设置?受什么因素限制?
答案:
设置方法:通过主设备时钟分频(如STM32的
SPI_BaudRatePrescaler
)。限制因素:
从设备支持的最高频率(如Flash芯片通常支持50MHz)。
总线电容(导线越长,最大频率越低)。
Q7: SPI通信时MISO无数据,如何排查?
答案:
检查CS信号是否已拉低(从设备未使能)。
确认时钟模式(CPOL/CPHA)匹配。
测量SCLK和MOSI波形(示波器抓取时序)。
Q8: 为什么Flash芯片常用SPI而不用I2C?
答案:
SPI速率远高于I2C(如W25Q128支持104MHz,I2C仅400kHz)。
Flash需频繁读写大数据块,SPI的全双工特性更高效。
Q9: “SPI可以没有MISO线吗?
答案:
可以!如果仅需主设备发送数据(如驱动LED屏),可省略MISO(单工模式)。
Q10: “SPI的CS信号可以一直拉低吗?
答案:
不建议!CS拉低期间从设备会持续消耗功率,且可能干扰其他设备。应在数据传输间隙释放CS。