嵌入式开发

面试题

Posted by LXG on March 14, 2025

基于stm32F407嵌入式底层驱动开发实践

硬件

什么是 上拉电阻(Pull-up) 和 下拉电阻(Pull-down)?它们的作用是什么?


上拉电阻(Pull-up Resistor) 和 下拉电阻(Pull-down Resistor) 是用于稳定数字电路输入端状态的电子元件,防止输入端悬空(Floating),导致不确定的逻辑状态。

上拉电阻:默认 高电平,防止输入端悬空,常用于 I2C、UART、开漏电路 等。
下拉电阻:默认 低电平,确保输入端稳定,常用于 按键输入、使能信号 等。
内置上拉/下拉:现代 MCU 可通过软件配置内部上拉/下拉,无需外部电阻

什么是 开漏输出(Open Drain) 和 推挽输出(Push-Pull)?它们的应用场景是什么?

特性 开漏输出(Open Drain) 推挽输出(Push-Pull)
能否主动输出高电平 不能(需要外部上拉) (直接输出 VCC)
能否主动输出低电平 能(MOSFET 导通接地) 能(下管导通接地)
是否需要外部上拉电阻 需要 不需要
适用于总线通信 适用于 I2C、信号共享 不适合
适用于高速信号 不适合 适用于 SPI、UART
驱动能力 适合驱动外部大功率负载 适合直接驱动小型负载
功耗 取决于上拉电阻值 较低

如何在 C 代码中实现一个 GPIO 的按键检测,并带去抖动功能?

方法 优点 缺点 适用场景
软件延时去抖动 简单、易实现 HAL_Delay() 影响其他任务 低频按键,单任务应用
定时器+中断去抖动 非阻塞,高可靠 需配置定时器,稍复杂 需要高可靠性、频繁检测

在中断服务程序(ISR)中应该避免哪些操作?

操作 原因
长时间的延时操作 影响系统响应和其他中断处理
动态内存分配(如 malloc/free) 可能导致堆栈溢出或内存碎片,影响系统稳定性
阻塞的 I/O 操作 增加 ISR 执行时间,导致其他中断无法及时响应
修改共享资源而不同步 可能引起数据竞争,导致数据不一致
调用复杂函数(如递归) 可能导致栈溢出和系统不稳定
中断嵌套 增加系统复杂性,可能导致栈溢出或延迟响应
使用浮点运算 运算速度慢,并增加上下文切换的开销
修改中断使能标志 可能导致系统无法响应其他重要中断

什么是 PWM(脉冲宽度调制)?使用场景是什么?


PWM(脉冲宽度调制)是一种通过在固定频率下改变数字信号中高电平持续时间(即脉冲宽度)来调节平均输出功率的技术。通过控制输出信号的占空比(Duty Cycle),可以实现对负载所施加电压或功率的精确控制,而无需使用模拟电路

现代 MCU 通常内置定时器/计数器模块,可配置为 PWM 模式。首先需要设置 PWM 的频率(周期)和计数器模式。设置占空比, 配置好定时器后,将 PWM 信号输出到相应的 GPIO 引脚,连接到 LED、电机或其他负载。

LED 调光:
通过改变 PWM 信号的占空比,可以控制 LED 的亮度。占空比越高,LED 亮度越高;占空比低时,LED 亮度降低。

电机速度控制:
在直流电机控制中,PWM 用于调整电机的平均输入电压,从而实现调速。较高的占空比可使电机转速更快,而较低的占空比则使电机转速降低。

音频信号生成:
通过快速切换 PWM 信号,可以生成音频波形。常用于数字音频输出和音调控制。

电源管理:
在开关电源(SMPS)中,PWM 用于调节输出电压和电流,通过控制开关管的导通时间来实现高效能量转换。

伺服控制:
一些伺服电机控制需要通过 PWM 信号来设定精确的位置和角度。

介绍下STM32的看门狗用法


独立看门狗(IWDG, Independent Watchdog)

IWDG 基于低速内部振荡器(LSI),独立于系统主时钟运行,因此即使系统主时钟出问题或软件异常导致主程序挂起,IWDG 仍能正常工作并复位系统。

窗口看门狗(WWDG, Window Watchdog)

WWDG 是基于系统时钟的看门狗,与 IWDG 不同,WWDG 提供一个“刷新窗口”概念。也就是说,只有在特定的时间窗口内刷新计数器才是有效的,过早或过晚刷新都会被认为异常,从而触发复位。

什么是 SRAM(静态 RAM) 和 DRAM(动态 RAM)?它们的区别是什么?

特性 SRAM(静态 RAM) DRAM / SDRAM(动态 RAM)
存储原理 采用触发器电路存储数据,无需刷新 采用电容存储数据,需要周期性刷新
集成情况 集成在 STM32 内部,用于运行时数据存储 通常作为外部存储器,通过 FMC 接口扩展
速度与延时 速度快、延时低 速度较慢、延时略高(但适用于大容量存储)
功耗 静态功耗较高(因持续维持触发器状态) 单位存储功耗较低,但刷新操作会增加一定功耗
容量与成本 面积大、容量有限、成本较高 面积小、密度高、成本低,适合需要大容量的场合
用途 用于高速缓存、堆、栈等对速度要求高的数据存储 用于扩展内存,如图像缓冲区、大数据处理、存储大容量数据

I2C、SPI 和 UART 的主要区别是什么?

特性 I2C SPI UART
通信方式 同步串行通信(使用时钟信号同步数据传输) 同步串行通信(使用时钟信号同步数据传输) 异步串行通信(不使用时钟信号同步数据传输)
总线拓扑 支持多主机和多个从设备,通过设备地址区分 支持一主多从模式,每个设备通过片选信号区分 点对点通信,支持单一发送和接收设备
数据传输速率 较低,通常为 100 kbps 到 400 kbps(高频模式可达 1 Mbps) 较高,通常为几 Mbps,甚至可达到 10 Mbps 较低,通常为 9600 bps 到 115200 bps
通信引脚数 需要 2 根线:SDA(数据线)、SCL(时钟线) 需要 4 根线:MISO(主入从出)、MOSI(主出从入)、SCK(时钟线)、CS(片选线) 需要 2 根线:TX(发送)、RX(接收)
设备数量 支持多主机和多个从设备(最多 128 个设备) 支持一主多从模式,但每个设备需要一个独立的片选线 仅支持点对点通信,即一对一的通信
数据传输方式 按字节传输数据,每个设备都有唯一的地址 按字节传输数据,通常是全双工通信 按字节传输数据,通常是半双工通信
复杂性 中等,支持设备地址和多设备通信 较简单,但需要更多的引脚 简单,易于实现,但仅支持一对一通信
通信协议支持 使用地址区分设备,协议较复杂 不使用地址区分设备,需要额外的片选信号 不涉及设备地址,只有发送和接收数据的功能
应用场景 适合多个低速设备、低功耗的应用(如传感器) 适合高速、全双工通信的应用(如存储器、显示器) 适合点对点通信(如串行终端、调制解调器等)

对比 CAN 总线 和 RS485

特性 CAN 总线 RS-485 总线
通信类型 串行通信协议,采用差分信号 串行通信协议,采用差分信号
数据传输速率 最大 1 Mbps 最大 10 Mbps(通常为较低速,如 115200 bps 或更低)
传输距离 最大 40 米(1 Mbps),最大 1 公里(低速) 最长可达 1200 米(较低速时,较远距离)
设备连接数 支持多主机和多从机(最多 128 个设备) 通常支持一主多从(最多 32 或 128 个设备,取决于驱动能力)
错误检测与容错能力 具有强大的错误检测和自修复能力(CRC 校验、帧校验等) 错误检测能力较弱,通常不具备自动重试功能
拓扑结构 采用总线型拓扑,支持多点通信(多主多从) 支持多点通信,通常采用总线型拓扑或星型拓扑(但不支持多主)
协议复杂度 协议复杂,支持优先级、消息过滤、实时性要求等 协议简单,不支持消息优先级,仅基于简单的点对点通信
抗干扰能力 高抗干扰能力,使用差分信号,可在电磁干扰强的环境中工作 具有一定的抗干扰能力,但不如 CAN,总线负载过重时可能影响稳定性
通信方式 支持多主机和从机通信,支持实时性与优先级控制 支持半双工通信,通常为点对点通信或一主多从通信
应用场景 汽车、工业自动化、机器人、医疗设备等实时性要求较高的系统 工业控制、楼宇自动化、远程控制、数据采集等
成本 较高,因协议复杂且需专用硬件支持 较低,RS-485 协议简单,易于实现和使用

在嵌入式系统中,如何处理 堆栈溢出(Stack Overflow)?


1. 增大堆栈空间。
2. 采用堆栈溢出检测机制(硬件或软件)。
3. 使用静态分析工具来检测潜在问题。
4. 优化程序,减少堆栈的使用,如避免深度递归。
5. 启用堆栈保护(如 Stack Canary 或硬件堆栈保护)。
6. 使用 RTOS 提供的堆栈管理功能。

如何使用 示波器 或 逻辑分析仪 进行嵌入式系统调试?

特点 示波器 逻辑分析仪
信号类型 模拟信号、数字信号(PWM、时钟信号等) 数字信号、协议数据流(I2C、SPI、UART等)
波形显示 显示电压随时间变化的波形 显示多个数字信号的时序关系
应用场景 信号完整性、电源噪声、PWM、时钟等 多通道数字信号分析、串行通信协议调试
触发功能 支持复杂的触发条件(边沿、幅度等) 支持协议特定的触发(如I2C的起始位、停止位)
调试速度 适合观察信号的波形、频率、幅度变化 适合捕捉和分析快速变化的数字信号
通道数量 通常为2-4通道 通常为8通道、16通道或更多
数据采集方式 连续采样信号,捕捉瞬时波形 捕捉多个数字信号的时序数据
解析功能 可以进行频率、幅度、时序等测量 解析并显示协议中的数据、命令、状态
精度 高时间精度,适合测量高频信号 高并行度,适合分析多信号的时序问题

在嵌入式系统中,如何检测 内存泄漏?


手动代码审查和内存分配/释放配对。
使用内存池管理内存。
利用内存泄漏检测工具(如 Valgrind、MemTool等)。
采用静态分析、动态分析和硬件调试工具。

RTOS

FreeRTOS

什么是RTOS? RTOS = Real Time Operating System,实时操作系统。

学嵌入式的路程,基本上是:裸奔-RTOS-LINUX。

FreeRTOS 是一款市场领先的嵌入式系统, RTOS 支持 40 多种处理器架构,内存占用小,执行时间快,具有尖端的 RTOS 功能和库,包括对称多处理 (SMP)、具有 IPv6 支持的线程安全 TCP 堆栈以及与云服务的无缝集成。它是开源的,并得到了积极的支持和维护。

特性 FreeRTOS 嵌入式Linux
类型 实时操作系统 (RTOS) 通用操作系统(通常是 Linux 发行版)
目标应用 适用于低功耗、资源受限的嵌入式设备(如微控制器、传感器) 适用于功能丰富、资源较多的嵌入式设备(如智能家居、路由器、平板电脑)
资源需求 轻量级,适合资源有限的设备(如 RAM 和存储都很小的微控制器) 需要较多的计算资源(内存、存储、处理能力)
实时性 强实时性,适合对时间敏感的任务 非实时操作系统,通常延迟较高,但可以通过实时补丁(如 PREEMPT-RT)实现实时性
任务管理 支持多任务调度、优先级控制、时间片轮转 支持多任务调度、优先级控制,通常使用抢占式调度
内存管理 简单的内存分配机制,通常手动管理内存(如内存池) 完整的内存管理,支持分页、虚拟内存,内存由操作系统动态管理
中断管理 支持中断服务例程(ISR),可以在 ISR 中调度任务 支持中断管理,但不能像 FreeRTOS 那样直接在 ISR 中调度任务
文件系统 通常不包含文件系统,或仅支持简单文件系统(如 FAT16、FAT32) 支持多种文件系统(如 ext4、FAT、NTFS、exFAT)
网络支持 可以集成简化的网络协议栈(如 lwIP) 内置完整的网络协议栈,支持 TCP/IP、UDP、HTTP 等多种协议
多核支持 基本支持多核,但大多数实现仅支持单核系统 完全支持多核,Linux 内核可以在多个核心上并行调度任务
调度方式 基于优先级的抢占式调度,适合实时任务的调度 完全抢占式调度,支持更复杂的调度策略(如 CFS、实时调度)
硬件支持 支持多种嵌入式硬件,但通常需要手动移植和配置驱动 提供广泛的硬件支持,拥有众多现成的设备驱动程序和内核模块
驱动支持 通常需要手动编写和移植硬件驱动 提供广泛的硬件驱动支持,支持各种外设(如 SPI、I2C、USB 等)
开源性 完全开源(MIT 许可证) 完全开源(GPL 许可证)
文件操作 不支持或仅支持非常简单的文件操作 完整的文件操作支持,具有强大的文件系统接口和 API
开发环境 通常使用简单的 IDE(如 Eclipse、Keil)与交叉编译工具 使用完整的开发环境(如 Yocto、Buildroot)与交叉编译工具
启动时间 启动时间非常快,适合快速响应的系统 启动时间相对较长,适合较为复杂的系统
调试工具 适用嵌入式调试工具(如 GDB) 提供强大的调试工具(如 GDB、strace、perf、ftrace 等)
社区和支持 拥有活跃的嵌入式开发社区和文档 拥有大型的全球社区和丰富的文档支持