锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

嵌入式软件面试总结

时间:2022-08-29 09:30:01 嵌入式传感器节点

本文只是一个总结。在嵌入式面试过程中,面试官会提到一些问题。你可以根据问题自己找到解释和总结,一些常见的考试内容可以自己总结

C语言

1、sizeof()是否是函数
sizeof()其实是关键词,因为它的用法sizeof()后面加了括号,误以为是函数。例如,我们声明一个变量
int i=0;
在程序中运行输出,sizeof(i)为4。再试一次sizeof i,结果也是4。所以不加括号和括号就能得到大小,很明显sizeof不是函数。为什么编程时习惯加括号?
比如输出,sizeof int,如果没有括号,编译就会出错,因为如果在数据类型之前没有括号,编译器将被误认为是一个修改符,类似const、unsigned。
因此,在编写代码时,建议添加括号

2、const
2.1、被const所有修改的对象都受到强制保护,不会意外改变,以提高程序的强度。
2.两种常见用法
const int i=10; ///修改变量i的值在内存中是不可变的
void fun(const int i); ///修饰函数参数在函数运行体内是不可变的
const int *p; //指针p是可变的,p指向内容不可变
int *const p; //指针p是不可变的,p指向的内容是可变的

3、volatile
理解英语字面意思是易变的。
例如,在多线程运行中常用的应用场景是共享变量,例如有一个变量int i=0.两个线程A,B.
A线程运行:i = i 1;
B线程运行:i = i 2;
无论是先操作A还是先操作AB。希望的结果i的值是3,那么就需要用volatile来修饰。
通过volatile修改后,当其中一个线程运行时,i的结果将直接刷新到内存中,销毁以前的缓存值,另一个线程将从内存中获得此值。
另一个场景是中断和线程配合。中断后,变量发生了变化。中断退出后,希望内存刷新此值。

4.指针函数和函数指针
指针函数:指函数返回的数据

int res=0; int *fun(int a,int b) { 
          res = a b;  return &res; } 

函数指针:将定义初始化为函数指针,

int*p)(int a,int b); int fun(int a,int b) { 
          int res=0;  res = a b;  return res; } void main(void) { 
          int a=1,b=2;  int sum;  p = fun;  sum = p(a,b);  printf("%d",sum); } 

函数指针最大的功能是在调用时直接找到函数地址,典型的应用是回调函数。函数指针可以作为参数传输。
例如,回调函数

int callback(int a,int b,int (*p)(a,b){ 
        
	return p(a,b);
}
void main(void)
{ 
        
	printf("%d",callback(2,3),fun);
}

5、回调函数callback

接着上面的说,回调函数起始可以理解为一个软中断,可以直接调用把函数名当作函数指针参数传入,通过寻址的方式跳转到函数运行,提高代码运行效率。

6、float与0值的比较

错误的写法:

float x;
//错误的写法
if(x == 0.0)
if(x != 0.0)
//正确的写法
const float EPSINION = 0.00001	//需要比较的精度
if((x >= -EPSINION) && (x <= EPSINION))

7、指针和0值比较

int *p;
//错误的写法
if(!p)		//这是BOOL变量的写法
if(p)
//正确的写法
if(p == NULL)
if(p != NULL)

8、字节对齐

  • 为什么要字节对齐
struct TestStruct
{ 
        
	char c1;
	short s;
	char c2;
	int i;
};

当读取该结构体是,你以为在内存存储是紧凑的,假设c1在地址0,s就在地址00000001,c2在地址00000003,i在地址00000004.
但在Visual C++中

struct TestStruct1 a;
printf("c1 %p, s %p, c2 %p, i %p\n",
    (unsigned int)(void*)&a.c1 - (unsigned int)(void*)&a,
    (unsigned int)(void*)&a.s - (unsigned int)(void*)&a,
    (unsigned int)(void*)&a.c2 - (unsigned int)(void*)&a,
    (unsigned int)(void*)&a.i - (unsigned int)(void*)&a);

在这里插入图片描述
这就是内存对齐导致的问题,如果不对齐,系统访问时,short s会访问两次才能组合成s系统为了提高系统性能,自动将c1按两字节对齐,这样系统访问short s时就只用访问一次。

  • 可以用什么样的方式对齐字节,使计算读取的字节数,对于定义
    一般我们为了使定义的结构sizeof()获取的结构体长度准确,会对结构体做1字节对齐
#pragma pack(1)
 struct TestStruct
{ 
        
	char c1;
	short s;
	char c2;
	int i;
};
#pragma pack()

这样在计算sizeof(TestStruct);就是实际的8,如果不加的话就是12.

通信协议

半双工、全双工

1、半双工:同一时刻只能发送或者接收
2、全双工:既可以接收也可以输出
可以通过硬件出线理解,比如IIC是SCL、SDA,只有一根数据线,肯定是半双工。串口TX、RX和4线SPI是MOSI\MISO,同时包含了输入输出肯定是全双工

同步、异步

1、同步:带有时钟线(IIC,SPI)
2、异步:不带有时钟线(uart,CAN)

通信协议 速率 节点通信 时序 通信模式 应用场景 节点总数 通讯距离 备注
IIC 100K~400K,也有高速3.4Mb/s对eeprom通讯 寻址的方式,注意地址位一般是7位,还有一个读写位 起始信号、应答、结束信号 半双工 加速度传感器芯片 根据地址来的。地址位7bit,可以挂127,也有8bit、10bit 板上通讯 上拉电阻一般是1.5K,2.2K,4.7K,电阻的大小对时序有一定影响,对信号的上升时间和下降时间也有影响。公式:Rmin={Vdd(min)-o.4V}/3mA、Rmax=(T/0.874) *c, T=1us 100KHz, T=0.3us 400KHz,c为电容,一般会选用100pF、200pF
SPI 最大可达几十兆一般配置8M足够 CS口片选 通过CLK时钟脉冲读写,还要注意配置极性模式,一般用模式0、3 3线半双工、4线全双工 eeprom、flash芯片 任意个 板上通讯
RS485 最高10M 寻址的方式 串口协议 半双工,空闲时主机和从机都处于接收状态 modbus通信 根据协议的地址码可以达到128个或者256个 距离可达1000多米,距离越远速率越低越稳定 传输距离较远时需要120欧的终端电阻
CAN 低速一般250K,500K,高速可达1M CANID寻址 ISO11898标准 半双工 汽车上ECU节点,机器人节点通信 最大32个 40米 高速CAN需要120欧的终端电阻,注意是终端电阻,不是每个节点上接电阻
LIN 20K 寻址的方式 ID寻址 半双工 上层主控接在can节点的ECU 最多16个
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章