嵌入式面试常问题32
指针函数和函数指针的区别:
指针函数本质上是一个函数,只不过该函数的返回值是一个指针类型。函数指针是一种指针,它指向一个函数。
指针的大小怎么算:
char* int* float*:在32位系统中为4位 64位系统是8位
size of 和strlen的区别;
sizeof:它是一个运算符,并非函数。其作用是在编译阶段计算数据类型或者变量所占用的字节数。
strlen:它是一个标准库函数,定义在 <string.h>(C 语言)或者 <cstring>(C++ 语言)头文件中。此函数用于计算以 '\0' 结尾的字符串的实际长度。
c语音中内存分配的方式有几种:
在 C 语言里,主要有三种内存分配方式,分别是静态内存分配、栈内存分配和堆内存分配,
struct 和union的区别:struct
结构体的每个成员都有自己独立的内存空间。结构体的总大小是其所有成员大小之和,同时可能会存在内存对齐的情况,以满足特定硬件平台的要求,提高内存访问效率。
例如,一个包含 int(通常 4 字节)和 char(1 字节)的结构体,考虑内存对齐后,其大小可能是 8 字节(假设按 4 字节对齐)。
union
共用体的所有成员共享同一块内存空间,这块内存空间的大小由共用体中最大的成员决定。
例如,一个包含 int(通常 4 字节)和 char(1 字节)的共用体,其大小为 4 字节,因为 int 是最大的成员。
- STM32启动过程详解?
STM32 的启动过程可以分为以下几个主要阶段:
硬件上电复位:当 STM32 芯片上电或者复位引脚被触发时,硬件会进行复位操作。复位后,CPU 会从特定的地址开始执行代码。
加载向量表:STM32 的向量表存储了一系列中断服务程序的入口地址,位于内存的起始地址(通常为 0x00000000)。复位后,CPU 会从向量表中读取栈顶地址和复位向量地址。栈顶地址用于初始化主栈指针(MSP),复位向量地址则是程序开始执行的起始地址。
初始化堆栈指针:CPU 将读取到的栈顶地址赋值给主栈指针(MSP),为后续的函数调用和局部变量分配内存做好准备。
跳转到复位处理函数:CPU 根据复位向量地址跳转到复位处理函数(通常是Reset_Handler)。在复位处理函数中,会进行一系列的初始化操作,如初始化全局变量、配置系统时钟、初始化外设等。
调用系统初始化函数:在复位处理函数中,通常会调用SystemInit函数来配置系统时钟。该函数会根据用户的配置,设置时钟源、分频系数等参数,使系统时钟达到所需的频率。
跳转到主函数:完成系统初始化后,程序会跳转到main函数,开始执行用户编写的应用程序代码。
- 中断优先级管理及嵌套?
中断优先级管理
STM32 的中断优先级分为抢占优先级和子优先级。
抢占优先级:具有高抢占优先级的中断可以打断正在执行的低抢占优先级的中断,实现中断嵌套。
子优先级:当两个中断的抢占优先级相同时,子优先级高的中断先执行。如果两个中断的抢占优先级和子优先级都相同,则按照中断向量表中的顺序依次执行。
中断嵌套
中断嵌套是指在一个中断服务程序执行过程中,更高优先级的中断可以打断当前的中断服务程序,转而执行更高优先级的中断服务程序。当更高优先级的中断处理完成后,再返回继续执行被打断的中断服务程序。
配置步骤
设置中断分组:通过NVIC_PriorityGroupConfig函数设置中断分组,确定抢占优先级和子优先级的位数。
配置中断优先级:对于每个中断源,使用NVIC_Init函数配置其抢占优先级和子优先级。
- DMA工作原理及应用场景?
工作原理
DMA(Direct Memory Access,直接内存访问)是一种无需 CPU 干预,直接在内存和外设之间进行数据传输的技术。其工作原理如下:
初始化:CPU 配置 DMA 控制器,设置源地址、目标地址、数据长度、传输方向等参数。
请求触发:当外设(如串口、ADC 等)有数据需要传输时,会向 DMA 控制器发送请求信号。
数据传输:DMA 控制器接收到请求信号后,接管总线控制权,直接在内存和外设之间进行数据传输,无需 CPU 干预。
传输完成:当数据传输完成后,DMA 控制器会向 CPU 发送中断信号,通知 CPU 数据传输已经完成。
应用场景
高速数据传输:如音频、视频数据的传输,使用 DMA 可以提高数据z传输效率,减轻 CPU 的负担。
大批量数据搬运:在需要将大量数据从一个内存区域复制到另一个内存区域时,使用 DMA 可以节省 CPU 时间。
外设与内存的数据交互:如 ADC 采集数据、SPI 发送数据等,使用 DMA 可以实现数据的自动传输,提高系统的实时性。
- 定时器的工作模式及配置?
工作模式
STM32 的定时器有多种工作模式,常见的有以下几种:
定时模式:定时器按照设定的时间间隔产生中断,用于实现定时功能。
输入捕获模式:用于测量外部信号的脉冲宽度或频率。定时器可以捕获外部信号的上升沿或下降沿,并记录相应的计数值。
输出比较模式:用于产生特定频率和占空比的 PWM 信号。定时器可以将计数值与比较值进行比较,当计数值等于比较值时,输出引脚的电平会发生变化。
编码器模式:用于测量旋转编码器的位置和速度。定时器可以根据编码器的输出信号,自动更新计数值。
配置步骤
以定时模式为例,配置步骤如下:
使能定时器时钟:使用RCC_APBxPeriphClockCmd函数使能相应的定时器时钟。
初始化定时器:使用TIM_TimeBaseInit函数初始化定时器的基本参数,如预分频系数、自动重装载值等。
配置中断:如果需要使用定时器中断,需要使用NVIC_Init函数配置中断优先级,并使用TIM_ITConfig函数使能定时器中断。
启动定时器:使用TIM_Cmd函数启动定时器
- I2C、SPI、UART的区别及应用场景?
电气特性
I2C(Inter - Integrated Circuit):是一种两线式串行总线,使用 SDA(串行数据线)和 SCL(串行时钟线)两根线进行通信,采用开漏输出,需要外接上拉电阻。
SPI(Serial Peripheral Interface):通常使用四根线,分别是 SCK(时钟线)、MOSI(主出从入)、MISO(主入从出)和 SS(片选线),采用推挽输出。
UART(Universal Asynchronous Receiver - Transmitter):一般使用两根线,TXD(发送端)和 RXD(接收端),用于异步串行通信。
通信方式
I2C:是同步、半双工通信,通过主从模式进行数据传输,每个从设备有唯一的地址。
SPI:是同步、全双工通信,主设备通过片选线选择要通信的从设备。
UART:是异步通信,不需要时钟线,通过约定的波特率进行数据传输。
传输速率
I2C:标准模式下传输速率为 100kbps,快速模式可达 400kbps。
SPI:传输速率较高,可达几十 Mbps 甚至更高。
UART:传输速率范围较广,从几百 bps 到几 Mbps 不等。
通信距离
I2C:通信距离较短,一般在几米以内。
SPI:通信距离也较短,通常在电路板级通信。
UART:在合适的电平转换和抗干扰措施下,通信距离可以达到几十米甚至更远。
应用场景
I2C:常用于连接低速外设,如 EEPROM、传感器(温度传感器、加速度计等)、实时时钟芯片等。
SPI:适用于高速数据传输的场景,如 SD 卡、LCD 显示屏、高速 ADC/DAC 等。
UART:常用于设备之间的异步通信,如计算机与单片机、调制解调器与计算机等。
- CAN总线的特点及应用?
多主通信:CAN 总线是一种多主总线,总线上的任何节点都可以在任意时刻主动向其他节点发送数据。
错误检测和处理:CAN 总线具有完善的错误检测机制,包括位错误、填充错误、CRC 错误等,当检测到错误时,节点会自动重发数据。
高可靠性:采用差分信号传输,抗干扰能力强,适合在恶劣的工业环境中使用。
优先级仲裁:当多个节点同时发送数据时,CAN 总线通过标识符进行优先级仲裁,高优先级的节点优先发送数据。
传输速率:传输速率最高可达 1Mbps,通信距离与传输速率成反比。
应用
汽车电子:CAN 总线在汽车中广泛应用,用于连接发动机控制单元、车身控制模块、仪表盘等,实现各模块之间的通信和数据共享。
工业自动化:在工业控制系统中,CAN 总线用于连接各种传感器、执行器和控制器,实现设备之间的通信和协调控制。
智能建筑:用于智能家居系统中,连接各种智能设备,如灯光控制器、门窗传感器等,实现设备的集中控制和管理。
- Modbus协议的帧格式及异常处理?
帧格式
RTU 模式
起始位:至少 3.5 个字符时间的空闲时间。
地址码:1 个字节,用于标识从站地址。
功能码:1 个字节,指示要执行的操作,如读线圈、读寄存器等。
数据域:可变长度,包含具体的数据信息。
CRC 校验:2 个字节,用于检测数据传输过程中的错误。
结束位:至少 3.5 个字符时间的空闲时间。
ASCII 模式
起始符:“:”(冒号)。
地址码:2 个 ASCII 字符,用于标识从站地址。
功能码:2 个 ASCII 字符,指示要执行的操作。
数据域:可变长度,包含具体的数据信息,以 ASCII 字符表示。
LRC 校验:2 个 ASCII 字符,用于检测数据传输过程中的错误。
结束符:“CR LF”(回车换行)。
异常处理
当主站发送的请求出现错误或从站无法执行请求时,从站会返回异常响应。异常响应的帧格式与正常响应类似,但功能码的最高位会置 1,同时在数据域中包含一个异常码,指示异常的类型,常见的异常码有非法功能码、非法数据地址、非法数据值等。主站收到异常响应后,会根据异常码进行相应的处理,如重新发送请求、提示用户等。
- TCP/IP协议栈在嵌入式系统中的实现?
TCP/IP 协议栈在嵌入式系统中的实现
实现方式
完整协议栈实现:使用专门的 TCP/IP 协议栈软件,如 uIP、LwIP 等,这些协议栈提供了完整的 TCP/IP 协议功能,包括 ARP、IP、TCP、UDP 等。开发者可以根据需求进行配置和裁剪,将其移植到嵌入式系统中。
硬件实现:使用带有 TCP/IP 协议栈硬件支持的网络芯片,如 W5500、ENC28J60 等,这些芯片内部集成了 TCP/IP 协议栈,开发者只需要通过 SPI 或其他接口与芯片进行通信,即可实现网络通信功能。
实现步骤
选择合适的协议栈或硬件:根据嵌入式系统的资源和需求,选择合适的 TCP/IP 协议栈软件或网络芯片。
移植协议栈:如果使用软件协议栈,需要将协议栈移植到嵌入式系统中,包括配置编译环境、修改底层驱动代码等。
配置网络参数:设置嵌入式系统的 IP 地址、子网掩码、网关等网络参数。
编写应用程序:根据实际需求,编写基于 TCP/IP 协议的应用程序,如 HTTP 服务器、TCP 客户端等。
i2c简易时序图
启动信号:
SCL为高电平的时候,SDA由高电平向低电平跳变。结束信号:SCL为高电平的时候,SDA由低电平向高电平跳变。
应答信号:
I2C总线上的所有数据都是以8位字节传送的,发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功,对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P。
写时序:
开始信号:主机+从设备地址+写命令,从机应答,应答成功,表示有这个设备,然后主机+设备内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址,主机写入数据,从机应答,是否继续发送,不发送的话,发送停止信号P。
读时序:
要想读设备,首先要知道将要所读取设备的地址告诉从设备,从设备才能将数据放到(发送)SDA上使主设备读取,从设备将数据放入SDA上的过程,由硬件主动完成,不用人为的写入。所以首先先写入从机地址,然后+写控制命令,从机应答,应答成功,表示有这个设备,然后写入内部寄存器地址,此时不用再加写命令控制字,从机应答,应答成功,表示设备内有这个地址。然后主机继续发出:写入从机地址,然后+读命令,从机应答,应答成功,此时便可以读取数据了,从设备已经将数据放入到SDA上了。地址跟设备已经验证了,不用再进行验证。
SPI通信的四种模式:
SPI通信有4种不同的操作模式,不同的从设备可能在出厂是就是配置为某种模式,这是不能改变的;但我们的通信双方必须是工作在同一模式下,所以我们可以对我们的主设备的SPI模式进行配置,通过CPOL(时钟极性)和CPHA(时钟相位)来
控制我们主设备的通信模式,具体如下:
时钟极性(CPOL)定义了时钟空闲状态电平:
- CPOL=0,表示当SCLK=0时处于空闲态,所以有效状态就是SCLK处于高电平时
- CPOL=1,表示当SCLK=1时处于空闲态,所以有效状态就是SCLK处于低电平时
时钟相位(CPHA)定义数据的采集时间。
- CPHA=0,在时钟的第一个跳变沿(上升沿或下降沿)进行数据采样。,在第2个边沿发送数据
- CPHA=1,在时钟的第二个跳变沿(上升沿或下降沿)进行数据采样。,在第1个边沿发送数据
SPI的三种模式
SPI工作在3中模式下,分别是运行、等待和停止。
运行模式(Run Mode)
这是基本操作模式
等待模式(Wait Mode)
SPI工作在等待模式是一种可配置的低功耗模式,可以通过SPICR2寄存器的SPISWAI位进行控制。在等待模式下,如果SPISWAI位清0,SPI操作类似于运行模式。如果SPISWAI位置1,SPI进入低功耗状态,并且SPI时钟将关闭。如果SPI配置为主机,所有的传输将停止,但是会在CPU进入运行模式后重新开始。如果SPI配置为从机,会继续接收和传输一个字节,这样就保证从机与主机同步。
停止模式(Stop Mode)
为了降低功耗,SPI在停止模式是不活跃的。如果SPI配置为主机,正在进行的传输会停止,但是在CPU进入运行模式后会重新开始。如果SPI配置为从机,会继续接受和发送一个字节,这样就保证了从机与主机同步。
嵌入式系统的启动流程设计?
嵌入式系统的启动流程通常包含以下几个主要阶段:
硬件上电复位
当系统上电或者复位引脚被触发时,硬件进行复位操作。此时处理器的寄存器被初始化为默认值,程序计数器(PC)被设置为复位向量地址,系统从该地址开始执行代码。
加载向量表
向量表是一系列中断服务程序入口地址的集合,存于内存起始地址。复位后,处理器从向量表读取栈顶地址和复位向量地址。栈顶地址用于初始化主栈指针(MSP),复位向量地址则是程序起始执行地址。
初始化硬件
时钟系统:配置系统时钟源、分频系数等,使系统时钟达到所需频率,为后续硬件和软件运行提供稳定时钟信号。
存储器:初始化片内和片外存储器,如 SRAM、Flash 等,确保存储器正常工作,为程序和数据存储提供支持。
外设:初始化各类外设,如 GPIO、UART、SPI 等,根据需求设置外设工作模式和参数。
初始化软件环境
全局变量:对全局变量进行初始化,确保程序运行时全局变量有正确的初始值。
堆栈:进一步配置堆栈,保证函数调用和局部变量分配内存正常。
中断系统:使能中断控制器,配置中断优先级和中断向量表,为中断处理做好准备。
跳转到应用程序
完成硬件和软件环境初始化后,程序跳转到主函数(main),开始执行用户编写的应用程序代码。
低功耗设计的关键技术?
电源管理技术
动态电压频率调整(DVFS):根据系统负载动态调整处理器的电压和频率。在低负载时降低电压和频率,减少功耗;在高负载时提高电压和频率,保证系统性能。
电源模式切换:嵌入式系统通常具有多种电源模式,如运行模式、睡眠模式、待机模式等。在系统空闲时,切换到低功耗模式,关闭不必要的模块和外设,降低功耗。
外设管理技术
外设时钟控制:只在需要使用外设时开启其时钟,使用完毕后及时关闭,减少外设功耗。
外设低功耗模式:许多外设具有低功耗模式,如 UART 的休眠模式、SPI 的停止模式等。在不使用外设时,将其设置为低功耗模式。
软件优化技术
算法优化:采用高效算法,减少处理器运算量和执行时间,降低功耗。
任务调度优化:合理安排任务执行顺序和时间,避免处理器空转,提高系统效率,降低功耗。
看门狗的工作原理及应用?
工作原理
看门狗(Watchdog)是一种定时器电路,其工作原理如下:
系统启动时,看门狗定时器开始计时。
在程序正常运行过程中,需要在规定时间内对看门狗定时器进行清零操作,即 “喂狗”。
如果程序由于某种原因(如硬件故障、软件死循环等)无法在规定时间内 “喂狗”,看门狗定时器就会溢出,产生复位信号,使系统复位。
应用
防止程序跑飞:当程序受到干扰出现死循环或跑飞时,看门狗能够及时复位系统,使程序重新开始运行,提高系统的稳定性。
监控系统运行状态:可以通过设置不同的 “喂狗” 周期,监控系统的运行状态。如果系统在规定时间内无法完成任务并 “喂狗”,则说明系统可能出现故障。
嵌入式系统的可靠性设计?
硬件可靠性设计
冗余设计:采用冗余电源、冗余处理器等,当一个部件出现故障时,另一个部件能够继续工作,保证系统正常运行。
电磁兼容性(EMC)设计:合理布局电路板,采用屏蔽、滤波等措施,减少电磁干扰,提高系统的抗干扰能力。
热设计:合理设计散热结构,确保系统在高温环境下正常工作,避免因过热导致器件损坏。
软件可靠性设计
容错设计:采用容错算法和数据校验机制,如 CRC 校验、奇偶校验等,检测和纠正数据传输和处理过程中的错误。
异常处理:在程序中添加异常处理代码,对可能出现的异常情况(如除数为零、数组越界等)进行处理,避免程序崩溃。
软件冗余设计:采用软件冗余技术,如 N 版本编程、恢复块等,提高软件的可靠性。
系统可靠性设计
故障诊断和恢复:在系统中添加故障诊断模块,实时监测系统的运行状态,当检测到故障时,能够自动进行恢复操作。
备份和恢复机制:定期对系统数据进行备份,当系统出现故障时,能够快速恢复数据,减少损失。
#嵌入式面试#