嵌入式软件面试题

2023-05-16

      CSDN的小伙伴们,我是林君。今天给小伙伴们分享一些嵌入式软件开发工程师的校招面试题。企业校招对基础考察较多。其次,在校参加的相关比赛,项目经历。我在生病前,面试了一周,收到八九个offer,薪资8-10k。下面说说我在面试嵌入式软件开发岗位常遇见的问题。在面试前可以提前熟悉这些问题的答案。

第一类问题:专业考察题

在下面问题中,我附上自己的理解,可能不全面,用到的话再自行补充一些。

问题1:问你写在简历上的项目经历,一般问的很细很细,在此基础上考察你项目里用到的技术知识。

问题2:IIC协议

(1)I2C 使用两条线在主控制器和从机之间进行数据通信。一条是 SCL(串行时钟线),另外一条是 SDA(串行数据线),

(2)这两条数据线需要接上拉电阻,总线空闲的时候 SCL 和 SDA 处于高电平。

(3)I2C 是支持多从机的,也就是一个 I2C 控制器下可以挂多个 I2C 从设备,这些不同的 I2C 从设备有不同的器件地址,这样 I2C 主控制器就可以通过 I2C 设备的器件地址访问指定的 I2C。

1、起始位

也就是 I2C 通信起始标志,在 SCL 为高电平的时候,SDA 出现下降沿就表示为起始位,

2、停止位

停止位就是停止 I2C 通信的标志位,在 SCL 位高电平的时候,SDA出现上升沿就表示为停止位,

3、数据传输

I2C 总线在数据传输的时候要保证在 SCL 高电平期间,SDA 上的数据稳定,因此 SDA 上

的数据变化只能在 SCL 低电平期间发生,

4、应答信号

当 I2C 主机发送完 8 位数据以后会将 SDA 设置为输入状态,等待 I2C 从机应答,也就是等到 I2C 从机告诉主机它接收到数据了。应答信号是由从机发出的,主机需要提供应答信号所需的时钟,主机发送完 8 位数据以后紧跟着的一个时钟信号就是给应答信号使用的。从机通过将 SDA 拉低来表示发出应答信号,表示通信成功,否则表示通信失败。

5、I2C 写时序 

主机通过 I2C 总线与从机之间进行通信不外乎两个操作:写和读,I2C 总线单字节写时序

写时序的具体步骤:

1)、开始信号。 

2)、发送 I2C 设备地址,每个 I2C 器件都有一个设备地址,通过发送具体的设备地址来决

定访问哪个 I2C 器件。这是一个 8 位的数据,其中高 7 位是设备地址,最后 1 位是读写位; 

3)、 I2C 器件地址后面跟着一个读写位,为 0 表示写操作,为 1 表示读操作。

4)、从机发送的 ACK 应答信号。

5)、重新发送开始信号。

6)、发送要写写入数据的寄存器地址。

7)、从机发送的 ACK 应答信号。

8)、发送要写入寄存器的数据。 

9)、从机发送的 ACK 应答信号。

10)、停止信号。

6、I2C 读时序

单字节读时序

I2C 单字节读时序比写时序要复杂一点,读时序分为 4 大步,第一步是发送设备地址,第二步是发送要读取的寄存器地址,第三步重新发送设备地址,最后一步就是 I2C 从器件输出要读取的寄存器值,我们具体来看一下这几步。

1)、主机发送起始信号。

2)、主机发送要读取的 I2C 从设备地址。

3)、读写控制位,因为是向 I2C 从设备发送数据,因此是写信号。

4)、从机发送的 ACK 应答信号。

5)、重新发送 START 信号。

6)、主机发送要读取的寄存器地址。

7)、从机发送的 ACK 应答信号。

8)、重新发送 START 信号。

9)、重新发送要读取的 I2C 从设备地址。

10)、读写控制位,这里是读信号,表示接下来是从 I2C 从设备里面读取数据。

11)、从机发送的 ACK 应答信号。

12)、从 I2C 器件里面读取到的数据。

13)、主机发出 NO ACK 信号,表示读取完成,不需要从机再发送 ACK 信号了。

14)、主机发出 STOP 信号,停止 I2C 通信。

I2C 多字节读写时序

有时候我们需要读写多个字节,多字节读写时序和单字节的基本一致,只是在读写数据的

时候可以连续发送多个自己的数据,其他的控制时序都是和单字节一样的。

问题3:UART 通信

1、UART 通信格式

空闲位:数据线在空闲状态的时候为逻辑“1”状态,也就是高电平,表示没有数据线空闲,

没有数据传输。

起始位:当要传输数据的时候先传输一个逻辑“0”,也就是将数据线拉低,表示开始数据

传输。

数据位:数据位就是实际要传输的数据,数据位数可选择 5~8 位,我们一般都是按照字节

传输数据的,一个字节 8 位,因此数据位通常是 8 位的。低位在前,先传输,高位最后传输。

奇偶校验位:这是对数据中“1”的位数进行奇偶校验用的,可以不使用奇偶校验功能。

停止位:数据传输完成标志位,停止位的位数可以选择 1 位、1.5 位或 2 位高电平,一般都选择 1 位停止位。

波特率:波特率就是 UART 数据传输的速率,也就是每秒传输的数据位数,一般选择 9600、

19200、115200 等。

2、UART 电平标准 

UART 一般的接口电平有 TTL 和 RS-232,一般开发板上都有 TXD 和 RXD 这样的引脚,

这些引脚低电平表示逻辑 0,高电平表示逻辑 1,这个就是 TTL 电平。

RS-232 采用差分线,-3~- 15V 表示逻辑 1,+3~+15V 表示逻辑 0。

USB 转 TTL 模块,TTL 接口部分有 VCC、GND、RXD、TXD、

RTS 和 CTS。RTS 和 CTS 基本用不到,使用的时候通过杜邦线和其他模块的 TTL 接口相连即

问题4:SPI通信协议

       相比I2C 接 口,SPI 接口的通信速度很快,I2C 最多 400KHz,但是 SPI 可以到达几十 MHz。I2C 是串行通信的一种,只需要两根线就可以完成主机和从机之间的通信,但是 I2C 的速度最高只能到 400KHz,如果对于访问速度要求比价高的话 I2C 就不适合了。本章我们就来学习一下另外一个和 I2C 一样广泛使用的串行通信:SPI是一种高速、全双工的同步通信总线,SPI 时钟频率相比 I2C 要高很多,最高可以工作

       在上百 MHz。SPI 以主从方式工作,通常是有一个主设备和一个或多个从设备,一般 SPI 需要 4 根线,但是也可以使用三根线(单向传输),这四根线如下:

①、CS/SS,这个是片选信号线,用于选择需要进行通信的从设备。

I2C 主机是通过发送从机设备地址来选择需要进行通信的从机设备的,SPI 主机不需要发送从机设备,直接将相应的从机设备片选信号拉低即可。

②SCK,串行时钟,和 I2C 的 SCL 一样,为 SPI 通信提供时钟。 

③、MOSI/SDO,简称主出从入信号线,这根数据线 只能用于主机向从机发送数据,也就是主机输出,从机输入。

④MISO/SDI,,简称主入从出信号线,这根数据线只能用户从机向主机发送数据,也就是主机输入,从机输出。

SPI 通信都是由主机发起的,主机需要提供通信的时钟信号。主机通过 SPI 线连接多个从

设备的结构。

SPI 有四种工作模式,通过串行时钟极性(CPOL)和相位(CPHA)的搭配来得到四种工作模式:

①、CPOL=0,串行时钟空闲状态为低电平。

②、CPOL=1,串行时钟空闲状态为高电平,此时可以通过配置时钟相位(CPHA)来选择具

体的传输协议。

③、CPHA=0,串行时钟的第一个跳变沿(上升沿或下降沿)采集数据。

④、CPHA=1,串行时钟的第二个跳变沿(上升沿或下降沿)采集数据。

问题5:程序的内存分配

运行程序的内存分为堆区、栈区、BSS区、数据区(初始化)、代码区。

  1. 栈:系统分配空间:存放临时创建的局部变量,存放函数调用的形参和返回值;

     局部变量申请的内存空间超过栈的剩余空间就会存在栈的溢出,例如栈中申请很长的数组和递归调用很多次的函数就有可能出现;

  1. 堆:由程序员分配释放,若程序员不释放,结束时由OS回收,

如果程序员在使用完申请后的堆内存却没有及时把它释放掉,那么这块内存就丢失了,就存在内存泄漏;内存的分配不是连续的。

  1. 通常存放程序运行中动态分配的存储空间;(2)使用 malloc 和new在堆中分配内存;
  1. BSS区:通常是指用来存放程序中未初始化的全局变量和静态变量

静态分配,在程序开始时通常会被清零。

  1. 数据区:通常是指用来存放程序中已初始化的全局变量和静态变量以及字符串常量
  2. 代码区:通常是指用来存放程序执行代码的一块内存区域,这部分区域的大小在程序运行前就已经确定。

问题6:数据类型占用字节大小

各个类型在64位系统中占字节数

char 1; short int 2 ;int 4;

unsigned int 4;float 4;

double 8;long 8;long long 8

unsigned long 8

问题7:单片机中断流程

(1)中断就是:CPU在正常执行程序的过程中,由于内部/外部事件的触发或程序的预先安排引起CPU暂时中断当前正在运行的程序,而转去执行中断服务子程序,待中断服务子程序执行完毕后,CPU继续执行原来的程序,这一过程称为中断;

(2)中断处理过程

第一步:保护现场,将当前位置的PC地址压栈;

第二步:跳转到中断服务程序,执行中断服务程序;

第三步:恢复现场,将栈顶的值回送给PC;

第四步:跳转到被中断的位置开始执行下一个指令

(3)中断服务函数

相对于正常子函数,中断服务函数有以下需要注意的地方:

1.中断服务函数不能传入参数;

2.中断服务函数不能有返回值;

3.中断服务函数应该做到短小精悍;

4.不要在中断函数中使用printf函数,会带来重入和性能问题。

问题9:main函数三个参数

1.int argc 整型变量

2.char *argv[] 字符指针的数组,通俗一点就是字符串数组,每个元素都是字符串

3.char *envp[] 字符串数组

问题10:232、485与422

(1)RS-232、RS422和RS-485 均属于UART是通用异步收发传输器,仅用两根信号线(Rx 和Tx)就可以完成通信过程;而由于各自使用的电平有所不同,因此由UART转换为RS-232、RS422或RS-485时,需要经过一个转换芯片SP3232E、SP3485。

(2)RS-232 一般只使用RXD、TXD、GND三条线;首先涉及到了电平的变化,UART使用的芯片自身输出的电压;然后由UART的两条信号线 TX和RX转换为RX-232的 TX和RX;

传输速率较低,在异步传输时,波特率为20Kbps。

接口使用一根信号线和一根信号返回线而构成共地的传输形式,这种共地传输容易产生共模干扰,所以抗噪声干扰性弱。

RS-232接口可以实现点对点的通信方式,但这种方式不能实现联网功能。

于是,为了解决这个问题,一个新的标准RS-485产生了。

(3)RS-485的数据信号采用差分传输方式,它使用一对双绞线;RS-422 的电气性能与RS-485完全一样。主要的区别在于:RS-422 有4 根信号线:两根发送、两根接收。由于RS-422 的收与发是分开的所以可以同时收和发(全双工),也正因为全双工要求收发要有单独的信道,所以RS-422适用于两个站之间通信,星型网、环网,不可用于总线网;

RS-485 只有2 根信号线,所以只能工作在半双工模式,常用于总线网。

问题11:sizeof与strlen

1. sizeof()【操作数所占空间的字节数大小】是一种c中的基本运算符。

可以以类型、指针、数组和函数等作为参数。

返回值类型为unsigned int

比如char a[5]="123";

int b=sizeof(a);//b=5

int c=strlen(a);//c=3

2.strlen()[计算字符串的长度]是一种函数。

'\0’作为终止符;

其参数必须是字符型指针(char*)。

头文件为#include<string.h>

问题12:什么是回调函数

1. 什么是回调函数:

函数指针的调用,即是一个通过函数指针调用的函数;

如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。

即:把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称为异步回调。

2. 为什么要使用回调函数

回到函数作用:“解耦”,普通函数代替不了回调函数的这个特点。这是回调函数最大的特点。

使用回调函数,和普通函数调用区别:1)在主入口程序中,把回调函数像参数一样传入库函数。这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,且不需要修改库函数的实现,变的很灵活,这就是解耦。

2)主函数和回调函数是在同一层的,而库函数在另外一层。如果库函数对我们不可见,我们修改不了库函数的实现,也就是说不能通过修改库函数让库函数调用普通函数那样实现,那我们就只能通过传入不同的回调函数了,这也就是在日常工作中常见的情况。

3. 回调函数:使用其实也是不得已而为之,是一种解决问题的策略

回调函数的使用是对函数指针的应用,函数指针的概念本身很简单,但是把函数指针应用于回调函数就体现了一种解决问题的策略,一种设计系统的思想

回调函数的缺点:

1)回调函数固然能解决一部分系统架构问题但是绝不能再系统内到处都是,如果你发现你的系统内到处都是回调函数,那么你一定要重构你的系统。

2)回调函数本身是一种破坏系统结构的设计思路,回调函数会绝对的变化系统的运行轨迹,执行顺序,调用顺序。回调函数的出现会让读到你的代码的人非常的懵头转向。

问题13:全局变量喝局部变量的区别

1.作用域不同:全局变量的作用域为整个程序,局部变量的作用域为当前语句块;

2.内存储存方式:全局变量存储在全局数据区,局部变量存储在栈上;

3.生命周期不同:全局变量的生命周期和程序一样,局部变量随着语句块的结束而结束;

4.当局部变量与全局变量同名时,优先使用局部变量;

问题14:结构体和联合体的区别

1.结构体和联合体都是由不同的数据类型组成,但在任何时刻,联合体只存在一个被选中的成员,结构体所有成员都存在。

2.在结构体中,各成员占有自己的储存空间,总大小等于各成员的大小之和

3.在联合体中,所有成员公用一块储存空间,其大小等于联合体中最大成员的大小

问题15:指针和数组的区别

1.数组要么在静态存储区,要么在栈上被创建。数组名对应着一块内存,其容量与地址在生命周期内保持不变。

2.指针可以随时指向任意类型的内存块,他的特征是可变。比数组灵活,但也危险。

问题16:指针函数和函数指针的区别

1.指针函数是一个函数,它的返回值是一个指针。

2.函数指针是一个指针,这个指针指向的对象是一个数组。

问题17:常量和变量的区别

1.常量是只读不可写,变量可读可写常量必须初始化,变量可以不初始化;

2.常量不可以寻址,它的地址不可赋值非常量指针;变量可以寻址,常量的效率比变量高。

问题18:指针自增自减与变量自增自减有什么区别?

指针自增自减是改变指针所指向的对象,变量自增自减是改变变量的值;

问题19:#include <stdio.h>与#include "stdio.h"的区别?

<stdio.h>表示的是该文件存在编译器指定的标准头文件存放处

"stdio.h"表示的是该文件在用户当前的工作目录下

问题20:头文件中的ifdef/define endif的作用是什么?

防止头文件被重复引用

问题21:用#define实现宏并求最大值与最小值

#define MAX(X,Y) ((X)>(Y)?(X):(Y))

#define MIN(X,Y) ((X)<(Y)?(X):(Y))

问题22:break语句与continue语句的区别

continue语句只能出现在循环语句内,表示结束本次循环;

break语句还能出现在switch语句中,表示结束switch语句,出现在循环语句中,表示结束整个循环。

问题23:static与cinst关键字的区别

(1)static用于全局变量:表示该变量是静态全局变量,

(2)作用域为当前文件用于函数:该函数为静态函数,只能在本文件中调用;静态函数在内存中只有一份,普通函数在内存中只有一份拷贝;

(3)用于局部变量:为静态局部变量,只初始化一次,之后调用函数都是上次函数退出的值。即改变变量的生存周期为整个程序运行时间段内。

(4)static成员函数:表示这个函数属于此而不属于此类的任何

(5)static成员变量:表示该变量属于此类而不属于此类的任何对象,该变量的初始化在此类体外。

2.const 关键字

(1)修饰一般常量:修饰符可在类型说明符前也可以在类型说明符后;

(2)修饰数组:修饰符const可以用在类型说明符前,也可以用在类型说明符后;例如:int const a[5]={1,2,3};或 const int a[5]={1,2,3};

(3)修饰常指针:const int *A; //const修饰指针指向的对象,指针可变,指针指向的对象不可变;

举例:int const *A; //修饰指针指向的对象,指针可变,指针指向的对象不可变; int *const A;//const修饰指针,指针不可变,指针指向的对象可变;

问题24:const与宏的区别

(1)编译检查 宏不会编译检查,const有编译检查

(2)宏的好处 宏可以定义函数、方法等,const不可以

(3)宏的缺点 大量使用宏,会导致预编译的时间过长

问题25:引用与指针的区别

(1)非空区别:指针可以指向NULL,引用必须指向某个对象

(2)可修改区别:指针可以指向不同的对象,引用总是指向初始化的对象

(3)合法性区别:在使用指针之前要判断是否为NULL,引用不需要判断

问题26:malloc()与calloc()的区别

(1)malloc与calloc都是从堆上动态申请内存空间。

(2)malloc只有一个参数,即要分配的内存大小。

(3)calloc函数有两个参数,分别是元素的个数与元素的大小。

(4)malloc不能对内存初始化,calloc堆内存的每一位初始化为零。

问题27:strcpy、sprint和memcpy的区别

(1)strcpy函数操作的对象是字符串,完成从源字符串到目的字符串的拷贝

(2)sprint函数操作的对象不限于字符串,是实现其他数据类型先给高字符串的转化,方法中需要指定源对象的数据类型,如果源对象是字符串,也可以实现字符串的拷贝功能。

(3)memcpy函数是内存的拷贝,实现将一个内存的内容复制到另一个内存块。内存块由首地址及长度决定。

(4)strcpy为什么要返回char *类型

增加代码的灵活性,方便其他函数直接调用

问题28:多线程问题:目前我没学到这,我直接回答不太了解。

问题29:问一些linux常见命令。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第二类问题:非专业题

1.自我介绍;

2.自我评价;

3.你对自己未来规划有什么规划?

4.你怎么看待加班问题?

5.为什么选择我们公司?

6.你还有什么想要了解的? 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式软件面试题 的相关文章

随机推荐

  • Docker的安装以及可视化图形界面的安装

    Dockerd的主要作用 xff1a 起到一个 容器 xff08 代码 43 环境 xff09 的作用 xff0c 解决了软件跨环境迁移导致的版本不兼容等问题 使用沙箱机制 xff0c 相互之间没有任何接口 xff0c 且性能开销极低 Do
  • MySQL数据库忘记密码后,如何修改密码

    MySQL修改密码 xff08 本人亲身试验可行 xff01 xff09 1 以管理员身份打开命令行 2 在命令行中进入MySQL的bin目录所在文件夹 即 xff1a 在命令行中输入 xff1a cd 路径 路径查找如下 xff1a 命令
  • 人工智能_03

    逻辑回归 xff08 用于解决分类问题的一种模型 xff0c 核心 xff1a 找到决策边界 xff09 根据数据的特征或者属性 xff0c 计算出其归属于某一类别的概率 P x P x P x
  • 人工智能_04

    无监督学习 xff08 Unsupervised Learning xff09 机器学习的一种方法 xff0c 没有给定事先标记过的训练示例 xff0c 自动对输入的数据进行分类或分群 优点 xff1a 算法不受监督信息 xff08 偏见
  • 远程连接本地以及其他机器上的Ubuntu虚拟机

    连接本机的Ubuntu虚拟机 xff1a 1 查看Ubuntu虚拟机是否安装了ssh服务 xff1a service sshd status 2 安装ssh服务 sudo apt get install openssh server 3 开
  • 注册中心Nacos

    注册中心 nacosNacos注册中心与配置中心nocos优点与缺点启动docker镜像测试linux windows下单机启动应用启动个报错nacos如何修改用户名密码 nacos Nacos注册中心与配置中心 nacos官方文档 Nac
  • git常见问题

    git常见错误 1 在git pull时遇到fatal refusing to merge unrelated histories错误 意思是 xff1a 拒绝合并不相关的分支 表示要合并的本地分支和远程分支是相互独立而不是相关联的 我的情
  • PID 控制器

    本文参考 xff1a 从不懂到会用 xff01 PID从理论到实践 哔哩哔哩 bilibili 目录 1 PID控制器入门 1 1 PID控制器的引入 1 2 PID控制器适用系统 1 3 PID控制器宏观意义 2 PID控制器的必备知识
  • Linux - 第11节 - 网络入门

    目录 1 计算机网络背景 1 1 网络发展 1 2 认识 34 协议 34 2 网络协议初识 2 1 协议分层 2 2 OSI七层模型 2 3 TCP IP五层 xff08 或四层 xff09 模型 3 网络传输基本流程 3 1 同局域网的
  • 【经典问题:汉诺塔】C语言编写程序实现汉诺塔问题——函数递归

    汉诺塔 xff08 Tower of Hanoi xff09 xff0c 又称河内塔 xff0c 是一个源于印度古老传说的益智玩具 大梵天创造世界的时候做了三根金刚石柱子 xff0c 在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘 大梵
  • 1.语音增强技术概述

    一 语音增强发展历史 1987年 xff1a Lim和Oppenheim发表语音增强的维纳滤波方法 xff1b 1987年 xff1a Boll发表谱减法 xff1b 1980年 xff1a Maulay和Malpass提出软判决噪声一直方
  • PCB软件对比分析(AD、Pads、Allegro)

    文章目录 前言一 国内的EDA软件市场二 Altium三 Mentor四 Candence总结 前言 今天来说一说国内用的最多的三款PCB软件对比 一 国内的EDA软件市场 国内的EDA软件几乎被三家瓜分 1 Altium 2 Canden
  • (二)立创EDA之新建工程,原理图,PCB

    文章目录 前言一 界面介绍二 工程广场介绍三 新建工程3 1 修改图纸属性 四 基本的操作介绍4 1 添加器件4 2 连接导线4 3 添加插针4 4 查看封装4 5 修改封装 五 原理图转PCB5 1设置PCB高亮显示元器件5 2 布局传递
  • stm32mp157 wm8960音频驱动调试笔记

    这次调试wm8960音频驱动遇到了好多的坑 xff0c 研究好几天终于调试好了 驱动调试步骤 驱动能不能成功加载是调试的第一大步骤 xff0c 也是最关键的步骤之一 1 查看硬件原理图 2 打开对应的设备树 xff08 stm32mp157
  • ROS发布者(Publisher)和订阅者(Subscriber)的python编程实现(讲解超级详细)

    有时候想想 xff0c 国内有些资源确实比较稀缺 xff0c 但是我们一样不会落后 xff01 学习python和ROS这么久了 xff0c 一直很少去实战 xff0c 另外看到基于python编程的ROS话题通信教程实在是稀缺了 xff0
  • C#工控上位机——框架

    C 工控上位机 第一部分 xff1a UI模块 先点击一下Panel xff0c 在点击一下屏幕 先选中Panel xff0c 在进行属性设置 图标连接 嵌入式窗体 设置按键的事件 using
  • docker镜像启动es/kibana

    下载镜像elasticsearch docker search elasticsearch docker pull elasticsearch 启动镜像 docker run name my elasticsearch p 9200 920
  • 虚拟串口的使用

    虚拟串口的使用
  • 修改闭包内使用的外部变量

    修改闭包内使用的外部变量的错误示例 定义一个外部函数 def func out num1 定义一个内部函数 def func inner num2 这里本意想要修改外部num1的值 xff0c 实际上是在内部函数定义了一个局部变量num1
  • 嵌入式软件面试题

    CSDN的小伙伴们 xff0c 我是林君 今天给小伙伴们分享一些嵌入式软件开发工程师的校招面试题 企业校招对基础考察较多 其次 xff0c 在校参加的相关比赛 xff0c 项目经历 我在生病前 xff0c 面试了一周 xff0c 收到八九个