嵌入式八股文-ARM

网上有很多八股文 但还是想自己总结以下 部分内容有借鉴这位博主嵌入式八股文总结(ARM篇)-CSDN博客

一、I2C通信

1.I2C基本概念

I2C一共有两根通信线:时钟线SCL(Serial Clock)、数据线SDA(Serial Data),同步、半双工。

如图1所示,在空闲时时钟线和数据线都处于高电平状态。

(1)起始条件:SCL高电平期间,SDA从高电平切换到低电平。

(2)终止条件:SCL高电平期间,SDA从低电平切换到高电平

(3)应答信号:
• 发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据 0 表示应答,数据 1 表示非应答
• 接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据 0 表示应答,数据 1 表示非应答(主机在接收之前,需要释放 SDA )

(4)在SCL高电平时为数据采样阶段,数据线SDA必须保持稳定。SCL为低电平时为数据放置阶段,数据线SDA才能变化。这样规定有效的区分了数据采样阶段和数据放置阶段。

(5)指定地址写数据:•对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)如图2所示,

I2C设备地址多为7位地址(也有10位地址)。

发送起始信号后紧跟着的是 7位地址+1位读写位(0表示写数据,1表示读数据;)

接收到应答信号后,发送寄存器地址。然后就可以发送数据了,发送完成后为终止信号。若要发送多个字节的数据,只用接收到应答信号后持续发送数据,若需要停止发送终止信号。

(6)指定地址读数据:指定地址读的前两位和写数据一样,首先发送从机地址(地址+0写数据位)+寄存器地址,然后再发送一次从机地址(这里是地址+1读数据位),此时就能读取指定地址下的数据,读取完成后发送终止信号。

2.I2C常问问题

(1)I2C为什么需要加上拉电阻,一般为多大,为什么需要使用开漏输出?

I2C支持总线挂载多设备(一主多从、多主多从),当两个设备同时抢占总线时,当主设备 A 输出高电平(1),主设备 B 输出低电平(0)时,会形成 电源到地的短路路径,烧毁器件!

而开漏输出无高电平状态,当设备拉低总线时就获得控制权,此时就需要增加上拉电阻,赋予高电平状态。

上拉电阻大小一般如图所示:

(2)I2C通信失败该怎样排查问题?

  • 硬件:电源、地、上拉电阻(值是否合适?存在吗?)、线路连接(短路/断路)、总线电容是否过大。

  • 软件:SCL/SDA GPIO 配置是否正确(开漏输出?上拉使能?)、I2C 外设初始化参数(速率、地址)、时序是否符合规范(特别是启动/停止/ACK)。

  • 工具:用示波器或逻辑分析仪抓取 SCL/SDA 波形(最有效!),查看是否有起始/停止/ACK/数据波形,电平是否正常,时序是否满足要求。

  • 设备:确认从机地址是否正确、从机是否正常工作(电源、复位)、是否存在地址冲突。

(3)什么是I2C死锁,怎样解决?

现象:I2C死锁就是时钟线SCL一直处于高电平,数据线SDA一直处于低电平。

原因:从机 拉低数据线SDA时(发送应答信号给主机时或发送数据0时)主机意外复位,主机复位后时钟线SCL就为高电平了,此时,SCL为高电平而SDA为低电平,主机就以为有其他设备占有了总线,而SCL为高电平时 数据位SDA不允许有变化,意思是:主机就一直等待时钟线SDA拉高,而从机就一直等待时钟线SCL拉高 就造成了死锁的现象。

解决方法:1.选择带有复位功能的从设备,复位后SDA被拉高。2.设置时钟延展时间:当检测到SDA低电平超过预设时间,超时则强制复位并终止传输。3.主机检测SDA被拉低超过指定时间后,主动复位从设备,前提需要主机具有控制有复位引脚的从设备

(4)I2C最多可以挂载多少个设备?

理论上可以挂载112个设备(七位从机地址)

AI给的,理论可以挂载2^7 - 不可用地址 = 112个

但是I2C协议没有限制总线上的最大设备数,但是规定了总线电容不得超过400pF,所以实际上I2C总线上的设备数推荐不超过8个。

(5)常见的I2C设备有什么?你用过那个?遇到过什么问题,怎样解决的?

常见的有:EEPROM芯片、MPU6050、一些OLED屏

EEPROM和MPU6050是我经常使用的,其中EEPROM是一款**可擦可编程只读存储器,**型号为24C02,当时在完成BootLoder代码时需要存储一些重要的标志位,不允许掉电丢失,所以将其存储到EEPROM芯片当中。

问题:当时遇到了写入后读取数据错误。

  • 主机连续写入 64 字节(页写)后立即读取,返回的数据随机错误(部分字节为0xFF或旧数据)。

  • 根本原因:跨页写入时未拆分数据(24LC256 页大小为64字节),导致地址回卷(Address Wrapping)。

  • 解决方案:强制页写拆分;

(6)你写IIC驱动的时候,速率是多少?

在使用硬件IIC的时候,我一般选择标准模式(速率为100KHz),但在需要高频读取数据时,总线可能会成为瓶颈,导致数据丢失或延迟,这时我会选择快速模式(400KHz)。

在使用软件IIC的时候,不需要想硬件IIC那样设置固定速率,软件IIC速率完全由自己决定。例如在软件IIC写SCL或SCK的时候我会选择延迟个10us,防止时序频率超过要求。

二、SPI通信

1.SPI通信基本概念

SPI通信模式一共有四根通信线:

SCK(Serial Clock):时钟线

MOSI(Master Output Slave Input):主机输出从机输入

MISO(Master Input Slave Output):主机输入从机输出

SS(Slave Select):片选线

SPI具有两根数据线 所以支持同时收发数据 并且具有时钟线 属于全双工同步通信

如图所示:

•所有SPI设备的SCK、MOSI、MISO分别连在一起

•主机另外引出多条SS控制线,分别接到各从机的SS引脚

•输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

(1)起始条件:只用将片选信号拉低 终止条件:将片选信号拉高

(2)工作模式:SPI一共有四种工作模式

时钟极性决定SCK的电平起始电平 相位决定采样时刻

以模式0为例,如图所示:我们可以看到MISO刚开始为高阻态,是因为对于主机来说,未被使能的从机是输出到主机的,若同时开始会造成冲突,则在SS未被使能的情况下,MISO处于高阻态。

片选信号先拉低 在SCK的第一个上升沿采样数据,在第二个边沿放数据,第三个边沿采样数据,直到数据传输完成,SS拉高结束。

2.SPI常见问题

(1)SPI可以去掉那些线?

SPI有四根线:SCLK、MISO 、MOSI、CS。当只需要主机向从机发送指令,而不需要从机回复数据时,MISO信号线就可以去掉;当主机只想读取从机的数据,而不需要向从机发送指令时,MOSI就可以去掉;如果只有一个从机,那么CS片选线也可以不要,直接将其固定为有效电平,一直处于使能的状态。需要注意的是,时钟线不能去掉,发送数据和接收到数据时都需要使用时钟线进行数据采样。

(2)SPI和I2C的差别是什么?

SPI只有两根线而SPI具有四根线 I2C的通信则要复杂一点

(3)SPI通信失效如何排查?

(4)面试管问你常用的SPI设备有什么?你遇到过什么问题?是怎样解决的?

我用过的SPI设备有:存储芯片W25Q64和SPI OLED屏幕

在写BootLoder程序时,用W25Q64当作外部Flash使用,用于存储不同的APP代码和阿里云下发的APP代码。但是在写外部Flash的时候总是遇到偏移量不好计算的问题。具体来说,因为我是通过Xmode协议一片一片写入Flash当中的,每片数据的大小固定,但不同APP代码的总长度不一样,比如数据写入到某个地址后,下一片数据的起始偏移量需要准确衔接,可一旦某片数据的处理出现偏差,后续分片的偏移量都会出错,导致APP无法正常加载。

为了解决这个问题,我在代码中加入了分片校验和偏移量预检查机制。每处理一片数据前,先检验该片的序号是否连续。

还有个最简单的问题,我写入Flash时后读取总为FF,结果发现是片选没使能。

三、串口通信

1.基本概念

•串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信

•单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力

普通串口有两根线 发送TX 接收RX •TX与RX要交叉连接 当只需要单向传输时只用一根通信线当电当电平标准不一致时,需要加电平转换芯片,如图所示。

串口参数及时序:

(1)波特率:串口通信的速率

(2)起始位:标志一个数据帧的开始,固定为低电平

(3)数据位:数据的有效载荷,1为高电平,0为低电平,低位先行

(4)校验位:用于数据验证,根据数据位计算得来

(5)停止位:用于数据帧间隔,固定位高电平

2.RS485基本理念

RS485用于工业和通信领域的串行通信标准,具有通信距离长、多点通信、抗干扰能力强的特点。

(1)差分信号:RS485有两根信号线(通常为A或B,或者Data+和Data-),RS485是通过两根线之间的电压差来表达传输逻辑,通常A B 差>200mv代表逻辑1,A B差<200mv代表逻辑0。 相比单端信号,差分信号对噪声的抗干扰能力更强,因为噪声通常影响两条线的相同程度,因此它们之间的电压差不会受到噪声的显著影响。

(2)多点总线拓扑:RS485设计用于连接多个设备到同一条通信总线上。

(3)半双工模式:这是常见的RS485应用模式,所有设备共享一对信号线,同一时间只能有一个设备发送数据(作为发送器),其他设备只能接收(作为接收器)。需要一个**通信协议(如Modbus)**来管理那个设备在何时获得总线控制权。

这里的RS485是硬件层协议:用于解决逻辑电平0和1的可靠传输

Modbus协议 是软件层面:解决传输目的,解决为什么两者要传输的协议,与之前的I2C和SPI物理层协议不同,Modbus协议是应用层协议,

3.串口通信常见问题

(1)面试官问在处理串口数据时你是怎样设计处理方案的?

1.在非裸机的项目中,我通常在中断中接收数据,任务中处理数据。具体来说,在中断服务程序中(ISR)仅将数据存入缓冲区中,再通过同步信号(如队列、任务通知、信号量)唤醒处理任务。任务在没有唤醒前一直处于阻塞状态,等到ISR发送数据到达信号,接收到信号后,从缓冲区取出数据进行数据处理(解包、校验、执行业务逻辑)。

2.在裸机项目中,可以采用中断存储数据+状态机解析的方案。具体来说,就是在ISR中使用环形缓冲器暂存数据,接收完数据后置位标志位。循环中检查标志位,状态机实现协议解析。

四、什么是回调函数?

回调函数就是一个通过函数指针来调用的函数。

  • 你把一个函数(B)的引用作为参数传递给另一个函数(A)。

  • 函数 A 执行完自己的任务后,回过头来调用(Call Back)你传给它的那个函数 B。

  • 所以,函数 B 就是回调函数。

五、中断函数

1.定义

中断函数,也叫中断服务程序(ISR - Interrupt Service Routine) ,是嵌入式系统中用于响应硬件中断的特殊函数。

2.常见的面试问题

(1)中断函数为什么需要快进快出

如果ISR执行时间过长,其他同等或更高优先级的中断无法及时得到响应,可能导致事件丢失。并且长时间处理中断会影响主程序的运行,影响系统整体性能和响应速度。

(2)如果中断处理需要做很多耗时的操作,你该怎么办?

在ISR中只做最紧急的事,如清除标志位、读取数据,然后通过设置标志位、发送信号量等方式通知主循环或任务来处理耗时的逻辑。

(3)volatile可以在中断函数中使用吗?一般怎样使用?

"volatile在中断中至关重要,主要用于修饰那些在中断服务程序主循环(或非ISR任务) 之间共享的全局变量。

六、嵌入式基于ROM运行和基于RAM运行有什么区别

基于ROM运行:程序代码直接在**非易失性存储器(如FLASH)**中被CPU读取和执行。

基于RAM运行:程序代码先从非易失性存储器复制到**易失性存储(RAM)**中,然后CPU再从RAM中读取并执行。

这里的"ROM"是现代嵌入式系统中Flash存储器的统称。

七、BootLoader/IAP

BootLoader:中文名为引导加载程序,是嵌入式系统中一段存储再非易失存储器(Flash)起始地址的底层程序,相当于启动管家。它负责在系统上电后初始化硬件,验证用户程序完整性,并决定是否跳转到APP执行。

八、介绍下TCP 连接中的"三次握手"和"四次挥手"

(1)三次握手定义

1.三次握手的目标是同步序列号,确保双方都准备好发送和接收数据。序列号是TCP实现可靠传输的关键。(同步服务器和客户端之间的通信)

①:客户端向服务器发送SYN=1(同步序列号),并随即生成一个初始序列号(seq=x),客户端状态由关闭(CLOSED)进入SYN-SENT(同步发送);

②:服务器收到并同意之后,服务器设置SYN=1和ACK=1(应答信号)并随机生成初始序列号(seq=y)。同时,将确认号设置为ack = x +1(客户端的序列号 + 1),表示已经收到客户端序列号了,希望下次从x+1的位置开始接收数据。

③:客户端收到服务器的包之后,向服务器发送一个确认包,ACK=1,将序列号设置为seq = x+1,(即第二次服务器希望的),再将确认号设置为ack = y +1,表示收到了服务器的序列号。最后客户端和服务器都进入连接模式。

简洁说:客户端:发送同步信号;服务器:收到了,你能接收到我的信息吗?客户端:我也收到了,连接成功可以开始通信了。

(2)四次挥手定义

四次挥手的目标是安全地、可靠地关闭双向数据流。因为TCP连接是全双工的,每个方向必须单独关闭。

①:主动关闭方(如客户端)发送一个TCP数据包。包中为FIN=1(完成标志位),一个序列号seq = u。客户端状态由已连接-终止等待1。

②:服务器收到后,发送确认包。包中为ACK=1,将确认号设置为ack = u + 1;序列号为 seq = v;

服务器由已连接-关闭等待;客户端状态由终止等待1-终止等待2;

此时TCP处于半关闭状态,客户端已无消息发送,服务器可能还有数据要送,此时为单端通信;

③此时,服务器还会发送一个包;关闭它与客户端的连接;包中为结束标志位FIN = 1,seq = w,确认号不变为 ack = u + 1;服务器状态由关闭等待-最后确认;

④:客户端接收到FIN后,发送确认包。包中为ACK = 1; seq = u + 1;ack = w + 1;

客户端从终止等待2-时间等待状态后,等待2MSL后才进入关闭状态。

服务器接收到ACK后就立即关闭。

简洁说:要关闭连接的话,主动连接方发送完成标志位(FIN),被动关闭方接收到后发送ACK(确认),被动关闭方再发送与主动方关闭连接的完成标志位(FIN),主动关闭方接收到后,发送ACK,确认双方断开连接,两者均进入到关闭状态。

相关推荐
17(无规则自律)10 小时前
深入浅出 Linux 内核模块,写一个内核版的 Hello World
linux·arm开发·嵌入式硬件
梁洪飞1 天前
内核的schedule和SMP多核处理器启动协议
linux·arm开发·嵌入式硬件·arm
代码游侠1 天前
学习笔记——Linux字符设备驱动
linux·运维·arm开发·嵌入式硬件·学习·架构
syseptember2 天前
Linux网络基础
linux·网络·arm开发
代码游侠2 天前
学习笔记——Linux字符设备驱动开发
linux·arm开发·驱动开发·单片机·嵌入式硬件·学习·算法
程序猿阿伟2 天前
《Apple Silicon与Windows on ARM:引擎原生构建与模拟层底层运作深度解析》
arm开发·windows
wkm9562 天前
在arm64 ubuntu系统安装Qt后编译时找不到Qt3DExtras头文件
开发语言·arm开发·qt
unicrom_深圳市由你创科技2 天前
基于ARM+DSP+FPGA异构计算架构的高速ADC采集卡定制方案
arm开发·fpga开发
松涛和鸣2 天前
DAY69 Practical Guide to Linux Character Device Drivers
linux·服务器·arm开发·数据库·单片机·嵌入式硬件
松涛和鸣2 天前
69、Linux字符设备驱动实战
linux·服务器·网络·arm开发·数据库·驱动开发