嵌入式软件工程师_面试题练习_01
一、C语言
1、嵌入式开发中,#define 宏定义和 const 常量有什么区别?分别适合什么场景?
2、简述指针在单片机开发里的常用场景,举 1-2 个实际例子。
- 操作寄存器:如*(volatile uint32_t*)0x40010800 = 0x01;(直接向 GPIOA 地址写值);
- 函数传参:通过指针修改外部变量(如void UART_Receive(uint8_t* data)接收串口数据到外部数组)。
3、位运算 &、|、^ 在操作寄存器时分别有什么作用?举例说明如何用位运算单独置位某一 IO 口。
- 假设 GPIOA 的 ODR 寄存器地址为0x4001080C,要将第 5 位置 1(输出高电平):(volatile uint32_t)0x4001080C |= (1 << 5);(用|置位,不影响其他位);
- 置 0:(volatile uint32_t)0x4001080C &= ~(1 << 5);(用&~清零);
- 取反:(volatile uint32_t)0x4001080C ^= (1 << 5);(用^切换电平)。
4、结构体在嵌入式工程中一般用来做什么?说说结构体对齐简单概念。
5、嵌入式代码里为什么常看到 volatile 关键字?它的作用是什么?
二、STM32基础外设
1、STM32 GPIO 八种工作模式分别是什么?每种简单适用场景,举出 3 个常用模式举例。
2、按键软硬件消抖原理分别是什么?单片机里软件消抖常用什么思路?
输入模式(4 种)
1.浮空输入
场景:外接上拉 / 下拉电阻的按键、外部中断信号(如红外接收、编码器 A/B 相)。
常用度:中等。因为需要外部电阻配合,但灵活性高,适合对功耗不敏感的场景。
2.上拉输入
场景:无外部上拉电阻的按键、检测外部设备是否连接(如传感器默认高电平,连接后拉低)。
常用度:高。内置上拉电阻节省外部元件,是按键检测的首选模式。
3.下拉输入
场景:无外部下拉电阻的信号检测(如外部设备正常工作时输出高电平,故障时拉低)。
常用度:中低。使用场景比上拉输入少,因为多数外设默认空闲状态为高电平(如 TTL 信号)。
4.模拟输入
场景:ADC 采集(如电压、温度传感器)、DAC 输出反馈(部分型号)。
常用度:高。ADC 必须用此模式,而模拟传感器是嵌入式系统的常见需求。
输出模式(4 种)
1.推挽输出
场景:LED 驱动、继电器控制、TTL 电平通信(如与 51 单片机、USB 转 TTL 模块通信)。
常用度:极高。能输出高电平(VCC)和低电平(GND),驱动能力强(可直接驱动小功率 LED),是最常用的输出模式。
2.开漏输出
场景:I2C 通信(SDA/SCL 引脚,需外部上拉电阻实现 “线与”)、多设备电平匹配(如 3.3V 单片机驱动 5V 外设,通过上拉电阻到 5V)。
常用度:高。I2C 协议是嵌入式系统的常用通信方式,开漏输出是其必要条件。
3.复用推挽输出
场景:USART 串口(TX 引脚,如 STM32 的 PA9 作为 USART1_TX)、SPI 通信(MOSI 引脚)、定时器 PWM 输出(如电机驱动、LED 调光)。
常用度:极高。外设的数字信号输出几乎都用复用推挽,比如串口通信、PWM 是项目核心功能。
4.复用开漏输出
场景:很少单独使用,极端情况如 “USART 串口在 I2C-like 多机通信中,需实现总线竞争时的电平拉低”(实际几乎不用)。
常用度:极低。因为多数外设(USART、SPI)需要高电平驱动能力,复用推挽已满足需求,开漏的复用模式显得冗余。
总结:
最常用的 5 种:上拉输入(按键)、模拟输入(ADC)、推挽输出(LED)、开漏输出(I2C)、复用推挽输出(串口、PWM)。原因是这些模式覆盖了 “数字输入检测、模拟信号采集、通用数字输出、总线通信、外设信号输出” 等核心需求。
较少用的 3 种:浮空输入(需外部电阻)、下拉输入(场景有限)、复用开漏输出(外设几乎不需要)。主要因为它们要么增加硬件成本,要么适用场景狭窄,可被其他模式替代。
三、通信协议
1、简述 UART 串口异步通信原理,起始位、停止位、校验位作用;
2、I2C 总线线与原理,为什么只能开漏 + 上拉,寻址机制简单说明;
3、SPI 四种时钟极性 CPOL、相位 CPHA 区别,简述主从通信流程;
4、ADC 模拟输入为什么不能用浮空 / 推挽模式,单次转换和连续转换区别;
5、项目中 UART、I2C、SPI 分别适合什么外设,举例选型。
- UART:适合远距离、低速率通信,如 GPS 模块、蓝牙模块(HC-05)。
- I2C:适合多设备、短距离通信,如 OLED 显示屏(SSD1306)、温湿度传感器(SHT30,DHT11 实际是单总线)。
- SPI:适合高速率、全双工通信,如 SD 卡、LCD 触摸屏(ILI9341)、ADC 芯片(ADS1256)。
补充:
- “线与” 其实是电路里的一种连接逻辑。简单说,就是把多个设备的 I2C 数据线或时钟线直接连在一起,形成一条公共总线。这时候,只要总线上有一个设备输出低电平,整条总线就会被拉成低电平;只有当所有设备都输出高阻态时,总线才会被上拉电阻拉成高电平。这种 “多个设备共同控制总线电平,低电平优先” 的机制,就是 I2C 的线与原理。而开漏输出 + 上拉电阻正是为了实现这个逻辑。如果用推挽输出,当一个设备输出低电平,另一个输出高电平时,就会形成短路,损坏芯片。开漏输出只能拉低电平,无法主动输出高电平,高电平需要靠外部上拉电阻实现,这样就避免了短路问题,完美支持多设备线与连接。
- 寻址机制方面,I2C 通信时,主机先发送一个 7 位的从机地址,紧接着是 1 位读写位。总线上所有从机都会接收这个地址,并与自己的地址进行比较。如果地址匹配,该从机就会发送一个应答信号给主机,之后主机和这个被选中的从机就可以进行数据传输了。
- 高阻态可以理解成引脚 “悬空” 的状态。这时候引脚既不输出高电平,也不输出低电平,相当于和芯片内部的电路断开了连接,对外呈现出非常高的电阻。在 I2C 总线里,当设备不需要控制总线电平时,就会让引脚进入高阻态,这时候总线电平就由上拉电阻来决定了。
- “开漏输出” 里的 “漏” 指的是 MOS 管的漏极。开漏输出的电路结构,简单说就是芯片内部的驱动管是 N 沟道 MOS 管,这个 MOS 管的漏极直接接到芯片引脚,源极接地,而漏极没有直接接电源。当要输出低电平时,MOS 管导通,引脚通过导通的 MOS 管接地,呈现低电平;当要输出高电平时,MOS 管截止,引脚就相当于悬空(高阻态),这时候需要外部接一个上拉电阻到电源,引脚才能通过上拉电阻获得高电平。因为输出结构中 MOS 管的漏极是 “开路” 的(没有直接连电源),所以叫开漏输出。
- SPI 是串行外设接口,比 I2C 快,常用 4 根线:SCK(时钟线,主机发)、MOSI(主机输出从机输入)、MISO(主机输入从机输出)、SS(片选线,主机选从机,低电平有效)。四种模式由 CPOL 和 CPHA 决定:CPOL 是时钟空闲电平,0 为低,1 为高;CPHA 是数据采样时刻,0 在 SCK 第一个边沿采样,1 在第二个边沿采样。比如模式 0(CPOL=0,CPHA=0):空闲时 SCK 低,主机在 SCK 上升沿发送数据,从机在上升沿采样;下降沿时从机发送数据,主机采样。主从通讯流程:主机拉低目标从机的 SS 线选中它;然后通过 SCK 发送时钟,同时在 MOSI 上发送数据,从机通过 MISO 返回数据;通讯结束,主机拉高 SS 线释放从机。
四、裸机架构与调试
1、简述轮询、中断两种裸机程序架构优缺点,什么场景选轮询、什么场景用中断?
- 轮询:优点→逻辑简单、无中断嵌套 / 临界区问题、调试方便;缺点→空耗 CPU,实时性差。
- 中断:优点→CPU 空闲时做别的任务,事件来了才处理,实时性强;缺点→中断嵌套、临界资源冲突、代码调试难度大。
2、裸机里状态机编程是什么?简单举例用状态机处理按键长按 / 短按。
3、串口作为调试口在裸机项目有哪 4 种常用调试用法?
- 打印变量、日志,追踪程序运行流程;
- 上位机下发指令控制单片机外设;
- 上报传感器采集数据,验证采样正确性;
- 崩溃打印出错信息,定位死机 BUG。
4、裸机常见硬件 BUG:引脚配置错误、电源不稳、晶振不起振,分别排查思路?
- 引脚配置错:核对寄存器、CubeMX 配置、原理图引脚,万用表测引脚电平;
- 电源不稳:万用表测 VCC 空载 / 带载电压,查滤波电容、负载短路;
- 晶振不起振:示波器测晶振引脚波形、起振电容参数、芯片晶振配置。
5、同一个工程里混用轮询 + 中断架构会出现什么隐患?如何规避?
- 共享数据加临界区(进入轮询处理共享数据前关中断,处理完开中断);
- 中断函数精简,只做数据标记,复杂处理丢到主循环轮询;
五、FreeRTOS
1、什么是 RTOS?对比裸机程序,RTOS 最大优势是什么?简述任务的概念,以及任务三态 / 五态分别是什么?
2、RTOS 中队列 (消息队列) 的作用是什么?一般用在什么场景?和全局变量传数据相比,队列有哪些优点?
- 自带数据缓冲,不会因为读写冲突丢失数据;
- 自带同步机制,配合阻塞等待,CPU 利用率更高;
- 数据拷贝传递,多任务访问安全,无需频繁手动加临界区;
- 支持定长数据、队列满 / 空阻塞策略。
3、什么是二值信号量、计数信号量?各自典型应用场景举例。
- 本质:取值只有 0 和 1,相当于一把 “互斥锁 / 同步标记”。
- 场景:任务同步、中断与任务同步(最常用:串口中断接收数据,用二值信号量唤醒处理任务)。
- 本质:计数值可大于 1,支持多个资源、多次触发。
- 场景:资源计数、事件计数,例如多个外设共享资源、统计脉冲次数、限流控制。
4、简单说下 RTOS 里任务优先级的作用,高优先级任务、低优先级任务、同优先级任务的调度规则?
5、裸机和 RTOS 开发思路有什么核心区别?项目中什么时候推荐用 RTOS,什么时候继续用裸机?
- 用裸机:功能简单、任务少、逻辑简单、成本敏感、无高实时要求;
- 用RTOS:功能复杂、多业务并发、高实时性要求、大量延时 / 等待类逻辑、代码需要模块化拆分。
六、IOT
1、简述 ESP32 相比传统 STM32 单片机,核心优势是什么?日常项目中它主要适用哪些场景?
- 硬件层面:ESP32 是双核 32 位处理器(传统 STM32 多为单核),自带更大 RAM(520KB+),能支撑更复杂的联网协议栈(如 MQTT、HTTP)。
- 软件层面:官方 SDK 集成了完整的 WiFi / 蓝牙驱动、LwIP 协议栈,开发联网功能更高效。
- 适用场景补充:智能家居,还常用于环境监测终端(温湿度上传)、工业传感器联网、远程控制设备(如智能开关)。
2、ESP32 的 WiFi 两种工作模式:Station (站点)、SoftAP (软路由) 分别是什么?各自常用场景举例。
- Station 模式:ESP32 作为 “客户端”,连接外部 WiFi 热点(如家里的路由器),从而接入互联网。
- SoftAP 模式:ESP32 自身作为 “WiFi 热点”,让其他设备连接自己,形成局域网。
3、简单说明 TCP 协议特点,为什么网络传输优先选用 TCP 而不是普通 UDP?
- 面向连接:通信前需 “三次握手” 建立连接,结束后 “四次挥手” 断开。
- 可靠传输:通过校验和、重传机制、流量控制、拥塞控制,确保数据无差错、按序到达。
- UDP 无连接、不可靠(丢包不重传),适合实时性要求极高但可容忍丢包的场景(如语音通话、视频流)。
- IoT 设备通常传输控制指令、传感器数据,要求数据准确(如 “开灯” 指令不能丢),因此优先用 TCP。
4、简述 ESP32 实现 WiFi 联网 + TCP 客户端的大致执行流程。
- 初始化 WiFi:配置为 Station 模式,设置要连接的 WiFi 名称(SSID)和密码。
- 连接 WiFi:调用 SDK 接口(如esp_wifi_connect()),等待连接成功(获取 IP 地址)。
- 创建 TCP 客户端:基于 LwIP 协议栈,创建 socket,指定服务器 IP 地址和端口号。
- 连接 TCP 服务器:调用connect()接口,与服务器建立 TCP 连接。
- 数据收发:通过send()发送数据,recv()接收服务器数据;通信结束后关闭 socket。
5、IoT 设备联网常见会遇到哪些问题?说出 2 个,并简单说排查思路。
