目录

🕐什么是字节对齐?有什么作用?

🕑列举 ARM 处理器的主要特点?

🕒ARM 有多少个寄存器?

🕓ARM 处理器的 7 种工作模式分别是什么?

🕔ARM 内核和 ARM SoC 处理器的异同是什么?

🕕ARM 通用寄存器中 3 个特殊寄存器的名字和作用是什么?

🕖描述 CPSR 寄存器中相关 Bit 的含义和作用?

🕗什么是立即数?使用时的注意要点是什么?

🕘什么是处理器现场?如何保存现场?

🕙什么是满堆栈和空堆栈?

🕚什么是满递减栈、空递减栈、满递增栈、空递增栈?

🕛ATPCS 规定的参数传递规则是什么?

🕜软件中断与硬件中断的区别是什么?ARM 提供的软件中断指令是什么?

🕝什么是异常?

🕞ARM 架构支持的七种异常类型是什么?

🕟boot loader 的主要作用是什么?

🕠U-Boot 是如何启动内核的?

🕡U-Boot 中 bootcmd 和 bootargs 分别有什么作用?

🕢vmlinux、Image、zImage、uImage 的区别是什么?

🕣Linux 内核中 Makefile、Kconfig、.config 的关系是什么?

🕤简述 Linux 内核的总体启动流程。

🕥简述 Linux 开发板的启动过程。

🕦Linux 中字符设备和块设备的主要区别是什么?

🕧为什么开发板一般不需要静态库?

🕐Linux 有哪几种驱动类型?

🕑Linux 中编写一个字符设备驱动程序的基本步骤?

🕒什么是设备树?设备树的作用是什么?

🕓什么是文件系统?其功能包括哪些部分?

🕔什么是根文件系统?

🕕GCC 编译器编译的完整流程是什么?各阶段的作用是什么?

🕖在 make menuconfig 界面下,驱动的三种状态(Y、N、M)分别表示什么含义?

🕗有没有做过 Linux 的驱动开发?

🕘FreeRTOS 有哪些特征?

🕙FreeRTOS 中任务状态有哪些,怎么转换的?

🕚FreeRTOS 任务默认调度方式是什么?

🕑freertos任务调度流程是什么?

🕛FreeRTOS 中任务的优先级如何设置?可以设置多少级?每级优先级的含义?

🕜为什么 FreeRTOS 应用程序中必须使用空闲任务?

🕝什么是可剥夺型内核(Preemptive Kernel)?适用场景是什么?

🕞什么是不可剥夺型内核(Non-preemptive Kernel)?适用场景是什么?

🕟FreeRTOS 抢占式任务调度机制适用于哪些场景?

🕠FreeRTOS 中 IPC可以通过哪些方式实现?

🕡FreeRTOS 中任务之间的通讯方式有哪些?

🕢IPC 通信和任务之间通讯是一个意思吗?

🕣操作系统中的自旋锁和信号量有什么区别?

🕤什么是临界资源和临界区?为什么要有临界区?

🕥在 FreeRTOS 中,互斥量(Mutex)和信号量(Semaphore)的区别?

🕦说一下FreeRTOS中的优先级反转?有什么危害?

🕐什么是可重入函数(Reentrant Function)?

🕑FreeRTOS 的内存管理是如何实现的?

🕒FreeRTOS 中断的工作流程知道吗?

🕓前后台程序与实时操作系统的区别是什么?

🕔实时系统的基本特性有哪些?

🕕操作系统(如 Linux)中进程的状态有哪些?FreeRTOS 中任务的状态有哪些?

🕖什么是死锁?在操作系统或并发编程中,如何避免死锁?

🕗如何获取并搭建一个 FreeRTOS 项目的运行环境?

🕘什么是 UART?它是如何进行通信的?UART 的工作原理及其数据包结构是怎样的?

🕙串口异步通信中的一个字符帧由哪些部分组成?

🕚说一下RS-232?

🕛说一下RS-485?

🕜串口和并口的区别是什么?

🕝I2C 总线的基本原理、特点及应用场景。

🕝说一下SPI 总线的通信原理、特点和应用场景。

🕞什么是 CAN 总线?请简述其工作原理、特点和应用场景。

🕟什么是 MODBUS?请简述其工作原理 和 应用场景。

🕠说一下MODBUS 协议模式?

🕡LoRa 是什么,其工作原理是什么?应用场景?

🕢什么是 LoRaWAN?和 LoRa 有什么区别?

🕣请简述 WiFi 的主要工作模式及其典型应用场景。

🕤说一下蓝牙是什么?有几种工作模式?

🕥常见的近距离无线通信协议?各自的特点和应用场景是什么?

🕒STM32 中常见通信协议(外设协议)?

🕧说一下 STM32 中的中断?为什么需要中断,有哪些中断,大概怎么做?

🕐STM32 中定时器(Timer)的类型、主要功能、使用场景及配置方法?

🕑GPIO是什么,STM32 中 GPIO 的输入输出模式分类及其适用场景?

🕑什么是 ADC?常见的 ADC 转换模式有哪些?

🕒ADC 采样精度由什么决定?

🕓什么是 PWM?请简述其工作原理、生成方式以及常见应用场景?

🕔请简述 PWM的核心参数及其作用?

🕕什么是 EEPROM?常见应用场景?

🕖什么是 RTC?它的作用和常见应用是什么?

🕗什么是看门狗(Watchdog)?它的工作原理是?

🕘说一下独立看门狗和窗口看门狗的区别?

🕙什么是单工、半双工和全双工?

🕚什么是时钟源?什么是 PLL?起什么作用?

🕛在单片机中,地的种类有哪些?

🕜说一下CPU、MPU、MCU、SoC、SoPC是什么?

🕝FPGA 和 ASIC 的概念以及两者的区别是什么?

🕞ROM 和 RAM 的区别及类型是什么?

🕟精度和分辨率的区别是什么?

🕡传感器的输出引脚是高阻抗好还是低阻抗好?为什么?

🕗解释通信中的基本概念:主机与从机、连续方式、指令方式。

🕤简述 OSI 七层模型。

🕥简述 TCP/IP 四层模型?

🕚在嵌入式系统中,如何进行数据采集与处理?

🕛解释嵌入式系统中的错误处理机制。

🕐MQTT(Message Queuing Telemetry Transport)怎么保证传输效率?

🕑MQTT消息质量等级有哪些?分别有什么涵义?

🕒MQTT报文格式?最小报文?举出一些报文的类型?


🕐什么是字节对齐?有什么作用?

指在内存中存储数据时,按照特定规则对齐数据地址。
它的目的是提高内存访问效率,避免 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),它完成硬件初始化并加载内核镜像与启动参数,随后跳转到内核入口函数。

内核从压缩镜像中解压自身,初始化中断、内存管理、设备驱动、文件系统等,最终挂载根文件系统并启动用户空间的第一个进程(通常是 initsystemd),至此完成系统启动。

🕥简述 Linux 开发板的启动过程。

首先,上电后执行 BootROM(固化在芯片中的初级引导程序),它加载并启动 BootLoader(如 U-Boot);

BootLoader 初始化基本硬件,加载内核镜像、设备树和启动参数;

然后控制权转交给 Linux 内核,内核完成系统初始化并挂载根文件系统,启动用户空间程序(如 initsystemd),最终进入系统正常运行状态。

🕦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 结构体

定义并实现 openreadwriterelease 等接口函数,用于处理用户空间请求。

 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),在运行时通过 insmodmodprobe 加载,支持动态插拔。

N(No)
不编译该驱动,最终不会包含在内核或模块中。

🕗有没有做过 Linux 的驱动开发?

是的,我有做过 Linux 驱动开发,主要涉及字符设备驱动和平台设备驱动。
具体工作包括:

  • 编写字符设备驱动,使用 register_chrdev 注册设备号,使用 file_operations 实现 openreadwrite 等接口;

  • 使用设备树匹配设备(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)

现在只有一把打印机(共享资源),只能一个人用,需要申请钥匙(互斥量)

步骤演示(未使用优先级继承时会发生的问题):

  1. 实习生(任务B)先来了,拿到了打印机钥匙,开始慢慢打印。

  2. 这时经理(任务A)来了,也要用打印机,但钥匙在实习生手里,于是他只能等着

  3. 正当实习生想把打印完,这时普通员工(任务C)来了,他虽然优先级比实习生高,但比经理低。

  4. 因为调度器默认按优先级安排工作,所以员工插队开始干活(抢占任务B)。

  5. 实习生继续被压着没机会释放打印机钥匙,经理只能一直等 → 优先级反转发生了!

引入互斥量的优先级继承机制后:

  1. 当经理(任务A)发现钥匙被实习生(任务B)拿着时,系统做了件事:

  2. 系统临时把实习生的优先级提升为和经理一样高

  3. 这样普通员工(任务C)就插不进队,实习生能立刻完成打印。

  4. 这样经理就不会因为「实习生+员工」这俩人组合拖延了自己的工作。

  5. 实习生释放钥匙,经理马上用上,实习生优先级恢复。

🕐什么是可重入函数(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 中的常见中断类型:

使用中断的基本流程:

  1. 开启外设时钟:

    __HAL_RCC_GPIOx_CLK_ENABLE();

  2. 配置外设为中断模式(如 EXTI):

    1. 配置 GPIO 为输入模式

    2. 设置为中断触发(上升沿/下降沿)

    3. 初始化 EXTI 线

  3. 使能中断并设置优先级:

    使用 HAL_NVIC_SetPriority()HAL_NVIC_EnableIRQ() 配置中断控制器 NVIC

  4. 编写中断服务函数(ISR):

    函数名通常为:void XXX_IRQHandler(void)

    在函数内部处理中断事件,并清除中断标志位

🕐STM32 中定时器(Timer)的类型、主要功能、使用场景及配置方法?

定时器类型(以 STM32F1/F4 为例):

主要功能:

  • 定时/计时功能:可配置为以固定周期触发中断

  • PWM 输出:用于电机控制、LED 调光等

  • 输入捕获:测量外部信号频率、脉宽

  • 输出比较:用于控制输出翻转或事件触发

  • 编码器接口模式:支持与编码器配合使用

使用流程:

  1. 打开时钟

  2. 配置定时器参数(如分频器、计数器模式、周期)

  3. 使能中断并配置中断优先级

  4. 开启定时器和中断

  5. 编写中断服务函数

应用场景:

  • 定周期任务调度(如 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 的优势:

  1. 释放 CPU 资源
    不再由 CPU 手动搬运每个字节,CPU 可去执行其他任务,提高效率。

  2. 速度快、延迟低
    DMA 控制器可并行于 CPU 工作,具有更快的传输速率和响应能力。

  3. 数据量大时效率更明显
    适合批量数据传输,如图像数据、音频流等。

  4. 节能高效
    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语言中什么时候会使用到栈内存,什么时候会使用到堆内存。

栈内存用于存储函数的参数、返回地址、局部变量等临时数据,由编译器自动分配和释放,速度快但空间有限;

堆内存则由程序员通过如 mallocnew 进行动态分配,适用于需要跨函数、生命周期较长或大小不确定的数据,但需手动释放,管理不当易导致内存泄漏。

🤗请描述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;
}
 

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐