面灵AI→

辉芒微电子应用工程师面经:MCU 与通信时序

时间
2026-09
来源
牛客网

《面试题目》

  1. 目前在找哪类工作?职业规划是什么?
  2. 你的长处和短处是什么?请举具体实例。
  3. 项目中的 OTA 升级流程是怎样的?(原帖注明问得很细)
  4. 毕设做的是什么?
  5. 主要接触过哪些 MCU?
  6. STM32F103 跑在什么主频上?72M 主频是怎么产生的?
  7. 72M 主频下取指令要插入多少个等待周期?
  8. 软件 IO 的翻转频率可以达到多少?
  9. MCU 低功耗怎么设计?
  10. IIC、SPI、UART 是用硬件实现还是软件模拟?
  11. 串口从机用 GPIO 翻转去模拟串口接收数据,应该怎么操作?(主要考察串口时序)
  12. IIC 时序:几根信号线?开始、结束、应答信号怎么定义?上升沿还是下降沿采样?SDA 的 IO 类型是什么?为什么这样设计?
  13. SPI:几根信号线?时序是怎样的?怎么通信?
  14. 自我介绍。

《参考解析》

STM32F103 的 72MHz 从哪来:F103 的时钟树是「外部晶振 HSE(常见 8MHz)→ 经 PLL 倍频 → 作为 SYSCLK」。8MHz 先经 HSE 分频器(PREDIV1,通常不分频)送入 PLL 的输入,再乘上 PLLMUL 倍频系数 9,得到 72MHz。系统时钟还要分配到各总线:AHB 最大 72MHz,APB1 最高 36MHz(所以挂 APB1 的定时器有 ×2 倍频,实际计时仍是 72MHz),APB2 为 72MHz。如果用的是内部 HSI(8MHz,精度差),同样能倍频到 64MHz 或 72MHz,但串口等对时钟精度敏感的场合通常还是外接晶振。

取指等待周期(Flash latency):F103 的 Flash 访问速度跟不上 72MHz 的 CPU,所以要在 FLASH_ACR 里配置等待周期:024MHz 为 0 个、2448MHz 为 1 个、4872MHz 为 2 个。也就是 72MHz 下要插 2 个等待周期(LATENCY=2),同时使能预取缓冲(Prefetch Buffer)来缓解流水线停顿。软件 IO 翻转频率:用 GPIO 的 BSRR 寄存器直接置位/复位,一轮翻转最少两条写指令,再算上循环跳转开销,STM32F103(72MHz)上通常能做到 12MHz 级别的翻转(具体取决于编译优化等级和是否用位带操作);用库函数 HAL_GPIO_WritePin 会慢很多,可能只有几百 kHz。这也是后面「软件模拟串口」的关键约束。

软件模拟串口从机接收:核心是采样时序。串口空闲为高,起始位是持续一个位时间的低电平;从机最好用外部中断捕获起始位的下降沿,然后延时 1.5 个位时间到起始位中间(避开边沿抖动),再每隔一个位时间采样一次数据位(LSB 先发),依次取 8 位,最后采样停止位并校验是否为高。位时间由波特率决定,例如 9600bps 一位约 104μs。误差来源主要有三:GPIO 中断响应和代码执行带来的固定延迟(必须从下降沿开始计时并扣除已耗时)、主频与定时器精度导致的累积漂移(一帧 10 位累计误差超过半个位时间就会采错)、以及接收期间被其它高优先级中断打断。所以实际工程做法是:用定时器输入捕获/定时中断而不是纯延时、接收期间关掉耗时中断或临时提优先级、优先用硬件 UART,软件模拟只在引脚不够或特殊场景下用;发送方向软件模拟相对容易,接收方向才是难点。

IIC 时序细节:IIC 是两线制——SCL 时钟线 + SDA 数据线,两者都必须外接上拉电阻,因此 SDA/SCL 的 IO 应配置为开漏输出(GPIO_Mode_Out_OD):开漏只能主动拉低、释放后由上拉电阻拉高,这样总线上任意一个从机都能拉低而不会出现「一个推高一个推低」的短路;同时也天然支持总线仲裁和多主机。协议上,SCL 为高时 SDA 由高变低是起始信号,SCL 为高时 SDA 由低变高是停止信号;数据在 SCL 低电平期间变化,在高电平期间被采样(即上升沿之后、高电平中间读稳定值),每个字节 8 位 MSB 先发,第 9 个时钟是应答位——接收方拉低 SDA 表示 ACK,保持高表示 NACK。实践坑点:主机读数据前要发完地址再释放 SDA;时钟拉伸(slave 拉低 SCL 请求等待)需要主机支持;用软件模拟时要注意上拉电阻取值与总线电容决定的上升时间。

SPI 时序与通信方式:SPI 是四线制——SCLK、MOSI(主出从入)、MISO(主入从出)、CS(片选,低有效),全双工、无地址、靠片选选择从机。它由 CPOL(空闲时 SCLK 电平)和 CPHA(在第几个边沿采样)两个参数组合出四种模式:Mode0(CPOL=0, CPHA=0)空闲低电平、第一个边沿(上升沿)采样;Mode1 空闲低、第二个边沿(下降沿)采样;Mode2 空闲高、第一个边沿(下降沿)采样;Mode3 空闲高、第二个边沿(上升沿)采样。主从两端的模式必须一致,否则读到的数据整体错位。数据一般 MSB 先出,移位寄存器按位交换,因此 SPI 的速度可以做得很高(几十 MHz),代价是每多一个从机就多一根片选线,且没有应答机制、无法确认从机是否真的收到。

OTA 与低功耗:OTA 在 MCU 上的标准做法是「双区 + Bootloader」:Flash 分为 Bootloader 区、App 运行区(A 区)和升级备份区(B 区),Bootloader 上电先检查升级标志位;新固件由通信接口(UART/CAN/4G)分包写入 B 区并逐包校验(CRC32 或哈希),全部收齐后校验整包签名和版本号,通过则把标志位切到 B 区并复位,由 Bootloader 完成跳转。要能答出细节:断电续传(记录已写入的偏移与包序号)、写入前先擦除整个扇区、升级失败回滚到 A 区、以及严禁在写 Flash 时直接跳转执行(Flash 写入期间取指会阻塞,需把关键代码搬到 RAM 执行)。低功耗设计的常见手段则包括:按需切换运行/睡眠/停机/待机模式,无任务时进 WFIO/Stop 并靠中断唤醒;关闭不用的外设时钟(RCC_APBxENR),未用引脚配置为模拟输入避免悬空漏电;降低主频和电压、用 DMA 代替 CPU 轮询、把周期任务合并成一次唤醒完成;外部器件用 MOS 管断电而不是只发休眠命令。