【嵌入式面试】UART 高频面试题
【嵌入式面试】UART 高频面试题
UART(通用异步收发器)是嵌入式系统最基础的通信接口,调试打印、AT 指令、Modbus 都离不开它。本文整理了 UART 从帧格式、波特率误差到电平标准、环形缓冲、空闲中断收不定长帧的高频面试题与参考答案。
时序图
char i=0;
while(1)
{
printf("%c\n",i++);
delay_ms(1000);
LED0=!LED0;
}先发LSB,再发MSB,读的时候从末尾往前读
空闲位是高电平,停止位也是高电平,还可以插一个奇偶校验位,根据1的个数来进行是否写入



一、异步通信与帧格式
什么是 UART?为什么是"异步"?
UART(通用异步收发器)是异步串行通信接口:双方不需要共享时钟,靠约定波特率和帧格式同步。说它异步是因为数据线上没有时钟信号,接收方靠检测起始位的下降沿来对齐采样时刻,并以约定波特率推算每个数据位的采样点。
UART 的帧格式是怎样的?各个位的作用?
一帧由 起始位 + 数据位 + 校验位(可选)+ 停止位 组成:起始位固定为低电平(1 位),标志一帧开始;数据位通常 5~8 位,低位(LSB)先发;校验位可选(奇/偶/无);停止位固定为高电平(1/1.5/2 位),标志一帧结束。空闲时数据线保持高电平,所以起始位的下降沿就是帧同步信号。
8N1 代表什么意思?
8N1 = 8 位数据位 + 无校验(None)+ 1 位停止位,是最常用的串口配置(如 115200-8-N-1)。同理 8E1 表示偶校验、8O1 表示奇校验。发送一帧实际占用 10 位(1 起始 + 8 数据 + 1 停止),所以有效数据率 = 波特率 ÷ 10,如 115200 波特率下每秒最多传约 11520 字节。
接收方怎么知道一帧什么时候开始?起始位为什么是低电平?
空闲时 TX 线为高电平,一帧开始发送低电平起始位,接收方检测到高→低的下降沿就认为帧开始,并从该时刻起按波特率采样后续位。起始位用低电平正是为了与空闲高电平形成明显的跳变沿,作为可靠的帧同步信号;若空闲为低、起始为高,则难以区分帧边界。
二、波特率与误差
什么是波特率?波特率误差如何计算?多少算合格?
波特率是每秒传输的码元(位)个数,单位 bps(如 9600、115200)。波特率误差 = |实际波特率 − 理想波特率| ÷ 理想波特率,由系统时钟分频精度决定(如 8MHz 晶振无法整分频出 115200 就会产生误差)。一般要求总误差 < 2%(过采样 16 倍时每位采样 16 次,容忍约 ±3%);误差过大导致采样点漂移到位的边界,产生乱码或丢字节。
为什么 UART 双方必须约定相同的波特率?
因为 UART 没有时钟线,接收方按约定波特率在每个位的中间时刻采样。若波特率不一致,采样点会逐位漂移,到帧末尾可能采到错误电平甚至把停止位采成数据。约定一致且误差在容限内(<2%),接收方才能稳定对齐。
什么是过采样?为什么 UART 要过采样?
过采样指接收方用远高于波特率的时钟(常见 16 倍)去采样数据线:先用它检测起始位(连续采样到低电平确认下降沿),再用计数方式在每个位的中点附近采样以提高抗干扰性。STM32 USART 支持 8 倍或 16 倍过采样;过采样倍数越高,对波特率误差容忍度越大、抗毛刺越好,但要求系统时钟更高。
三、电平标准
TTL、RS232、RS485 电平有什么区别?如何选择?
TTL 电平:0~0.8V 为低、2~5V 为高,单端、距离短(几十 cm)、只能板级/点对点;RS232:负逻辑,逻辑 1 为 -3~-15V、逻辑 0 为 +3~+15V,单端、抗干扰一般,点对点,最远约 15m;RS485:差分信号(A/B 两线电压差),半双工、可多点组网(标准 32 个节点)、最远约 1200m、抗干扰强。选型:板内用 TTL,短距离调试用 RS232,长距离、多节点、工业现场用 RS485。
RS485 为什么用差分传输?终端电阻怎么接?
差分传输用两根线(A/B)的电压差表示逻辑,共模干扰同时叠加在两线上、差值不受影响,因此抗干扰能力强、传输距离远;同时支持多点挂接(半双工)。终端电阻(典型 120Ω)接在总线两端,用于匹配特征阻抗、消除信号反射;注意 RS485 是半双工,收发方向切换需要换向延时(DE/RE 控制)。
为什么说 UART 是全双工?
因为 UART 的 TX 和 RX 是两条独立的线,可以同时发送和接收,互不干扰,属于全双工。相比之下 RS485 虽然基于 UART,但物理层只有一对差分线,同一时刻只能一个方向传输,是半双工——这正好解释了"UART 全双工、RS485 半双工"这个常见考点。
四、校验与可靠性
奇偶校验的原理和局限是什么?
奇校验要求一帧中"1"的个数(含校验位)为奇数,偶校验要求为偶数;发送方计算并填充校验位,接收方重新计算比对,不一致则报错。局限:只能检测奇数个位错误(偶数个位翻转会互相抵消),无法纠错,也不能定位错误位;对噪声引起的多位错误无能为力。要求可靠性时常改用 CRC 校验或帧格式校验(帧头帧尾 + 长度 + 累加和)。
串口接收丢字节的常见原因有哪些?
① 波特率误差过大导致采样错位;② 接收缓冲区溢出(软件未及时取走数据);③ 中断响应不及时(更高优先级中断长时间占用、中断里处理过多,下一字节到达时旧数据还没取走);④ 接收中断被关闭或优先级配置不当;⑤ 缓冲区读写指针竞争(主循环与中断并发访问);⑥ 无流控导致对端发送过快。解决:用环形缓冲区 + DMA/空闲中断、提高接收中断优先级、缩短中断处理、核对波特率。
什么是流控?RTS/CTS 和 XON/XOFF 有什么区别?
流控用于协调收发双方速率,防止接收方处理不过来而丢数据。硬件流控:接收方通过 RTS(请求发送) 告知对端"我能否接收",对端以 CTS(清除发送) 应答,用电平实时控制对端是否可发;软件流控:接收方发送 XON/XOFF 控制字符(0x11/0x13)通知对端暂停/恢复发送。硬件流控实时性好、不占用数据带宽,适合高速;软件流控不占用额外引脚但依赖数据通道,低速可用。
五、接收方案与工程实践
串口接收用中断好还是轮询好?
轮询:主循环不停查询接收标志,实现简单但浪费 CPU、容易漏数据,适合低速、简单场景(如调试打印);中断接收:每收到一字节触发一次中断,及时取走数据、CPU 利用率高,是生产代码的主流做法,配合环形缓冲区把数据暂存、主循环统一处理。要点:中断服务函数要短小(只搬数据、不做解析),避免长时间关中断。
串口接收环形缓冲区如何设计?
环形缓冲区用固定大小数组 + 读指针和写指针实现 FIFO:接收中断把字节写入写指针处并后移,主循环从读指针处取出并后移,指针到末尾回绕到开头(取模)。要点:① 读写指针相等表示空,为区分空/满可牺牲一格(写满时留一格)或加计数;② 中断与主循环共享时,读指针只被主循环改、写指针只被中断改,可免锁;③ 容量按最大突发数据量设计,满了要及时处理或丢弃并置溢出标志。
如何用串口空闲中断(IDLE)接收不定长帧?
空闲中断在接收线上空闲超过一个字节时间(即一帧数据结束后)触发,配合 DMA 接收可收不定长数据:开启 USART 空闲中断 + DMA,DMA 连续把收到的字节写入缓冲区,IDLE 中断触发时从 DMA 计数寄存器读出本次实际收到的长度,解析一帧后重置 DMA 等待下一帧。这种方案不依赖帧头帧尾、不占用 CPU,是 STM32 上收不定长帧(如 AT 指令、Modbus)的标准做法;注意 IDLE 标志需软件清除(先读 SR 再读 DR)。
串口 DMA 接收有什么好处和坑?
好处:CPU 完全不参与字节搬运,适合大批量、连续接收,且配合空闲中断可收不定长帧。坑:① DMA 缓冲区长度要足够,接收超过容量会溢出截断;② 需要在 IDLE 中断里计算实际接收长度(用 DMA 剩余计数减去当前值),否则不知道一帧多长;③ DMA 与中断接收不要同时使能同一通道造成冲突;④ 注意收发共用一个 DMA 通道时的配置与清除。
用逻辑分析仪/示波器怎么判断串口通信是否正常?
抓 TX 波形:空闲应为高电平,一帧应有1 位低电平起始位 + 数据位 + 高电平停止位;用波特率解码功能可直接解出数据,与发送内容比对。若波形一直是低说明 TX 常低(发送端未释放/短路)、无下降沿说明无数据发出、帧长短于/长于 10 位说明数据位/停止位配置或波特率不对。这是排查"收不到数据、乱码"的第一步。

