嵌入式软件开发面试题汇总
介绍跟嵌入式软件开发相关的面试题
目录
🕕ARM 通用寄存器中 3 个特殊寄存器的名字和作用是什么?
🕜软件中断与硬件中断的区别是什么?ARM 提供的软件中断指令是什么?
🕡U-Boot 中 bootcmd 和 bootargs 分别有什么作用?
🕢vmlinux、Image、zImage、uImage 的区别是什么?
🕣Linux 内核中 Makefile、Kconfig、.config 的关系是什么?
🕛FreeRTOS 中任务的优先级如何设置?可以设置多少级?每级优先级的含义?
🕝什么是可剥夺型内核(Preemptive Kernel)?适用场景是什么?
🕞什么是不可剥夺型内核(Non-preemptive Kernel)?适用场景是什么?
🕥在 FreeRTOS 中,互斥量(Mutex)和信号量(Semaphore)的区别?
🕐什么是可重入函数(Reentrant Function)?
🕕操作系统(如 Linux)中进程的状态有哪些?FreeRTOS 中任务的状态有哪些?
🕘什么是 UART?它是如何进行通信的?UART 的工作原理及其数据包结构是怎样的?
🕧说一下 STM32 中的中断?为什么需要中断,有哪些中断,大概怎么做?
🕐STM32 中定时器(Timer)的类型、主要功能、使用场景及配置方法?
🕑GPIO是什么,STM32 中 GPIO 的输入输出模式分类及其适用场景?
🕓什么是 PWM?请简述其工作原理、生成方式以及常见应用场景?
🕐MQTT(Message Queuing Telemetry Transport)怎么保证传输效率?
🕐什么是字节对齐?有什么作用?
指在内存中存储数据时,按照特定规则对齐数据地址。
它的目的是提高内存访问效率,避免 CPU 在访问数据时跨越多个内存单元。
🕑列举 ARM 处理器的主要特点?
低功耗、节能:非常适合电池供电设备,如手机、平板等。
RISC架构:采用精简指令集,执行效率高,硬件设计简洁。(RISC:Reduced Instruction Set Computer RISC)
高集成度:集成度高,可嵌入多个外设模块,适合 SoC 设计。
可授权架构:ARM 公司授权 IP,厂商可自主定制 CPU 内核。
良好的生态支持:拥有成熟的编译器、工具链、操作系统支持(如 Linux、Android)。
🕒ARM 有多少个寄存器?
ARM 通常提供 37 个寄存器,其中 31 个为通用寄存器(含用户模式和异常模式下的别名),以及 6 个状态寄存器。在正常执行中,程序员最常接触的是前 16 个通用寄存器(R0–R15)和一个程序状态寄存器 CPSR,其余用于异常处理和模式切换。
🕓ARM 处理器的 7 种工作模式分别是什么?
1.用户模式(USR):正常程序执行模式,不能直接切换到其他模式
2.系统模式(SYS):运行操作系统的特权任务,与用户模式类似,但具有可以直接切换到其他模式等特权
3.快中断模式(FIQ):支持高速数据传输及通道处理,FIQ异常响应时进入此模式
4.中断模式(IRQ):用于通用中断处理,IRQ异常响应时进入此模式
5.管理模式(SVC):操作系统保护模式,系统复位和软件中断响应时进入此模式(由系统调用执行软中断SWI命令触发)
6.中止模式(ABT):用于支持虚拟内存和/或存储器保护,在ARM7TDMI没有大用处
7.未定义模式(UND):支持硬件协处理器的软件仿真,未定义指令异常响应时进入此模式
🕔ARM 内核和 ARM SoC 处理器的异同是什么?
ARM 内核(Core)是指 CPU 的处理核心本身,负责指令执行、寄存器操作和基本运算;
而 ARM SoC 是基于 ARM 内核构建的完整系统芯片,除了 CPU 核心外还集成了内存控制器、图形处理器、I/O 接口等多个模块。
🕕ARM 通用寄存器中 3 个特殊寄存器的名字和作用是什么?
R13 - SP(Stack Pointer)栈指针
指向当前栈顶地址,管理函数调用过程中的局部变量、返回地址、参数压栈等。R14 - LR(Link Register)链接寄存器
保存函数调用返回地址,BL
(Branch with Link)指令会把返回地址保存在 LR 中,供返回时使用。R15 - PC(Program Counter)程序计数器
指向当前正在执行的指令地址。ARM 中由于流水线,PC
实际值可能略超前当前执行指令地址(通常+8字节偏移)。
🕖描述 CPSR 寄存器中相关 Bit 的含义和作用?
CPSR(Current Program Status Register)是 ARM 中用于记录程序当前状态的寄存器。
它包含条件位(指令进行算术运算后的结果是否有进位,借位等),I位(IRQ异常允许位),F位(FIQ异常允许位),T位(ARM/Thumb工作状态),M位(处理器工作模式)。
🕗什么是立即数?使用时的注意要点是什么?
在 ARM 指令集中,立即数是指直接写入指令中的常数值,用于操作数或寻址。
使用时需注意两点:
(1)立即数前要加
#
号表示常量(如MOV R0, #5
);(2)ARM 指令是 32 位长度,其中用于立即数的字段为 12 位:8 位表示有效数值(基数 B)+ 4 位表示右旋次数 M,最终立即数等于 B 循环右移 M×2 位组成一个 32 位值。
由于这种编码方式限制了立即数的表示范围,因此并不能表示任意数值,使用时需判断是否为合法立即数。
🕘什么是处理器现场?如何保存现场?
处理器现场是指进程在被中断打断时刻的各种寄存器的值。
保存现场的核心是将这些信息压到内核栈,中断结束时再恢复这些信息。
🕙什么是满堆栈和空堆栈?
满堆栈(Full Stack)指栈顶指针指向当前已使用的栈顶位置,入栈前需要先移动指针再写入数据;
空堆栈(Empty Stack)则指栈顶指针始终指向下一个可用的空位置,入栈时直接写入当前指针位置的数据,然后更新指针。
🕚什么是满递减栈、空递减栈、满递增栈、空递增栈?
这些是栈的组织方式,区别在于栈顶指针的位置语义(满 or 空)和栈增长方向(递增 or 递减)。
“满”表示栈顶指针指向当前栈顶数据,
“空”表示栈顶指向下一个空位;
“递增”表示入栈时地址从低地址向高地址增长,
“递减”则表示地址从高地址向低地址增长。
满递减栈(Full Descending Stack) ← ARM 默认
栈顶指向当前元素
新元素入栈:指针先减,数据写入低地址
栈从高地址向低地址增长
常用于嵌入式处理器(如 ARM)
空递减栈(Empty Descending Stack)
栈顶指向空地址
新元素入栈:数据写入当前地址,然后指针减
也从高地址向低地址增长
满递增栈(Full Ascending Stack)
栈顶指向当前元素
新元素入栈:指针先加,数据写入高地址
栈从低地址向高地址增长
空递增栈(Empty Ascending Stack)
栈顶指向空地址
新元素入栈:数据写入当前地址,然后指针加
🕛ATPCS 规定的参数传递规则是什么?
ATPCS(ARM Procedure Call Standard)是 ARM 平台上的函数调用约定,规定了函数参数和返回值的传递方式。
一般来说,当参数个数不超过4个时,使用r0~r3这4个寄存器来传递参数;如果参数个数超过4个,剩余的参数通过数据栈来传递。
🕜软件中断与硬件中断的区别是什么?ARM 提供的软件中断指令是什么?
硬件中断是由外部硬件设备发起的中断信号,处理器响应后暂停当前程序执行,进入中断服务程序;
软件中断是程序内部通过指令主动触发的一种中断,通常用于系统调用或异常处理。
ARM 中触发软件中断的指令是
SWI
(Software Interrupt),现在新版本也用SVC
(Supervisor Call)。
🕝什么是异常?
由于内部或者外部的一些事件 , 导致处理器停下正在处理的工作, 转而去处理这些发生的事;当遇到异常的时候, 先将处理器状态保存起来, 以便执行完异常处理程序后, 可以恢复处理器状态, 继续执行异常出现点下面的代码;
在一个时间点可以出现 多个异常;当异常发生的时候, 程序被强行从一个固定的内存地址执行, 每个种类的异常都有对应的一固定内存地址, 这个内存地址就是异常向量;
🕞ARM 架构支持的七种异常类型是什么?
1).Reset : 处理器在工作时, 突然按下重启键, 就会触发该异常;
2).Undefined instructions : 处理器无法识别指令的异常, 处理器执行的指令是有规范的, 如果尝试执行不符合要求的指令, 就会进入到该异常指令对应的地址中;
3).Software interrupt (SWI) : 软中断, 软件中需要去打断处理器工作, 可以使用软中断来执行 ;
4).Prefetch Abort (instruction fetch memory abort) : 预取指令失败, ARM 在执行指令的过程中, 要先去预取指令准备执行, 如果预取指令失败, 就会产生该异常;
5).Data Abort (data access memory abort) : 读取数据失败;
6).IRQ (interrupt) : 普通中断;
7).FIQ (fast interrupt) : 快速中断, 快速中断要比普通中断响应速度要快一些;
🕟boot loader 的主要作用是什么?
Boot Loader 是系统上电启动后运行的第一个软件程序,它的主要作用是完成硬件初始化、加载操作系统内核并将控制权移交给内核。
🕠U-Boot 是如何启动内核的?
uboot启动内核分为两个步骤:第一步是将内核镜像从启动介质中加载到DDR中,第二步是去DDR中启动内核镜像。
🕡U-Boot 中 bootcmd 和 bootargs 分别有什么作用?
在 U-Boot 中,
bootcmd
表示启动时自动执行的命令序列,通常用来加载内核和设备树并启动系统;而
bootargs
是传递给内核的启动参数,比如根文件系统路径、控制台设置等,内核会根据这些参数完成初始化配置。
🕢vmlinux、Image、zImage、uImage 的区别是什么?
vmlinux
是编译后未压缩、带符号的可执行内核文件,主要用于调试;
Image
是去掉调试信息后的裸内核镜像;
zImage
是对Image
进行压缩后的版本,便于嵌入式设备使用;
uImage
则是在zImage
基础上添加 U-Boot 头部,供 U-Boot 引导时识别使用。
🕣Linux 内核中 Makefile、Kconfig、.config 的关系是什么?
在 Linux 内核中,
Kconfig
定义内核配置选项及其依赖关系,用户通过配置工具(如menuconfig
)选择需要的功能后生成.config
文件,该文件保存所有配置结果;
Makefile
根据.config
中的选项控制编译流程,决定哪些模块被编译、如何编译。
🕤简述 Linux 内核的总体启动流程。
Linux 内核的启动流程通常包括:
处理器上电后运行 Bootloader(如 U-Boot),它完成硬件初始化并加载内核镜像与启动参数,随后跳转到内核入口函数。
内核从压缩镜像中解压自身,初始化中断、内存管理、设备驱动、文件系统等,最终挂载根文件系统并启动用户空间的第一个进程(通常是
init
或systemd
),至此完成系统启动。
🕥简述 Linux 开发板的启动过程。
首先,上电后执行 BootROM(固化在芯片中的初级引导程序),它加载并启动 BootLoader(如 U-Boot);
BootLoader 初始化基本硬件,加载内核镜像、设备树和启动参数;
然后控制权转交给 Linux 内核,内核完成系统初始化并挂载根文件系统,启动用户空间程序(如
init
或systemd
),最终进入系统正常运行状态。
🕦Linux 中字符设备和块设备的主要区别是什么?
字符设备是以字节为单位进行顺序读写的设备,如串口、GPIO;
块设备以块(通常是 512 字节或更大)为单位进行随机访问读写,如硬盘、SD 卡等。
字符设备不经过缓存,操作简单;
块设备通常通过页缓存管理,可支持更高效的数据访问和文件系统操作。
🕧为什么开发板一般不需要静态库?
开发板资源有限,为了节省存储空间和内存,一般不使用体积较大的静态库,而使用动态库可以实现多个程序共享一份代码,减少冗余;
此外,动态库易于更新维护,无需重新编译所有程序。
而静态库在每个程序中都会重复打包,浪费资源,不适合嵌入式设备的轻量化需求。
🕐Linux 有哪几种驱动类型?
字符设备驱动(Character Device Driver)
按字节流读写设备
典型设备:串口、GPIO、I2C、传感器等
通过
cdev
注册,使用read
/write
等系统调用接口块设备驱动(Block Device Driver)
按块(如512字节)读写,可随机访问
典型设备:SD卡、eMMC、硬盘
支持文件系统挂载
网络设备驱动(Network Device Driver)
管理网络接口卡(NIC),处理数据包的收发
提供
net_device
接口,供 TCP/IP 协议栈使用如以太网驱动、WiFi 驱动
平台驱动(Platform Driver)
配合设备树或 ACPI 进行 SoC 内部设备的管理
通常用于片上资源(如 SPI、I2C 控制器)
总线驱动(Bus Driver)
管理设备与驱动的匹配与注册,如 I2C、SPI、PCI、USB 总线
通常配合子设备(设备树)进行匹配
中断驱动(Interrupt Handler/Driver)
响应外设产生的中断,完成事件驱动处理
应用场景:按键输入、数据就绪等
电源管理驱动(PM Driver)
处理设备休眠、唤醒、功耗调节
用于低功耗场景,节能优化
输入设备驱动(Input Driver)
管理输入事件,如触摸屏、键盘、鼠标
与 Linux 输入子系统结合,生成标准事件上报接口
🕑Linux 中编写一个字符设备驱动程序的基本步骤?
1. 分配/注册设备号
使用
register_chrdev_region()
或alloc_chrdev_region()
注册主设备号和次设备号。✅ 2. 初始化并添加 cdev 结构体使用
cdev_init()
初始化字符设备结构,并通过cdev_add()
添加到内核。3. 实现并注册 file_operations 结构体
定义并实现
open
、read
、write
、release
等接口函数,用于处理用户空间请求。4. 创建设备节点(可选)
使用
class_create()
和device_create()
在/dev
下创建设备节点,方便用户访问。5. 模块加载与卸载函数
编写
module_init()
和module_exit()
,分别完成驱动注册和资源释放。
🕒什么是设备树?设备树的作用是什么?
设备树是一种数据结构,用于描述硬件系统的层次结构和属性。它通常由一系列节点和属性组成,每个节点代表一个设备或子系统,每个属性描述了设备的特性或配置信息。
它将设备的地址、中断、时钟等硬件资源信息从驱动程序中分离出来,内核在启动时解析设备树,从而动态识别和初始化平台上的外设。这样可以提高驱动的可移植性,降低驱动开发与硬件平台的耦合度。
🕓什么是文件系统?其功能包括哪些部分?
文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构,即在存储设备上组织文件的方法。
操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。
文件系统的功能包括:
管理和调度文件的存储空间,提供文件的逻辑结构、物理结构和存储方法;
实现文件从标识到实际地址的映射,实现文件的控制操作和存取操作,实现文件信息的共享并提供可靠的文件保密和保护措施,提供文件的安全措施。
🕔什么是根文件系统?
根文件系统是 Linux 系统启动后挂载的第一个文件系统,位于路径
/
,它包含操作系统正常运行所需的基本目录结构、系统命令、库文件、配置文件、设备节点等资源,是系统启动和运行的基础环境。
🕕GCC 编译器编译的完整流程是什么?各阶段的作用是什么?
1. 预处理(Preprocessing)
命令:
gcc -E source.c -o source.i
作用:处理
#include
、#define
、条件编译等指令,将所有宏展开、头文件展开,生成纯净 C 代码。2. 编译(Compilation)
命令:
gcc -S source.i -o source.s
作用:将预处理后的 C 源码翻译成汇编代码,包括词法分析、语法分析、语义分析、优化等。
3. 汇编(Assembly)
命令:
gcc -c source.s -o source.o
作用:将汇编代码翻译成目标文件(机器码 + 符号信息),生成
.o
文件。4. 链接(Linking)
命令:
gcc source.o -o a.out
作用:将多个目标文件和所需库文件链接,解决函数/变量地址,生成可执行文件。
🕖在 make menuconfig 界面下,驱动的三种状态(Y、N、M)分别表示什么含义?
Y(Yes):
将驱动编译进内核,开机时自动加载,不能卸载或重新加载。M(Module):
将驱动编译成模块文件(.ko
),在运行时通过insmod
或modprobe
加载,支持动态插拔。N(No):
不编译该驱动,最终不会包含在内核或模块中。
🕗有没有做过 Linux 的驱动开发?
是的,我有做过 Linux 驱动开发,主要涉及字符设备驱动和平台设备驱动。
具体工作包括:
编写字符设备驱动,使用
register_chrdev
注册设备号,使用file_operations
实现open
、read
、write
等接口;使用设备树匹配设备(
of_match_table
);使用内核日志(
printk
)调试;熟悉内核模块编写、编译、加载(
insmod
/rmmod
)以及udev
设备节点的自动创建;也做过简单的 I2C/SPI 外设驱动开发,包括读取寄存器和中断处理。
🕘FreeRTOS 有哪些特征?
轻量级内核:代码体积小,可运行在资源有限的 MCU 上(如 STM32、AVR)。
可移植性强:支持多种 CPU 架构,移植简单。
支持多任务:可创建多个任务并调度执行。
抢占式调度:默认支持基于优先级的抢占式调度,也支持协作式调度。
任务优先级管理:最多可设置
configMAX_PRIORITIES
个优先级。时间管理:支持任务延时(
vTaskDelay()
)、超时等待、滴答定时器。多种通信机制:
队列(Queue)
信号量(Semaphore:二值、计数)
互斥量(Mutex:含递归互斥量)
事件组(Event Group)
软件定时器:支持回调函数的定时执行。
内存管理:支持多种动态/静态内存分配方式(heap_1 ~ heap_5)。
支持钩子函数:如空闲钩子(Idle Hook)、滴答钩子(Tick Hook)等,用于系统自定义行为。
🕙FreeRTOS 中任务状态有哪些,怎么转换的?
Ready(就绪):已准备好执行,只等调度器分配时间片。
Running(运行):当前 CPU 正在执行的任务。
Blocked(阻塞):等待某个事件(如时间、信号量、队列等),暂时不能运行。
Suspended(挂起):任务被显式挂起(
vTaskSuspend()
),不会被调度,除非手动恢复。Deleted(删除):任务已经被删除,等待资源回收(由空闲任务完成)。
任务状态的转换由调度器根据任务优先级、延时、事件等待情况等条件决定,例如任务创建后进入就绪态,由调度器选中后进入运行态,调用
vTaskDelay()
会进入阻塞态,等待时间结束后重新进入就绪态。
🕚FreeRTOS 任务默认调度方式是什么?
FreeRTOS 的默认调度方式是优先级抢占式调度(Preemptive Priority Scheduling)。
在这种模式下,系统总是运行最高优先级的就绪任务,如果有更高优先级的任务变为就绪态,将立即中断当前任务并切换到高优先级任务运行,从而实现实时响应。
🕑freertos任务调度流程是什么?
1、调度器初始化
2、任务创建与加入调度
3、调度器启动(vTaskStartScheduler())
4.运行中的调度触发场景
时间片到期
高优先级任务就绪
任务主动让出CPU
5.上下文切换
🕛FreeRTOS 中任务的优先级如何设置?可以设置多少级?每级优先级的含义?
在 FreeRTOS 中,任务优先级用整数表示,从
0
(最低)到configMAX_PRIORITIES - 1。
数值越大表示优先级越高。优先级的最大数量由宏
configMAX_PRIORITIES
决定,通常用户在FreeRTOSConfig.h
中配置。每个任务创建时可指定其优先级,调度器总是选择就绪任务中优先级最高的一个运行。优先级相同的任务会按照时间片轮转调度(若启用
configUSE_TIME_SLICING
)。
🕜为什么 FreeRTOS 应用程序中必须使用空闲任务?
在 FreeRTOS 中,空闲任务(Idle Task)是由内核自动创建的一个最低优先级任务,始终存在且不可删除。
它的作用是保证当没有任何用户任务就绪时,CPU 有任务可运行,维持调度器的运行;此外,空闲任务还负责清理被删除任务的资源,如果启用了钩子函数,还可以用于系统空闲时执行低优先级后台任务(如进入低功耗状态)。
🕝什么是可剥夺型内核(Preemptive Kernel)?适用场景是什么?
可剥夺型内核指的是一种任务调度机制,当有更高优先级的任务变为就绪状态时,系统会立即中断当前正在运行的低优先级任务,切换执行更高优先级的任务。嵌入式 RTOS(如 FreeRTOS、RT-Thread)常采用此机制。
它适用于需要快速响应外部事件、并确保高优先级任务获得及时处理的实时系统,例如嵌入式控制系统、医疗设备、工业自动化等场景。
🕞什么是不可剥夺型内核(Non-preemptive Kernel)?适用场景是什么?
不可剥夺型内核是一种任务调度机制,其中正在运行的任务不会被其他任务中断,即使有更高优先级的任务变为就绪,也要等当前任务主动让出 CPU(如调用阻塞函数或结束)之后,调度器才会切换任务。
这种机制适合任务间切换控制严格、实时性要求不高的场景,调试简单,但容易导致高优任务响应延迟。
🕟FreeRTOS 抢占式任务调度机制适用于哪些场景?
外部中断唤醒高优先级任务
如串口/按键中断中唤醒一个高优先级任务,通过xSemaphoreGiveFromISR()
触发上下文切换。软件中释放资源,唤醒高优先级任务
例如任务 A 释放一个信号量,唤醒等待该信号量的高优任务 B,此时会发生抢占切换。定时任务到时唤醒
使用vTaskDelay()
、xTaskDelayUntil()
等函数的任务被系统时钟唤醒,如果其优先级高于当前任务,则立即调度。任务优先级动态提升
使用vTaskPrioritySet()
提升某任务优先级后,如果该任务处于就绪态且优先级更高,也会触发抢占。中断服务函数通知任务(task notification)
在 ISR 中使用xTaskNotifyGiveFromISR()
等 API 通知高优任务,触发立即切换。
🕠FreeRTOS 中 IPC可以通过哪些方式实现?
IPC 的全称是 Inter-Process Communication(进程间通信)。
常见 IPC 通信方式:
- 队列(Queue)
用于在任务间传递数据(如结构体、消息、命令等)。
线程安全,支持阻塞等待,最常用的通信方式之一。
- 二值信号量(Binary Semaphore)
用于事件同步或中断通知,表示“某个事件发生了”。
不传递数据,仅用于唤醒任务。
- 计数信号量(Counting Semaphore)
管理多个资源单位(如多个连接),用于资源计数同步。
- 互斥量(Mutex)
用于多个任务访问共享资源时的互斥控制。
支持优先级继承,避免优先级反转。
- 递归互斥量(Recursive Mutex)
同一个任务可以重复获取该互斥锁,适用于嵌套函数共享资源的情况。
- 事件组(Event Groups)
通过设置/清除 bit 位表示多个事件状态。
支持等待多个事件“或/与”条件,适合复杂同步需求。
- 任务通知(Task Notification)
每个任务默认有一个轻量级的通知通道。
比信号量和队列更快,适合高性能、简单通信场景。
🕡FreeRTOS 中任务之间的通讯方式有哪些?
常见通信方式:
- 队列(Queue)
用于在任务间传递数据(如结构体、消息、命令等)。
线程安全,支持阻塞等待,最常用的通信方式之一。
- 二值信号量(Binary Semaphore)
用于事件同步或中断通知,表示“某个事件发生了”。
不传递数据,仅用于唤醒任务。
- 计数信号量(Counting Semaphore)
管理多个资源单位(如多个连接),用于资源计数同步。
- 互斥量(Mutex)
用于多个任务访问共享资源时的互斥控制。
支持优先级继承,避免优先级反转。
- 递归互斥量(Recursive Mutex)
同一个任务可以重复获取该互斥锁,适用于嵌套函数共享资源的情况。
- 事件组(Event Groups)
通过设置/清除 bit 位表示多个事件状态。
支持等待多个事件“或/与”条件,适合复杂同步需求。
- 任务通知(Task Notification)
每个任务默认有一个轻量级的通知通道。
比信号量和队列更快,适合高性能、简单通信场景。
🕢IPC 通信和任务之间通讯是一个意思吗?
IPC(Inter-Process Communication)通信是一个广义概念,指进程/线程/任务之间的数据交换或同步机制。
在 FreeRTOS 或嵌入式 RTOS 中,通常说的 IPC 就是任务之间的通信方式。
🕣操作系统中的自旋锁和信号量有什么区别?
自旋锁是一种轻量级的锁机制,在竞争资源时,线程不会休眠,而是持续循环检查锁是否可用(即“自旋”),直到获取锁或被系统打断。自旋锁适用于多核系统中的短临界区保护。
而信号量则可以让线程阻塞等待资源,适合任务或线程之间的同步与互斥。
由于自旋锁是一种忙等待锁,占用 CPU 资源较多,所以 像 FreeRTOS 这种轻量实时系统中通常不使用自旋锁,因为嵌入式单核系统或低资源环境下它的成本太高。
🕤什么是临界资源和临界区?为什么要有临界区?
临界资源是指多个线程或任务可能同时访问的共享资源,比如全局变量、设备寄存器、文件等。
临界区是访问临界资源的那一段代码,它必须被互斥保护,否则可能导致数据竞争、资源冲突、结果不一致等问题。
因此,必须引入临界区的概念并通过锁机制保护它,来保证系统的正确性和线程安全。
🕥在 FreeRTOS 中,互斥量(Mutex)和信号量(Semaphore)的区别?
互斥量是基于信号量实现的一种特殊二值信号量,它用于保护临界区,支持优先级继承机制,防止优先级反转;
信号量既可以是二值的,也可以是计数型的,主要用于任务同步或多资源管理。
二者在用法上类似,但互斥量更适合用于互斥访问共享资源,而信号量更适合用于事件通知和资源计数管理。
🕦说一下FreeRTOS中的优先级反转?有什么危害?
指低优先级任务持有高优先级任务所需的资源(如互斥锁)时,高优先级任务被阻塞,而中等优先级任务却能抢占低优先级任务执行的现象。
危害:
中优先级任务插队加剧问题
高优先级任务延迟执行
实时性失效
系统调度逻辑混乱
可能导致死锁
🕧为什么FreeRTOS中的互斥量能解决优先级反转的问题?
互斥量解决优先级反转问题,是通过优先级继承机制(Priority Inheritance)实现的。
当高优先级任务因等待一个被低优先级任务持有的互斥量而阻塞时,系统会临时提升低优先级任务的优先级,使其尽快释放互斥量,避免中间被更低优先级任务打断,从而减少高优任务的等待时间。场景例子(现实生活类比):
你在公司有三个同事:
👨💼 高优先级:经理(任务A)
👷♂️ 低优先级:实习生(任务B)
🧑🔧 中优先级:普通员工(任务C)
现在只有一把打印机(共享资源),只能一个人用,需要申请钥匙(互斥量)。
步骤演示(未使用优先级继承时会发生的问题):
实习生(任务B)先来了,拿到了打印机钥匙,开始慢慢打印。
这时经理(任务A)来了,也要用打印机,但钥匙在实习生手里,于是他只能等着。
正当实习生想把打印完,这时普通员工(任务C)来了,他虽然优先级比实习生高,但比经理低。
因为调度器默认按优先级安排工作,所以员工插队开始干活(抢占任务B)。
实习生继续被压着没机会释放打印机钥匙,经理只能一直等 → 优先级反转发生了!
引入互斥量的优先级继承机制后:
当经理(任务A)发现钥匙被实习生(任务B)拿着时,系统做了件事:
系统临时把实习生的优先级提升为和经理一样高!
这样普通员工(任务C)就插不进队,实习生能立刻完成打印。
这样经理就不会因为「实习生+员工」这俩人组合拖延了自己的工作。
实习生释放钥匙,经理马上用上,实习生优先级恢复。
🕐什么是可重入函数(Reentrant Function)?
可重入函数是指能被多个线程或中断安全调用的函数,它不依赖全局或静态变量,只使用局部变量和传入参数,因此不会互相干扰【指多个执行流(线程、中断等)同时调用可重入函数时,函数的执行状态和结果不会因并发调用而产生错误或不一致】。
// 可重入函数示例
int sum(int a, int b) {
return a + b;
}//不可重入函数示例
int counter = 0;
int add_one() {
return ++counter; // 使用了共享的全局变量,不可重入
}
🕑FreeRTOS 的内存管理是如何实现的?
🕒FreeRTOS 中断的工作流程知道吗?
1.中断发生
硬件触发中断,自动跳转到 ISR(中断服务程序)。
2.保存现场
CPU 自动压栈部分寄存器(如程序计数器 PC、程序状态寄存器 CPSR、部分通用寄存器)。
FreeRTOS/编译器 额外保存其他需要的寄存器(R4-R11)以保证任务上下文完整。
3.执行 ISR
中断服务函数执行逻辑,如处理外设数据、中断清除、发送信号等。
4.是否切换任务
如果 ISR 中调用了
xSemaphoreGiveFromISR()
、xQueueSendFromISR()
等 API,可能唤醒高优先级任务。用
portYIELD_FROM_ISR()
来判断是否需要上下文切换。5.恢复现场
如果无需切换任务,恢复原任务上下文。
如果切换任务,将当前任务的上下文存栈,恢复新任务的上下文。
🕓前后台程序与实时操作系统的区别是什么?
前后台程序中,前台是中断服务程序,用于响应外设等突发事件;后台是主循环,用于轮询执行常规任务。
这种结构简单、资源占用低,但无法支持真正的多任务,实时性和可维护性差。
而 RTOS 中通过内核调度多个任务,结合任务优先级、中断嵌套与同步机制,支持高实时性和系统复杂性。
🕔实时系统的基本特性有哪些?
实时系统具有以下基本特性:
确定性(Determinism):
能在规定时间内完成特定任务,响应时间可预测。实时性(Timeliness):
系统必须在时间约束下完成任务,分为硬实时与软实时。并发性(Concurrency):
同时管理多个任务或事件,通过调度机制有序执行。可靠性(Reliability):
系统需在长时间运行中保持稳定,容错能力强。可预见性(Predictability):
对系统行为、资源占用和调度过程具有高度可控性。
🕕操作系统(如 Linux)中进程的状态有哪些?FreeRTOS 中任务的状态有哪些?
操作系统中的进程状态(以 Linux 为例):
新建(New):进程正在创建。
就绪(Ready):已分配资源,等待 CPU。
运行(Running):正在执行。
阻塞(Blocked / Waiting):等待 I/O 或事件。
(可选)挂起(Suspended):进程被换出主存。
终止(Terminated):已完成或被杀死。
FreeRTOS 中的任务状态:
就绪(Ready):可以执行,等待调度。
运行(Running):占用 CPU 正在执行。
阻塞(Blocked):等待事件或延时超时。
挂起(Suspended):被挂起,无法调度执行。
删除(Deleted):任务已标记删除,等待清除。
🕖什么是死锁?在操作系统或并发编程中,如何避免死锁?
死锁(Deadlock) 是指多个进程或线程因相互等待对方占有的资源而永久阻塞,导致系统无法继续推进的一种状态。
发生死锁必须满足四个条件(死锁的必要条件):
互斥:资源不能被多个进程共享,只能一个占用。
占有且等待:持有资源的同时等待其他资源。
不剥夺:资源不能被强制夺取,只能主动释放。
循环等待:形成一个资源等待的环形链。
如何避免死锁(常见方法):
破坏必要条件:
禁止“占有且等待”:申请资源时一次性申请全部。
支持“资源可剥夺”:允许强制释放已占有资源。
打破“循环等待”:统一资源申请顺序,按序请求。
使用超时/尝试锁机制:
使用
trylock
或设置锁超时,避免无限等待。死锁检测与恢复(适用于系统级):
定期检测资源等待图,发现死锁后终止或回滚进程。
采用银行家算法(资源调度中):
保证系统始终处于安全状态,避免分配导致死锁。
🕗如何获取并搭建一个 FreeRTOS 项目的运行环境?
获取官方或芯片厂商提供的 FreeRTOS 源码,
选择适配的 芯片平台(如 STM32、ESP32 等),
配置 交叉编译工具链(如 arm-none-eabi-gcc),
基于 开发板或仿真器 进行开发调试,并使用 IDE(如 STM32CubeIDE、Keil、VS Code 等)搭建工程,
配置
FreeRTOSConfig.h
和任务代码,最后烧录到目标板运行。
🕘什么是 UART?它是如何进行通信的?UART 的工作原理及其数据包结构是怎样的?
UART(通用异步收发 传输器,Universal Asynchronous Receiver/Transmitter) 是一种用于设备间串行 全双工 异步数据通信的协议,常见于单片机、模块、电脑串口等。
通信方式和原理:
通信线:
TX
(发送)和RX
(接收)。通信方式:全双工 异步。不需要时钟线,而是通过设置一致的波特率(如9600bps)进行收发。
每发送/接收一个字节的数据,UART 自动将数据转换为一帧格式。
数据包结构(字符帧):
起始位(1位) | 数据位(5~9位) | 可选奇偶校验位(1位) | 停止位(1或2位)
常见的UART配置:1 起始位 + 8 数据位 + 1 停止位(无校验) = 10位一帧
🕙串口异步通信中的一个字符帧由哪些部分组成?
串口(UART)异步通信中的一个字符帧(数据帧)通常由以下几部分组成:
起始位(Start Bit):1位,标志一个新字符的开始,始终为逻辑低电平(0)。
数据位(Data Bits):5~9位,通常是 7 或 8 位,表示实际传输的数据内容。
校验位(Parity Bit,可选):0 或 1 位,用于检测数据传输错误(奇校验或偶校验)。
停止位(Stop Bit):1 或 2 位,逻辑高电平(1),标志一帧数据的结束。
🕚说一下RS-232?
RS-232 是由 EIA(电子工业协会)定义的一种 串行 全双工 异步 通信接口标准,用于在 DTE(数据终端设备) 和 DCE(数据通信设备) 之间进行 低速、短距离、点对点 的数据通信。
关键特性:
通信线(以 DB9 为例):
RXD:接收数据
TXD:发送数据
GND:信号地
DTR:数据终端就绪
DSR:数据设备就绪
RTS:请求发送
CTS:清除发送
通信方式:全双工 异步
拓扑结构:点对点(1对1),常用的接口是 DB9(9针)或 DB25。
波特率:通常在 1200~115200 bps 之间,较慢。
电气特性:
逻辑"1":–3V 到 –15V
逻辑"0":+3V 到 +15V
电平与 TTL 相反。
传输距离:理论上最长 15 米,实际推荐 10 米以内。
字符帧包含:
起始位(1位)
数据位(5~9位,常用8位)
可选的奇偶校验位(1位)
停止位(1或2位)
🕛说一下RS-485?
RS-485 是一种支持 多点总线通信 的 差分串行 异步通信接口标准,具有传输距离远、抗干扰能力强、通信速率高的特点,广泛应用于工业自动化、楼宇控制、安防等场景。
关键特性:
接口引脚:
通常使用A、B两根信号线(+GND),比RS232简洁
通信方式:半双工(常见)或全双工(需双总线)
拓扑结构:主从模式,支持多达32个设备并联(有的芯片扩展支持128/256个)
电器特性:
使用差分信号(A/B线),增强抗干扰性
逻辑“1”:A>B
逻辑“0”:A<B
传输距离:
最长可达1200米
波特率与距离成反比
终端电阻:
通常在总线两端加120Ω终端电阻防止信号反射
🕜串口和并口的区别是什么?
串口是按位依次传输数据的通信方式,优点是线路少、成本低、传输距离远;
并口是同时传输多个位(如8位或更多)的方式,线路多,传输速度快,传输距离短。
如今串口更常用于长距离、低速设备通信,而并口逐渐被高速串行总线(如USB)取代。
速记:串口线少、传得慢但远;并口线多、传得快但短。
🕝I2C 总线的基本原理、特点及应用场景。
I2C(Inter-Integrated Circuit)是一种两线式串行通信协议,由 SDA(数据线) 和 SCL(时钟线) 构成,支持多主多从通信,数据通过地址匹配来识别从设备。
关键特性:
通信线:SDA(数据线)和SCL(时钟线)
通信方式:半双工 同步
拓扑结构:一主多从,或多主多从(多个主设备可控制总线,但需要仲裁机制)
传输速率:标准模式(100kbps)、快速模式(400kbps)、高速模式(3.4Mbps)等
寻址方式:每个从设备有唯一地址(7位或10位)
应用场景:
读取传感器数据(如温湿度、加速度)
控制 OLED 屏、LCD 屏
访问 EEPROM、RTC 实时时钟
音频芯片、PMIC(电源管理芯片)通信
🕝说一下SPI 总线的通信原理、特点和应用场景。
SPI(Serial Peripheral Interface)是一个全双工、同步、主从式串行通信协议,使用 4 根信号线(MOSI、MISO、SCLK、CS)进行通信,通信速度快、硬件实现简单。
关键特性:
通信线:
MOSI(主输出从输入)
MISO(主输入从输出)
SCLK(时钟信号)
CS/SS(片选线,低电平有效)
通信方式:全双工 同步
拓扑结构:一主多从
传输速率:可达几十Mbps
寻址方式:片选信号(CS 引脚)
应用场景:
外接 Flash、EEPROM
TFT/LCD 显示屏
SD 卡
传感器或 ADC 芯片(如 MCP3008)
SPI 串口屏(如 Nextion)
🕞什么是 CAN 总线?请简述其工作原理、特点和应用场景。
CAN(Controller Area Network)总线是一种异步、半双工、差分式、多主机 串行通信协议。广泛应用于汽车电子、工业控制等场景。
关键特性:
通信线:
CAN_H(高电平线)
CAN_L(低电平线)
使用差分信号传输,增强抗干扰能力。
通信方式:半双工 异步
拓扑结构:总线型结构(多个节点并联在两条总线上)
传输速率:常见为 125 kbps ~ 1 Mbps,距离越远速率越低
优先级仲裁:基于标识符 ID,ID 越小,优先级越高;仲裁过程不丢帧(非破坏性)
应用场景:
汽车电子系统(车灯控制、发动机、ABS、空调等)
工业自动化(控制器、传感器、执行器通信)
电梯、机器人、医疗设备、船舶系统
无人机、AGV 等智能控制设备
🕟什么是 MODBUS?请简述其工作原理 和 应用场景。
MODBUS 是一种主从式通信协议,广泛应用于工业自动化领域中各类电子设备间的数据通信。它是一种开放协议,支持串口(如 RS-232/RS-485)和网络(如 TCP/IP)通信。
工作原理:
主从架构:通信始终由主设备发起,从设备只能被动应答。
请求-应答机制:主机发送请求帧(包含功能码和数据),从机根据请求进行操作并返回应答帧。
寄存器访问:主机通过功能码读取/写入从机的线圈、输入、寄存器等资源。
应用场景:
PLC 与传感器/执行器通信(温度采集、继电器控制)
智能仪表数据读取(电表、气表、液位传感器等)
工业设备组网监控(人机界面 HMI、SCADA 系统)
楼宇自动化(空调、照明、能耗监测系统)
农业、能源、交通自动化系统
🕠说一下MODBUS 协议模式?
🕡LoRa 是什么,其工作原理是什么?应用场景?
LoRa (Long Range)是一种基于扩频技术的超远距离无线传输技术,属于物联网通信技术的一种。
它利用线性调频扩频(CSS)技术,将信号在较宽的频谱上进行扩展,从而提高信号的抗干扰能力和传输距离。
发送端将原始数据调制到 LoRa 信号上,通过天线发送出去,接收端则通过解扩等操作还原出原始数据。
应用场景:
智慧农业(远程监测土壤、温湿度)
城市管理(井盖、路灯、停车监控)
工业现场(传感器状态上传、远程告警)
能源管理(抄表、燃气监控)
🕢什么是 LoRaWAN?和 LoRa 有什么区别?
LoRa 是物理层的调制技术;LoRaWAN 是构建在 LoRa 之上的 MAC 层通信协议和网络架构,支持设备接入、认证、安全、数据传输架构 。
🕣请简述 WiFi 的主要工作模式及其典型应用场景。
STA 模式(Station):作为客户端连接外部路由器/热点,常用于上行数据传输
AP 模式(Access Point):自身充当热点,终端设备直连,适用于配置界面或局域网通信
STA+AP 混合模式:同时作为客户端和热点,用于桥接网络或现场设备配置
Mesh 模式:多节点自动组网,扩展覆盖范围,适合大规模 IoT 部署
🕤说一下蓝牙是什么?有几种工作模式?
蓝牙是一种短距离无线通信技术,主要用于低功耗、点对点或小规模组网的设备间通信。
模式分类:
经典蓝牙(BR/EDR) BR(Basic Rate)和 EDR(Enhanced Data Rate)
低功耗蓝牙(BLE)Bluetooth Low Energy
双模蓝牙(Dual Mode)
🕥常见的近距离无线通信协议?各自的特点和应用场景是什么?
常见的有 Bluetooth、Wi-Fi、ZigBee、NFC、Infrared、UWB 等。
蓝牙(Bluetooth)
通信距离:10~100 米
特点:低功耗(BLE)、易配对
应用:耳机、穿戴设备、传感器数据传输
Wi-Fi
通信距离:数十米~百米
特点:高速、宽带传输、支持 TCP/IP
应用:无线局域网、视频传输、IoT 网关
ZigBee
通信距离:10~100 米
特点:低速率、低功耗、自组网
应用:智能家居、工业控制、传感器网络
NFC(近场通信)
通信距离:小于 10 厘米
特点:点对点通信、无需配对
应用:移动支付、门禁、电子票证
红外(Infrared)
通信距离:几米内,需视距
特点:低成本、抗干扰性弱
应用:电视遥控器、简单数据传输
UWB(Ultra Wide Band)超宽带
通信距离:10~30 米,厘米级精度
特点:高精度定位、抗干扰强
应用:室内定位、智能穿戴、高安全场景
🕦常见的物联网(IoT)通信协议?它们的特点和适用场景分别是什么?
应用层协议(用于设备之间数据交换)
MQTT(Message Queuing Telemetry Transport)
轻量级发布/订阅模式
占用带宽小、低功耗、适合低带宽网络
应用:传感器数据上传、智能家居
CoAP(Constrained Application Protocol)
类似 HTTP,基于 UDP,适合资源受限设备
小型二进制报文,支持多播
应用:小型设备之间快速通信
HTTP/HTTPS
基于 TCP,通用性强,适配 Web 应用
数据开销大,实时性差
应用:Web 服务对接、数据上报
LwM2M(Lightweight M2M)
基于 CoAP,为设备管理和远程控制设计
支持设备注册、远程配置和固件升级
应用:设备远程管理、大型部署环境
AMQP(Advanced Message Queuing Protocol)
面向消息队列,适合复杂消息交换场景
适用于企业级 IoT 解决方案(如金融、医疗)
网络/传输层协议
LoRaWAN
基于 LoRa 的低功耗广域网协议,星型拓扑
适合远距离、低速率的传感器网络
应用:远程抄表、环境监控、农业物联网
NB-IoT(Narrow Band IoT)
基于蜂窝网络,低功耗广域(LPWAN)通信技术
支持深度覆盖、海量连接、低成本
应用:智能水表、电表、城市管理
ZigBee
自组网能力强,低速率短距离
应用:智能照明、家庭自动化、工业控制
Bluetooth LE(低功耗蓝牙)
点对点通信、低功耗、近距离
应用:智能穿戴、健康监测、智能门锁
🕒STM32 中常见通信协议(外设协议)?
这些用于芯片与外部设备通信,可理解为“协议类外设”:
🕢 STM32 常见功能类外设(非协议)?
这些用于信号采集、控制、系统功能支持,可称为“功能类外设”:
🕧说一下 STM32 中的中断?为什么需要中断,有哪些中断,大概怎么做?
中断是一种处理异步事件的重要机制。
为什么需要中断?
提升响应效率:无需轮询,响应外部事件迅速
降低资源占用:CPU 在无任务时可休眠
支持异步操作:如按键、串口、定时器、DMA等外设事件处理
STM32 中的常见中断类型:
使用中断的基本流程:
开启外设时钟:
__HAL_RCC_GPIOx_CLK_ENABLE();
配置外设为中断模式(如 EXTI):
配置 GPIO 为输入模式
设置为中断触发(上升沿/下降沿)
初始化 EXTI 线
使能中断并设置优先级:
使用
HAL_NVIC_SetPriority()
和HAL_NVIC_EnableIRQ()
配置中断控制器 NVIC编写中断服务函数(ISR):
函数名通常为:
void XXX_IRQHandler(void)
在函数内部处理中断事件,并清除中断标志位
🕐STM32 中定时器(Timer)的类型、主要功能、使用场景及配置方法?
定时器类型(以 STM32F1/F4 为例):
主要功能:
定时/计时功能:可配置为以固定周期触发中断
PWM 输出:用于电机控制、LED 调光等
输入捕获:测量外部信号频率、脉宽
输出比较:用于控制输出翻转或事件触发
编码器接口模式:支持与编码器配合使用
使用流程:
打开时钟
配置定时器参数(如分频器、计数器模式、周期)
使能中断并配置中断优先级
开启定时器和中断
编写中断服务函数
应用场景:
定周期任务调度(如 RTOS tick)
PWM 控制电机、舵机
红外测距信号脉宽测量
精确延时(比
delay()
更准确)事件触发、测速、编码器方向检测
🕑GPIO是什么,STM32 中 GPIO 的输入输出模式分类及其适用场景?
GPIO(通用输入输出口)用于 MCU 与外设的数据通信控制。
🕑什么是 ADC?常见的 ADC 转换模式有哪些?
ADC(Analog to Digital Converter) 是模数转换器,用于将模拟信号(如电压、电流)转换为数字信号,供 MCU 等数字系统处理。
常见的 ADC 转换模式(以 STM32 为例):
单次转换模式(Single Conversion Mode)
触发后仅转换一次,完成后停止
适用场景:低速采样、单点测量,如电池电压监测
连续转换模式(Continuous Conversion Mode)
一次触发后不断采样、转换,直到停止命令
适用场景:实时信号监测,如电压波动分析
扫描模式(Scan Conversion Mode)
顺序转换多个通道
适用场景:多路传感器读取,如温度、电压、电流等采集
间断模式(Discontinuous Mode)
每次触发转换一组通道的一部分,可与扫描模式配合
适用场景:分批处理,提高效率或配合中断使用
注入通道(Injected Mode)
高优先级采样,打断常规通道进行快速转换
适用场景:电机控制、需要紧急采样的应用
模拟看门狗(Analog Watchdog)
设置上下限,监控 ADC 值是否越界
适用场景:安全保护、电压异常报警
🕒ADC 采样精度由什么决定?
1.ADC的位数(分辨率) 越高表示电压划分越细,精度越高
2.参考电压 决定量化范围,越稳定越精准
3.输入信号质量 噪声小、阻抗合适能减少误差
4.采样时间 合理设置时间,确保信号稳定采样
5.温度/电源噪声/地线干扰 使用滤波/稳压/合理布线抑制干扰
🕓什么是 PWM?请简述其工作原理、生成方式以及常见应用场景?
PWM(Pulse Width Modulation,脉宽调制)是一种通过控制信号的“高电平持续时间”来调节模拟效果的数字信号技术。
工作原理:
固定频率下,通过调节高电平持续时间(称为“占空比”)来实现模拟信号的控制。
例如:
频率:1kHz
占空比:30% → 高电平持续 0.3ms,低电平 0.7ms
占空比:70% → 高电平持续 0.7ms,低电平 0.3ms
实现方式:
在微控制器中通常由 定时器(Timer)外设 来自动生成 PWM 信号:
设置周期(ARR,自动重装载寄存器)
设置占空比(CCR,比较寄存器)
设置输出模式(如 PWM1、PWM2)
应用场景:
电机调速:通过调节占空比控制直流电机转速
LED 调光:调节 PWM 占空比控制亮度
声音控制:PWM 产生音频信号输出到蜂鸣器
电压控制类 DAC:通过滤波实现简易 DAC 输出
伺服控制:如舵机转角控制,通常用 50Hz、占空比调角度
🕔请简述 PWM的核心参数及其作用?
1.频率(Frequency)
含义:PWM 信号的周期性变化速度,即每秒钟脉冲重复的次数,单位为 Hz。
作用:决定控制反应速度
2.占空比(Duty Cycle)
含义:一个 PWM 周期中,高电平持续时间占整个周期的比例,通常以百分比表示。
作用:直接影响功率输出,控制强度
3.周期(Period)
含义:PWM 信号从一次开始到下次开始所经历的时间,T = 1 / 频率
4.分辨率(Resolution)
含义:占空比变化的最小单位,通常由定时器的位宽决定,例如 8 位、10 位、16 位
作用:分辨率越高,占空比控制越精细(控制越平滑)
🕕什么是 EEPROM?常见应用场景?
EEPROM(Electrically Erasable Programmable Read-Only Memory) 是一种非易失性存储器,即在掉电后仍能保存数据。它可以通过电信号进行擦除与重写,适用于频繁小量写入的应用场景。
应用场景:
保存用户配置参数(如设备 ID、通信地址)
存储校准数据、运行日志等
🕖什么是 RTC?它的作用和常见应用是什么?
RTC(Real-Time Clock,实时时钟) 是一种保持当前时间和日期的硬件模块,即使在系统掉电或重启后,也能继续计时。它通常由独立电源(如纽扣电池)供电,以保证长时间运行。
RTC 的作用:
提供年、月、日、时、分、秒等系统时间
支持定时唤醒/报警功能
在系统掉电时保持时间持续运行
为日志、数据采集提供时间戳
🕗什么是看门狗(Watchdog)?它的工作原理是?
看门狗定时器(Watchdog Timer, WDT) 是一种防止系统出现异常、卡死或死循环的自动复位机制。
工作原理:
看门狗启动后,会从设定的时间倒计时。
系统必须在倒计时到零前调用“喂狗函数”重置计数器。
如果系统因故障未能喂狗(如死循环、卡死等),看门狗超时触发复位动作。
🕘说一下独立看门狗和窗口看门狗的区别?
IWDG: 简单可靠,任何时候都能喂狗。(完全独立,主时钟异常也能复位)
WWDG: 时间控制更严格,只能在“窗口期”喂狗,防止程序跑飞但还在喂狗。(依赖主时钟)
🕙什么是单工、半双工和全双工?
在通信系统中,单工、半双工、全双工描述的是通信双方信息传输的方向和方式.
单工:单向 → “广播”
半双工:双向非同时 → “对讲机”
全双工:双向同时 → “电话”
🕚什么是时钟源?什么是 PLL?起什么作用?
时钟源是微控制器或处理器内部各模块工作的基础时序信号来源,决定了系统运行的速度和同步节奏。
常见时钟源类型:
外部晶振(HSE):高精度,比如 8MHz 石英晶振
内部振荡器(HSI):芯片内置振荡源,精度略低,但无需外设
低速振荡器(LSE/LSI):用于 RTC、低功耗等功能
PLL(Phase Locked Loop,锁相环) 是一种时钟倍频电路,可以将一个较低频率的输入时钟,通过倍频或分频生成更高频率的系统时钟,用于 CPU、外设等高速模块。
🕛在单片机中,地的种类有哪些?
1、数字地:作为数字电路的参考地
2、模拟地:为模拟信号电路提供参考地,保证模拟信号精度
3、强电地:为大电流器件(如电机、电源模块)提供地参考
4、信号地:在串口通信、CAN、485、RS232 等接口中,用作不同设备间信号参考地
5、安全地:连接设备外壳或屏蔽层,用于静电放电、防雷保护、EMI 屏蔽
🕜说一下CPU、MPU、MCU、SoC、SoPC是什么?
🕝FPGA 和 ASIC 的概念以及两者的区别是什么?
FPGA(Field Programmable Gate Array) 是现场可编程门阵列,它可以反复编程,适合用来做硬件逻辑的原型验证或者需要灵活配置的场景。
而 ASIC(Application Specific Integrated Circuit) 是专门为某种应用定制的集成电路,性能和功耗表现都更优,但一旦流片就不能更改,开发周期和成本也更高。
一般来说,FPGA 用于研发阶段或小批量产品,ASIC 用于大规模量产,对性能和成本敏感的项目。
🕞ROM 和 RAM 的区别及类型是什么?
ROM 是只读存储器(Read-Only Memory),用于永久保存数据,比如程序代码或固件,一般断电后数据不丢失。
RAM 是随机访问存储器(Random Access Memory),用于临时存储运行中的数据,断电后数据会丢失。
ROM 常见类型有 Mask ROM、EPROM、EEPROM、Flash;
RAM 常见类型有 SRAM 和 DRAM,其中 SRAM 用于缓存,DRAM 用作主存。
🕟精度和分辨率的区别是什么?
精度表示测量结果接近真实值的程度,而分辨率表示设备能分辨的最小单位。
前者反映‘准不准’,后者反映‘细不细’。
🕡传感器的输出引脚是高阻抗好还是低阻抗好?为什么?
一般来说,传感器的输出引脚最好是低阻抗输出。
因为低阻抗输出可以更稳定地驱动后级电路,抗干扰能力强,信号衰减小,更适合长线传输。
而高阻抗输出则容易受到外界干扰,且对后级负载较敏感。
🕢什么是上位机?常用的通信协议包括?
上位机是与下位机通信并进行控制与数据管理的软件平台。
上下位机之间常用的通信协议包括:
串口类协议:
UART/RS-232/RS-485:常用于近距离、点对点或多点通信;
MODBUS-RTU:基于串口,工业自动化中非常常见;
网络协议:
MODBUS-TCP:基于以太网,适用于网络化系统;
TCP/IP、UDP:传输稳定可靠或实时性要求高时使用;
HTTP/HTTPS、MQTT:常用于 IoT 设备与云平台通信;
自定义协议:
根据项目需要在串口/TCP/IP等底层基础上设计报文结构,满足定制化控制与数据传输;
🕗解释通信中的基本概念:主机与从机、连续方式、指令方式。
主机(Master):负责发起通信、控制通信节奏,主动发送命令;
从机(Slave):被动响应主机指令,不能主动发起通信;
连续方式:又称轮询方式;主机或系统不断循环检测各个设备的状态,有数据则读取,无数据也一直轮询;
指令方式:主机发送特定的命令或请求,从机根据命令做出有目的的响应;
🕤简述 OSI 七层模型。
自下而上如下:(物数 网传 会表应)
1.物理层(Physical Layer)
传输比特流,规定电气信号、接口标准,如电缆、光纤、网卡。
举例:网线、电压、电流、传输速率。
2.数据链路层(Data Link Layer)
建立可靠的数据链路,负责帧传输与错误检测(如 CRC),协议有 Ethernet、PPP。
举例:MAC 地址通信、以太网帧。
3.网络层(Network Layer)
负责路由选择和逻辑地址(IP 地址)分配,典型协议:IP、ICMP。
举例:IP 路由器转发数据包。
4.传输层(Transport Layer)
提供端到端的可靠传输,常见协议:TCP(可靠)、UDP(不可靠但快速)。
举例:数据包分段、重传控制、端口编号(如 TCP 80)。
5.会话层(Session Layer)
管理会话、建立/维护/断开连接,支持全双工或半双工通信。
举例:远程登录、视频会议会话控制。
6.表示层(Presentation Layer)
数据格式转换、加密/解密、压缩/解压。
举例:JPEG、MP3 解码,SSL 加密。
7.应用层(Application Layer)
面向用户,提供网络服务接口(如 HTTP、FTP、SMTP 等)。
举例:浏览器访问网页,发邮件。
🕥简述 TCP/IP 四层模型?
自下而上如下:({链路} 网传 {} {} 应)
1.链路层(Link Layer)
负责物理传输与帧处理,连接硬件接口。
2.网络层(Internet Layer)
实现逻辑寻址与路由选择,保证数据包从源到目的地址。
3.传输层(Transport Layer)
提供端到端的通信服务,支持可靠或不可靠的数据传输。
4.应用层(Application Layer)
提供用户服务接口,处理高层协议与用户交互。
🕚在嵌入式系统中,如何进行数据采集与处理?
1.信号采集阶段:
模拟信号 → ADC(如 STM32 的 ADC)
数字信号 → GPIO / UART / SPI / I2C / CAN / Modbus
2.数据传输阶段:
中断驱动采样 / 周期性定时器采样
DMA 将数据写入内存或 FIFO 缓冲区
3.数据预处理阶段:
滤波算法(滑动平均、中值滤波、卡尔曼滤波)
校准、归一化(如温度、电压修正)
异常值检测(超限报警、去抖动)
4.数据应用阶段:
控制执行器(如 PWM 输出)
存入 Flash/EEPROM 或上传(串口/WiFi/MQTT)
🕛解释嵌入式系统中的错误处理机制。
常见的错误处理机制包括:
1、错误检测机制:
断言检查(assert):在开发阶段检查变量和状态是否合法;
校验机制:如 CRC 校验、奇偶校验、和校验等,用于通信和数据存储;
看门狗(Watchdog):检测程序运行是否卡死;
硬件中断错误处理:如总线错误、非法访问等触发异常中断。
2、错误响应方式:
错误码返回:函数执行返回错误码(如
-1
,E_TIMEOUT
等);日志记录:将错误写入日志系统(可存入 Flash、串口输出等);
LED/蜂鸣器报警:常用于人机交互时指示故障状态;
任务重启或系统复位:严重错误触发 MCU 复位或重启任务。
3、错误恢复策略:
重试机制:例如通信失败后重发数据包;
降级处理:如部分模块故障后转为低功耗或备用模式;
异常处理函数:使用
try-catch
(在 RTOS 或高级语言环境中);使用看门狗复位系统:软件长时间无响应时由独立/窗口看门狗重启。
🕐MQTT(Message Queuing Telemetry Transport)怎么保证传输效率?
轻量协议头:MQTT 的协议头非常小,最小仅需 2 字节,极大减少了通信开销。
发布/订阅模型:客户端之间解耦,服务端负责转发,避免点对点通信带来的复杂性。
QoS 等级控制:提供 3 种服务质量(QoS 0、1、2),用户可根据场景选择合适的可靠性与效率权衡。
保持连接机制(Keep Alive):定期发送心跳包,检测客户端状态,避免频繁建立连接带来的开销。
遗嘱消息(Will Message):客户端异常断开时,服务器自动推送其“最后一条消息”(让其他设备收到这个遗嘱),节省异常检测流程。
持久会话(Clean Session):客户端可选择是否保留会话状态,断网重连时减少重复订阅和消息丢失。
有效载荷自由格式:支持二进制数据,结构简单,不限制内容格式,方便优化压缩和解析。
🕑MQTT消息质量等级有哪些?分别有什么涵义?
MQTT 消息质量等级 QoS(共 3 种):
1、QoS 0:最多一次(At most once)
说明:消息最多发送一次,不确认、不重发。
适用场景:传感器数据频繁上报,丢一两次无所谓。
2、QoS 1:至少一次(At least once)
说明:消息至少被送达一次,可能重复接收。
机制:客户端必须接收到 PUBACK 确认,不确认则重发。
适用场景:比如报警消息,重要但可容忍重复。
3、QoS 2:仅一次(Exactly once)
说明:消息只送达一次,且不重复,保证最高可靠性。
机制:采用四次握手(PUBREC/PUBREL/PUBCOMP)确保去重。
适用场景:如订单处理、支付信息等不能重复的关键数据。
🕒MQTT报文格式?最小报文?举出一些报文的类型?
MQTT 报文由三部分组成:固定报头(Fixed Header)、可变报头(Variable Header) 和 有效载荷(Payload)。其中,固定报头是每个 MQTT 报文必须包含的部分,而可变报头和载荷是否存在则取决于具体的报文类型。
MQTT 最小的报文是 PINGREQ(心跳请求) 或 PINGRESP(心跳响应),这类报文只有固定报头,没有可变报头和载荷,因此它们的长度仅为 2 字节,体现了 MQTT 协议轻量、高效的特点。其中:
第 1 个字节表示报文类型及标志位(例如
C0
表示 PINGREQ);第 2 个字节为“剩余长度”,这里是
0
,说明无额外内容。MQTT 报文总共有 14 种类型,例如:
CONNECT
:客户端请求建立连接;
PUBLISH
:发布消息;
SUBSCRIBE
:订阅主题;
PINGREQ
/PINGRESP
:维持心跳连接;
DISCONNECT
:断开连接等。
补充:
😀请简要说下什么是回调函数,有什么用途?
把一个函数作为参数传进去,等某个时机到了,这个函数就会被“回调执行”。
它广泛用于异步事件处理、硬件中断响应、任务完成通知等场景,提高了程序的灵活性和可扩展性。
比如 STM32 中定时器中断处理函数就是一种典型的回调函数。
🫥只用了两根数据线和一根地线实现全双工通信的串口,是异步串口还是同步串口?
异步串口(Asynchronous Serial Port)
原因如下:
异步通信 不依赖共享的时钟信号,发送方和接收方通过 起始位、数据位、校验位和停止位 来完成数据同步。
使用的线少:只需要 TX(发送)、RX(接收)和 GND;
全双工能力:TX/RX 各自独立,支持发送和接收同时进行;
常见标准:如 UART、RS-232、RS-485 等都属于异步串口通信方式。
😐芯片的GPIO有哪些状态,各种状态进行描述下差异?
😉IIC有几个硬件IO,协议中的起始信号,ack信号是请描述下?
I²C 仅使用 两根信号线:
SCL(Serial Clock Line):时钟线
SDA(Serial Data Line):数据线
这两条线都是 开漏结构,需要外部上拉电阻。
I²C 协议中关键信号描述:
1.起始信号(Start Condition)
定义:在 SCL为高电平时,SDA从高变低。
2.停止信号(Stop Condition)
定义:在 SCL为高电平时,SDA从低变高。
3.应答信号(ACK/NACK)
ACK(应答):
由接收方在 第9个时钟周期拉低SDA 表示成功接收数据。
NACK(非应答):
接收方 不拉低 SDA(保持高电平),表示数据接收失败或终止传输。
使用时机:每个字节传输完毕后,发送方会等待接收方给出 ACK。
🤗什么是的 ADC,实际产品中有哪些设备的哪些功能是使用ADC来实现的?
ADC(Analog-to-Digital Converter),即模数转换器,是将模拟信号(连续变化)转换为数字信号(离散值)的电路模块。
😉DMA的用途是什么?有什么优势?
DMA(Direct Memory Access,直接内存访问) 是一种由 外设或硬件控制器 直接访问系统内存,而不需要 CPU 参与数据搬运的机制。
DMA 的主要用途:
在外设与内存之间自动搬运数据,如:
ADC 采集数据后自动写入内存;
串口、SPI、I2C 接收/发送大量数据;
内存到内存的数据拷贝。
DMA 的优势:
释放 CPU 资源:
不再由 CPU 手动搬运每个字节,CPU 可去执行其他任务,提高效率。速度快、延迟低:
DMA 控制器可并行于 CPU 工作,具有更快的传输速率和响应能力。数据量大时效率更明显:
适合批量数据传输,如图像数据、音频流等。节能高效:
CPU 空闲时功耗更低,适合低功耗设计需求。
😚什么是中断,当触发中断后,系统会做哪些事情?
中断(Interrupt) 是嵌入式系统或处理器在运行过程中,由外部或内部事件触发的一种打断当前程序执行的机制,它允许系统及时响应外设或异常事件。
中断触发后系统会做什么?(即:中断处理流程)
当中断发生时,系统大致会执行以下几个步骤:
1.保存现场
自动或手动将当前 CPU 的 寄存器、程序计数器(PC)、堆栈指针(SP) 等保存到栈中,确保返回后可以继续原程序。
2.切换上下文(进入中断服务程序)
跳转到对应的中断向量地址,执行 中断服务函数 ISR(Interrupt Service Routine)。
3.处理中断
在 ISR 中执行对应的逻辑,例如读取外设数据、清除中断标志等。
4.恢复现场
中断处理完毕后,从栈中恢复寄存器与程序计数器状态。
5.返回中断前的程序继续执行
恢复到中断前的代码继续运行。
☺️请分别简述万用表、示波器、逻辑分析仪的用途和特点是什么?
万用表(Multimeter)
用途:用于测量电压、电流、电阻、电容、通断、电感、二极管等基本电气参数。
特点:数字万用表精度较高,但只能显示静态的数值,不能观察波形;
示波器(Oscilloscope)
用途:用于实时观察电压随时间变化的波形;
常用于调试 模拟信号、PWM、电源信号、通信波形(如 UART/SPI) 等。
特点:能直观显示信号波形,是动态信号调试的核心工具;
逻辑分析仪(Logic Analyzer)
用途:专用于分析数字信号(高/低电平);
特点:以“0/1逻辑电平变化”为主,不显示模拟电压;
适用于多通道并发、长时间逻辑状态分析;
通常比示波器便宜,但不能观测模拟波形。
🙂请描述C语言中什么时候会使用到栈内存,什么时候会使用到堆内存。
栈内存用于存储函数的参数、返回地址、局部变量等临时数据,由编译器自动分配和释放,速度快但空间有限;
堆内存则由程序员通过如
malloc
或new
进行动态分配,适用于需要跨函数、生命周期较长或大小不确定的数据,但需手动释放,管理不当易导致内存泄漏。
🤗请描述C语言中volatile的作用和用途。
在 C 语言中,
volatile
是一个 类型修饰符,它的作用是告诉编译器:这个变量的值可能会被程序之外的因素(如硬件或其他线程)改变,因此每次使用都要重新从内存中读取,不要优化或缓存它。
不加 volatile 可能会出现的问题:
编译器可能将变量优化到寄存器中,导致读取到的不是最新值;
死循环中变量值被中断或外设修改,但程序因缓存旧值而无法退出。
🤩递归函数如何实现,有哪些优缺点?
递归函数是函数直接或间接调用自身来解决问题的编程方式,常用于将一个大问题拆解成结构相似的子问题。
优点:代码简洁,逻辑清晰,适用于树形结构、分治问题、回溯算法等。如斐波那契、汉诺塔、DFS 等。
缺点:
内存消耗大:每次调用都会占用栈空间,深度过大可能造成栈溢出。
效率较低:部分递归会重复计算(如朴素斐波那契)。
调试困难:递归层级深时,不易跟踪错误。
🤔请描述C语言的头文件有哪些作用和用途。
头文件(Header File)是以
.h
结尾的文件,主要用于声明函数、变量、宏、结构体等接口信息,方便多个源文件共享和调用,避免重复编写和出错。
🫡请实现函数yoid *memmove(void *dest,const void *src, unsigned incount)?
题目:请实现函数yoid *memmove(void *dest,const void *src, unsigned incount),功能:由src所指内存区域复制count个字节到dest所指内存区域。
#include <stdio.h>
void *memmove(void *dest, const void *src, unsigned int count) {
unsigned char *d = (unsigned char *)dest;
const unsigned char *s = (const unsigned char *)src;if (d == s || count == 0) {
return dest; // 地址相同或长度为 0,无需操作
}if (d < s) {
// 前向拷贝:从前往后,适用于目标在源前方
while (count--) {
*d++ = *s++;
}
} else {
// 后向拷贝:从后往前,适用于目标在源后方,有重叠风险
d += count;
s += count;
while (count--) {
*(--d) = *(--s);
}
}return dest;
}
更多推荐
所有评论(0)