辉芒微电子应用工程师面经:MCU 与通信时序
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 目前在找哪类工作?职业规划是什么?
- 你的长处和短处是什么?请举具体实例。
- 项目中的 OTA 升级流程是怎样的?(原帖注明问得很细)
- 毕设做的是什么?
- 主要接触过哪些 MCU?
- STM32F103 跑在什么主频上?72M 主频是怎么产生的?
- 72M 主频下取指令要插入多少个等待周期?
- 软件 IO 的翻转频率可以达到多少?
- MCU 低功耗怎么设计?
- IIC、SPI、UART 是用硬件实现还是软件模拟?
- 串口从机用 GPIO 翻转去模拟串口接收数据,应该怎么操作?(主要考察串口时序)
- IIC 时序:几根信号线?开始、结束、应答信号怎么定义?上升沿还是下降沿采样?SDA 的 IO 类型是什么?为什么这样设计?
- SPI:几根信号线?时序是怎样的?怎么通信?
- 自我介绍。
《参考解析》
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 的 2MHz 级别的翻转(具体取决于编译优化等级和是否用位带操作);用库函数 BSRR 寄存器直接置位/复位,一轮翻转最少两条写指令,再算上循环跳转开销,STM32F103(72MHz)上通常能做到 1HAL_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 管断电而不是只发休眠命令。