当前位置: 首页 > news >正文

嵌入式软件面试八股文

目录

一、指针函数和函数指针

二、指针的大小

三、sizeof 和 strlen 区别

四、数组指针和指针数组

五、C语言里面内存分配的方式

六、struct结构体和union联合体的区别

八、数组和链表的区别

九、写一个宏这个红返回输入参数比较小的一个

 十,使用#include<> 和使用 include " "  区别

十一、全局变量和局部变量的区别

十二、define 和 typedef的区别

十三、static的作用

十四、什么是内存泄漏

十五、内存对齐(字节对齐)

十六、数组名和指针的区别

十七、指针常量和常量指针

十八、堆和栈的区别

 十九、malloc 和 new 的区别

二十、class和struct在c++的区别

二十一、c++的类有几个访问权限

二十二、内敛函数 

二十三、实现拷贝strcpy函数

二十四、程序分为几个段

二十五、队列和栈的区别

二十六、一个.c 文件怎么转化为可执行程序

二十七、SPI和IIC的寻址区别

 二十八、交叉编译

 二十九、uart iic spi 的区别

三十、SPI有几根线可以去除哪几根

三十一、TCP和UDP的区别

三十二、线程和进程的区别

三十三、进程间通信有几种方式

三十四、什么是DMA

三十五、进程的状态

三十六、什么是僵尸进程,孤儿进程,守护进程

三十七、FreeRTOS的调度算法

 三十八、RTOS中任务同步的方式

三十九、RTOS中时间片的大小是由什么决定的

四十、FreeRTOS中任务的状态

四十一、环行缓冲区

四十二、PWM

四十三、if两种写法

四十四、UDP和TCP通信建立流程

四十五、IIC的GPIO配置为什么要使用开漏输出,并且为什么需要上拉电阻

四十六、大小端的概念和判断

四十七、LInux和RTOS的区别

四十八、看门狗定时器

四十九、面向对象的三大特征

五十、fork和vfork的区别

五十一、当for循环遇到fork函数

 五十二、GPIO的工作模式

 五十三、UART 和 USART 的区别

五十四、OSI7层模型和 TCP/ IP四层模型

五十五、什么是MQTT协议

五十六、RAM,ROM,Flash 的区别

五十七、FreeRTOS 和 RT - Thread


一、指针函数和函数指针

指针函数:返回值是一个指针的函数

函数指针:指向一个函数的指针

二、指针的大小

指针的大小跟编译器的位数有关,在32bit系统下,指针的大小是4个字节,在64bit系统下,指针大小是8字节

三、sizeof 和 strlen 区别

sizeof 是一个运算符,它计算的是所占内存的长度,还可以计算 int(4字节) char等类型的大小

strlen 是一个函数,计算的是字符串的长度,字符串以  “\0” 结尾

printf("%d %d \n",sizeof("\0"),strlen("\0"));结果输出    2    0由于sizeof计算的是内存的大小,而"\0"也是一个字符串,而字符串是以"\0"结尾的,故后面还省略了一个"\0",所以是两个。而strlen是计算字符串长度的,"\0"是不需要计算长度的,所以为0

四、数组指针和指针数组

1、数组指针指的是指向数组的指针,本质是一个指针

2、指针数组本质是一个数组,里面每一个元素都是指针

eg.int (*p)[10];        数组指针的声明int* p[10];          指针数组的声明

五、C语言里面内存分配的方式

1、静态存储区的分配        例如全局变量,静态变量

2、栈上分配(函数中定义出的局部变量)

3、堆上分配(malloc,new)

六、struct结构体和union联合体的区别

1、union 联合体 :成员共享一块地址,共用体大小 = 成员中占内存最大的成员大小

2、struct 结构体:不同成员放在不同的地址中,结构体大小 = 所以成员大小之和(字节对齐)

                               (字节对齐不清楚的,看下面十五的内容)

七、野指针是什么,为什么导致野指针

野指针是指向不可以内存的指针

是指指针指向的内存已经被释放或失效,但指针本身未被置空,仍然保留着原来的地址。这样的指针称为“野指针”,访问它会导致未定义行为(Undefined Behavior, UB),可能引发程序崩溃、数据损坏或安全漏洞。

1、当指针被创建的时候,没有赋值,那么就会变成野指针

char* p    野指针char* p = NULL    正确初始化指针

2、当指针被 free 或 delete 后如果没有将指针赋值为NULL,也会变成野指针

char* p1 = malloc(10);
free(p1);                没有赋值,变成野指针p1 = NULL;  // 消除野指针

3、指针越界也是野指针

#include <stdio.h>
#include <stdlib.h>int main() {int *arr = malloc(5 * sizeof(int));  // 分配 5 个 int 的空间if (!arr) return -1;// 错误:越界写入(arr[5] 超出分配的内存范围)for (int i = 0; i <= 5; i++) {  // 错误:i <= 5(合法索引是 0~4)arr[i] = i;                 // 当 i=5 时,越界写入!}// 此时 arr 可能已被越界操作破坏,变成野指针printf("%d\n", arr[0]);  // 可能正常,也可能崩溃(取决于越界是否破坏了指针)free(arr);  // 可能崩溃,因为 arr 可能已被越界操作损坏return 0;
}

八、数组和链表的区别

1、数组的地址空间是连续的,访问速度快,直接通过下标访问,增删改查麻烦

2、链表的地址空间是不连续的,访问速度慢,需要遍历链表,增删改查方便

九、写一个宏这个红返回输入参数比较小的一个

#define MIN(a,b) ( (a) <= (b) ) ? (a) : (b) 

注意:

这里define只做一个替换的作用,它不会检查语法和计算运算结果,需要把每一个变量都用括号括起来,防止出现问题

 十,使用#include<> 和使用 include " "  区别

#include<>  :编译器会从标准库的路径里面去搜索,对于搜索标准库的文件速度会比较快

include " "    :编译器会从用户的工作路径里面去搜索,对于自己定义的文件使用这个会比较快,比如自己定义的 .h .c 文件

十一、全局变量和局部变量的区别

1、作用域,全局变量的作用域为程序块,局部变量的作用域是当前函数内部

2、生命周期,全局变量的生命周期是整个程序,局部变量的生命周期是当前函数

3、存储方式不同,局部变量是存储在栈里面的,全局变量是存储在静态存储区里面的

4、使用方式不同,局部变量在程序的各个部分都可以使用到,局部变量的话只能在函数的内部使用

十二、define 和 typedef的区别

1、define是一个预处理指令,typedef是关键字

#define PI 3.1415926  // 宏定义void func1() {printf("%f\n", PI);  // 可用
}
===========================================================typedef int MyInt;  // 全局作用域void func1() {MyInt x = 10;  // 可用(全局 typedef)printf("%d\n", x);
}

2、define不会做正确性检查,而typedef会做正确性检查

3、define没有作用域的限制

  • 从定义点开始,直到文件末尾(或遇到 #undef),无视函数、代码块等作用域

typedef是有作用域的限制

  • 如果定义在全局,则作用域为文件。

  • 如果定义在函数或代码块内,则只在该区域内有效。

4,对指针的操作不同

 

十三、static的作用

 static的作用是定义一个静态变量或者一个静态函数

1、在函数体中使用static去定义变量,那么这个变量就只会被初始化一次

2、定义的静态函数或者是静态变量就只能在当前文件使用(作用域的限制)

3、在函数内定义的静态变量无法被其它函数使用

十四、什么是内存泄漏

内存泄漏指的是在程序运行的时候,动态分配的空间没有被回收或者是正确释放,导致了这个内存空间还占据者系统的资源

也就是当你 malloc 动态开辟一个空间时,使用完后没有及时的 free 或者 delete 它 就会造成内存泄漏

十五、内存对齐(字节对齐)

内存对齐时在存储数据时,数据按照一定的规则放置在内存中的过程

以最大的变量所占据的内存来进行分配空间

 下图是字节对齐的示例:

注意

一、结构体变量的首地址是最长成员长度的整数倍。

二、每个成员相对结构体首地址的偏移量,一定是该成员长度的整数倍
三、结构体的总长度是最长成员长度的整数倍。

四、如果结构体内有成员长度大于处理器的位数那么就以处理器的位数作为对齐单位, 

十六、数组名和指针的区别

1、数组名就是数组首元素的地址,也可以看作一个常量指针,这个指针时不能修改指向,内存访问为4个字节

2、使用指针访问数组的时候需要访问到解引用使用*,使用指针访问数组是间接访问,使用数组名访问是直接访问

int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr;  // ptr 指向数组首元素// 使用指针遍历数组
for (int i = 0; i < 5; i++) {printf("%d ", *(ptr + i));  // 解引用访问元素
}
  • 指针存储的是地址,访问数组元素需要:

    1. 计算偏移量ptr + i)得到目标地址。

    2. 解引用*)获取该地址的值。

  • 间接访问:指针先找到地址,再通过地址访问数据(多一步寻址)。

  • 灵活性强:指针可以随意移动(如 ptr++),适用于动态内存(如 malloc 分配的数组)。

int arr[5] = {10, 20, 30, 40, 50};// 使用数组名遍历
for (int i = 0; i < 5; i++) {printf("%d ", arr[i]);  // 直接通过索引访问
}
  • 数组名是首元素地址的常量指针(类型为 int[5]),但编译器会优化为直接访问。

  • 直接访问

    • arr[i] 会被编译为 *(arr + i),但编译器可能直接计算内存位置,无需运行时寻址。

    • 类似于“硬编码”偏移量,效率可能更高(尤其在循环中)。

  • 不可修改:数组名是常量,不能执行 arr++ 这样的操作。

3、使用sizeof对指针和数组名进行计算的时候是不同的,指针的大小和编译器的位数有关,使用sizeof计算数组名是整个数组的大小

十七、指针常量和常量指针

常量指针:指的是向一个常量的指针,这个指针无法修改所指向的数据,但是可以修改指向

int a = 10;
const int b = 20;const int *ptr = &a;  // 指向变量 a(但通过 ptr 不能修改 a)
// *ptr = 30;        // 错误!不能通过 ptr 修改 a
ptr = &b;            // 正确!可以修改指针指向 bprintf("%d\n", *ptr); // 输出 20

 指针常量:指指针是一个常量,指针所指向的地址是固定的,但是可以修改地址中的值

int a = 10;
int *const ptr = &a;  // ptr将永远指向a的地址

十八、堆和栈的区别

1、创建方式不同

栈是自动创建(栈主要用于局部变量),但函数执行完成,栈被销毁

堆是程序员手动进行创建和释放的,malloc进行创建,free进行释放

2、空间大小的区别,栈的空间比较小,堆的空间比较大

3、访问速度,栈的访问速度是比堆快的

为什么栈存储局部变量?

  • 高效:栈的分配和释放只需移动指针,速度快。

  • 自动管理:函数返回时,栈帧自动弹出,变量销毁,无需手动释放。

为什么使用堆内存?

  1. 需要大内存(如大型数组、动态数据结构)。

  2. 生命周期需灵活控制(如跨函数使用数据)。

  3. 栈空间不足时(递归深度大或局部变量过多)。

 十九、malloc 和 new 的区别

1、malloc 是c语言中的标准库函数,new是c++中的操作符

2、malloc分配内存后返回的是void* 类型的指针,new 分配内存后返回的是对应对象类型的指针

3、使用malloc分配内存的时候需要指定分配内存的大小,使用new进行内存分配时不需要指定

4、使用malloc分配内存的时候不会调用到构造函数,使用new分配内存时会调用到构造函数

二十、class和struct在c++的区别

1、struct成员默认时公有的,class默认的成员是私有的

2、继承方面,struct默认是公有继承,class默认是私有继承

3、使用常见,struct一般是用于做简单的数据结构,class一般用于封装和继承

二十一、c++的类有几个访问权限

1、在c++中分别有三个访问权限:公有的、私有的,受保护的

2、public,当成员声明为public时,就可以在类的外部进行访问

3、private,当成员声明为private时,只能在类的内部使用

4、protected,当成员声明为protected时,只能在类内部或者时子类中进行访问

二十二、内敛函数 

1、是一种特殊的函数声明方式,通过在函数签名加上inline关键字,来指示编译器

2、减小函数调用的开销

3、提高执行的效率

4、允许编译器进行优化进一步提高性能

二十三、实现拷贝strcpy函数

用于将一个字符串(包括终止符 \0)复制到另一个字符串

char *strcpy(char *dest, const char *src);dest:目标字符串(复制到的地址)src:源字符串(被复制的字符串)返回值:返回 dest 的地址(便于链式调用)

二十四、程序分为几个段

1、代码段,用于存储程序的可执行指令,一般是只读的,防止被修改

2、数据段(Data段):用于存储已经初始化的全局变量和静态变量

3、BSS段:存储没有初始化的全局变量和静态变量

4、堆:malloc 和 free 进行管理

5、栈:存储局部变量,栈的申请和释放都是由操作系统来决定的

二十五、队列和栈的区别

1、访问的方式:栈是先进后出,队列是先进先出

2、栈:只能在栈顶进行操作     队列:在队尾进行插入,在队首进行删除

3、应用场景:栈主要在函数调用和表达式求值        队列主要在任务调度和广度优先搜索

二十六、一个.c 文件怎么转化为可执行程序

1、预处理:将头文件和宏定义进行展开,生成没有注释的源代码         .i 文件

2、编译:将预处理得到的源代码转化为汇编代码        .s 文件

3、汇编:将汇编的代码转换为机器码生成对应的目标文件         .o文件

4、链接:将全部的 .o  文件链接成一个可执行文件        .hex文件

二十七、SPI和IIC的寻址区别

  • I2C 靠地址寻址SPI 靠片选寻址

 二十八、交叉编译

交叉编译指的是在一个平台上编译出另一个平台的可执行程序

交叉编译是指在一种计算机平台(主机,Host)上编译生成另一种平台(目标机,Target)可执行的代码。例如:

  • 在 x86 电脑 上编译 ARM 开发板 的程序。

  • 在 Windows 系统 上编译 Linux 系统 的可执行文件。

 二十九、uart iic spi 的区别

1、uart:异步通信的方式,没有时钟线

      iic 和 spi 都是同步通信,SCL SCLK

2、接线的区别

UART: TX,RX

SPI:SCLK(时钟线)  CS(片选引脚)  MOSI(主机输出从机输入)   MIS0(主机输入从机输出)

IIC:SDA(数据线)  SCL(时钟线)

3、设备数量
UART:一对一通信
IIC:支持多主机和多从机之间的通信
SPI:一主机多从机

4.传输速度
UART: 115200 9600
IIC:标准模式(100kbps)快速模式(400kbps)高速模式(3.4Mbps)
SPI:

5.工作模式

UART:全双工,半双工

IIC:半双工

SPI:全双工

  • 用 UART
    需要简单、低速、点对点通信(如调试日志)。

  • 用 I2C
    设备数量少、引脚有限、速度要求不高(如传感器网络)。

  • 用 SPI
    需要高速、全双工通信或设备地址冲突时(如存储芯片、显示屏)。

 全双工(Full Duplex)

  • 定义:通信双方可以同时进行数据的发送和接收

  • 特点

    • 需要独立的发送和接收通道(如两根数据线)。

    • 实时性强,效率高。

  • 典型应用

    • 电话通话(双方能同时说话和听声)。

    • UART(通过 TX 和 RX 线实现全双工)。

    • SPI(通过 MOSI 和 MISO 线实现全双工)。

         

半双工(Half Duplex)

  • 定义:通信双方可以双向传输数据,但不能同时进行(需分时复用同一通道)。

  • 特点

    • 只需单根数据线,但需要协议控制方向(如切换发送/接收模式)。

    • 效率较低(需等待对方传输完成)。

  • 典型应用

    • 对讲机(同一时间只能一方说话)。

    • I2C(通过 SDA 线分时传输数据)。

    • RS-485(工业总线,需方向控制)。

三十、SPI有几根线可以去除哪几根

SPI有四根线

1、SCLK:时钟线,用于同步数据传输时的时序控制

2、MOSI:主设备输出,从设备输入线

3、MIS0:主设备输入,从设备输出线77CS:片选线,用于选择对应的从机设备

4、不需要进行双向通信,MOSI,MIS0其中一根线去除

5、CS:只进行一对一通信的时候,不需要片选线

三十一、TCP和UDP的区别

1、数据的可靠性:TCP提供的是可靠的数据传输,三次握手,UDP无连接的,不可靠的数据通信

2、通信方式 TCP是面向连接的通信方式        UDP是不需要进行连接

3、数据传输的效率UDP的通信速率比TCP快        UDP丢包概率比较大

4、应用场景:TCP一般用于邮件,文件传输(FTP)         UDP:视频在线游戏 直播

三十二、线程和进程的区别

1、定义:进程是资源分配的基本单位 线程是进程中的执行单元,CPU调度和执行的基本单位 

2、资源占用:每一个进程都有自己独立的地址空间        线程是共享进程的地址空间

3、容错性:当一个进程出现问题不会影响到其他的进程执行                                                            线程出现问题可能会导致整个程序崩溃从而影响到其他的线程

4、调度和切换:进程是一个独立的单位,需要恢复的上下文的内容就比较多,消耗的资源也就比较多,线程消耗的资源是比较少的

三十三、进程间通信有几种方式

1.管道    2.命名管道  3.共亭内存(mmap)   4.信号量   5.消息队列    6.套接字(socket)  7  信号

1 3 4 5 6 都要借助系统内核

三十四、什么是DMA

DMA是一种无需CPU参与就可以让外设和系统之间的内存进行双向的数据传递

DMA:直接内存存取器

DMA可以减轻CPU的负担提高系统的运行效率

                

三十五、进程的状态

创建状态:当调用fork进入创建状态

就绪状态:进程已经准备好,但是还没有运行

运行状态:进程已经获得系统的资源可以运行

阻塞状态:等待信号量或者互斥量等事件的时候会进入这个状态

终止状态:进程结束

三十六、什么是僵尸进程,孤儿进程,守护进程

僵尸进程:使用fork创建的子进程后,如果子进程退出,父进程并没有调用wait或者waitpid函数记录子进程的退出状态,那么这个子进程的信息还保存在系统中,这个时候这个子进程就叫做僵尸进程

因为父进程异常结束,子进程就会变成孤儿进程,会被进程号为1进程 init 收养

在父进程创建出子进程后故意把父进程结束那么这个进程就是守护进程

三十七、FreeRTOS的调度算法

1、抢占式调度:高优先级的任务可以打断低优先级任务的执行(适用于优先级不同的任务)

 2、时间片轮转:相同优先级的任务具有相同大小的时间片(1ms)当时间片被耗尽任务会强制退出

3、协作式调度:使用vtaskdelay释放CPU的资源让其他的任务来运行,信号量,互斥量等来实现

 三十八、RTOS中任务同步的方式

1、队列:还可以进行数据的传递

2、信号量:在FreeRT0S中会分成两种:二进程信号量(实现共享资源的访问)计数型信号量(实现生产者和消费者模型)

3、互斥量:实现共享资源的访问

4、事件组:可以等待多个任务的通知

5、任务通知:是一种轻量级的任务同步方式,TCB,任务通知不需要创建就可以使用(用于一对一的通信)

三十九、RTOS中时间片的大小是由什么决定的

直接通过修改freeRT0S配置文件宏定义的时间片频率来设置时间片大小

在        FreeRTosConfghlist.h         这个文件里面

#define configTICK RATE HZ     ((TickType_t)1000)//时间片的频率 1000HZ = 1ms

四十、FreeRTOS中任务的状态

1、就绪态:当任务被创建的时候就会进入到就绪态

2、运行态:当任务的代码正在被执行的时候就是运行态

3、阻塞态:当任务在等待信号量或者是互斥量等的时候会进入阻塞态

4、挂起态:使用vTaskSuspend进入到挂起态

                      

四十一、环行缓冲区

使用环形缓冲区经常被用于串口通信,socket,使用环形缓冲区可以将数据保存下来,使用R,W指针来进行数据的操作

 

四十二、PWM

PWM:脉冲宽度调制技术

占空比:高电平占整个周期的比例/整个周期*100%

四十三、if两种写法

if(x == 0)                if( 0 == x )

四十四、UDP和TCP通信建立流程

TCP客户端

1.socket函数创建套接字
2.connect函数连接服务器
3.使用read write函数进行发送和读取数据  send   recv                                                              4.使用close关闭客户端 

TCP服务器

1.socket创建套接字
2.bind绑定IP地址和端口号
3.listen去监听对应的端口
4.accept等待客户端的连接
5.使用read write函数进行发送和读取数据
6.使用close关闭服务器

UDP客户端
1.socket创建套接字                                                                                                          2.sendto发送数据                                                                                                            3.recvform来接收服务器的消息                                                                                        4.close关闭客户端

UDP服务器
1.socket创建套接字                                                                                                          2.bind进行绑定                                                                                                                  3.recvferm接收数据                                                                                                          4.sendw发送数据                                                                                                                    5.关闭服务器

四十五、IIC的GPIO配置为什么要使用开漏输出,并且为什么需要上拉电阻

因为IIC总线的两个引脚都配置为了开漏输出,开漏输出无法输出高电平,只能输出低电平          加入上拉电阻可以让引脚输出高电平

假设使用推挽输出,一个设备输出高电平,一个设备输出低电平,这个时候会导致短路烧毁设备  在IIC中可以挂载多个设备这个时候就需要区分是谁在使用IIC总线,实现了线与的功能,0&1&0=0

四十六、大小端的概念和判断

概念:指多字节的数据在内存中的存储顺序方式,在不同的计算机中会使用不同的字节序来表示数据

大端存储:高字节在低地址,低字节在高地址

小端存储:低字节在低地址,高字节在高地址

0x12345678假设他的第一个字节是0x78那么这个系统为小端存储假设第一个字节是0x12,那么这个系统是大端存储

四十七、LInux和RTOS的区别

1、应用场景

Linux:桌面计算机,服务器,嵌入式系统。

RTOS:嵌入式系统

2、实时性

Linux不保证实时性

RTOS提供严格的实时性保证,任务的调度和执行时间非常可预测,任务的响应都非常快

3、资源占用

Linux比较庞大,占用的资源比较多

RTOS是轻量级的操作系统占用的资源比较少,RTOS适用于在嵌入式系统

4、内存方面

Linux有虚拟内存,内核空间和用户空间

RTOS没有虚拟内存,也没有用户空间和内核空间

5、扩展性

Linux的扩展性非常高,通过加载各种模块和各种库来达到扩展功能

RTOS扩展性比较有限,功能比较专门化

四十八、看门狗定时器

概念:
旨在检测和恢复系统故障,它是一种硬件计时器,要求系统在规定的时间内定期对其进行复位(喂狗)。如果系统没有及时复位看门狗,计时器将会溢出,并触发一种预定的响应,通常是系统复位或重启。

作用:

  1. 防止系统卡死:如果系统由于软件错误、死锁或其他原因导致无法继续正常工作,看门狗定时器可以自动复位系统,从而防止系统长时间卡死。
  2. 提高系统可靠性:在任务关键的嵌入式应用中,如工业控制、汽车电子、医疗设备等,看门狗定时器是确保系统持续可靠运行的重要手段。
  3. 恢复程序运行:当系统由于不可预见的故障导致异常行为时,看门狗定时器可以让系统迅速恢复到已知的初始状态,减少故障的影响。

四十九、面向对象的三大特征

1.封装(Encapsulation):

  • 封装是将数据和操作这些数据的代码(方法)放在一起,形成一个独立的单元一一对象。对象的内部数据通常是私有的,只能通过公共方法访问,从而保护数据不被随意修改。
  • 例子:一个 car 对象有私有的 speed 属性,只能通过 setspeed()和 getspeed()方法修改和获取速度。

2.继承(Inheritance):

  • 继承允许一个类(子类)从另一个类(父类)继承属性和方法。子类可以重用父类的代码,并可以添加或修改功能,
  • 例子:car 类可以继承 vehic1e 类的属性和方法,如 move(),然后添加 honk()方法。

3.多态(Polymorphism):

  • 多态是指同一操作在不同对象上可以表现出不同的行为。通常通过方法重写实现,不同类的对象可以通过相同的接口调用不同的实现。
  • 例子:Dog 和 cat 都继承自 Anima1,它们都有 speak()方法,但具体的 speak()实现不同.

五十、fork和vfork的区别

1、fork的子进程会拷贝父进程的数据段和代码段,vork子进程和父进程共享数据段

2、fork创建出的子进程和父进程执行的顺序不确定,vfork保证了子进程先运行

3、当需要改变共享数据段的变量的时候才会拷贝父进程

4、vfork保证子进程先运行,在它调用exec或者是exit之后父进程才可能被调度执行,如果在调用这两个函数之前子进程依赖父进程的下一步操作这个时候会发生死锁

五十一、当for循环遇到fork函数

for (int i = 0; i<3; i++)
{fork();
}

初始进程 P1:在第一次 fork()调用时创建了进程 P2,
第二次循环:P1 和 P2 分别创建了 P3 和 P4.
第三次循环:P1、P2、P3、P4各自再创建一个进程,最终有8个进程:P1 到 P8.

五十二、SPI的工作模式

SR!(串行外设接口,SerialPeripheralinterface)有四种不同的工作模式,主要是由时钟极性(CPOL)和时钟相位(CRHA)这两个参数来决定的。它们决定了时钟信号如何与数据交换进行同步。

1.SP!的基本概念
SP!是一种全双工、同步的通信协议,常用于短距离的芯片间通信。它包括以下四个基本信号线:

  • MOSl(Master Out Slave In):主设备发送数据,外设接收数据。
  • MISO(Master In Slave Out):外设发送数据,主设备接收数据。                                 
  • SCLK(Serial Clock):时钟信号,由主设备生成
  • SS/cs(Slave Select/Chip Select):选择某个从设备的信号线,低电平时选中从设备。

2.时钟极性(CPOL) 和时钟相位(CPHA)

  • CPOL:控制时钟空闲状态时的电平                                                                                

 CPOL=0:时钟空闲时为低电平

 CPOL=1:时钟空闲时为高电平0

  • CPHA:控制数据是在时钟的第一个还是第二个跳变边沿采样。

CPHA=0:在第一个时钟跳变沿(从空闲到活动)采样数据
CPHA-1:在第二个时钟跳变沿采样数据。

 五十二、GPIO的工作模式

 五十三、UART 和 USART 的区别

UART (Universal Asynchronous Receiver/Transmitter)和USART (Universal synchronous / AsynchronousReceiver/Transmitter)都是用于串行通信的接口,主要区别在于它们支持的通信模式:

1. UART:

  • 通信方式:仅支持异步通信,即发送端和接收端不使用统一的时钟信号
  • 时钟信号:无时钟信号,数据帧通过预定义的波特率进行同步。
  • 工作原理:发送端在开始位(start bit)后发送数据,接收端在没有时钟的情况下依赖波特率来解释数据。
  • 应用场景:适用于点对点的低速数据通信。

2. USART

  • 通信方式:支持异步和同步通信两种模式。

异步模式:与 UART 相同,没有时钟信号,依靠波特率同步。
同步模式:发送端和接收端共享时钟信号,数据与时钟同步传输。

  • 时钟信号:在同步模式下使用时钟信号进行同步通信。
  • 工作原理:

异步模式与 UART 相同。
同步模式下,发送和接收的数据与时钟信号严格同步,提高通信的准确性和速度。

  • 应用场景:可以用于高速和高可靠性的串行通信,尤其是需要同步时钟的场合。

五十四、OSI7层模型和 TCP/ IP四层模型

五十五、什么是MQTT协议

五十六、RAM,ROM,Flash 的区别

 

五十七、FreeRTOS 和 RT - Thread

http://www.dtcms.com/a/301636.html

相关文章:

  • 面试150 数字范围按位与
  • PLLIP核
  • 测试老鸟整理,物流项目系统测试+测试点分析(一)
  • 【笔记】Gibbs自由能全微分公式推导
  • AJAX 原理_第一节_XHR 对象
  • 免安装MySQL启动全解:从解压到远程访问的保姆级教程
  • U盘中毒,文件被隐藏的解决方法
  • Redis6.0+安装教程(Linux)
  • Map系列
  • docker搭建部署 onlyoffice 实现前端集成在线解析文档解决方案
  • 车载诊断架构 ---面向售后的DTC应该怎么样填写?
  • net8.0一键创建支持(Kafka)
  • 基于Prometheus+Grafana的分布式爬虫监控体系:构建企业级可观测性平台
  • 【旧文】Adobe Express使用教程
  • net8.0一键创建辅助开发的个人小工具
  • c++加载qml文件
  • G1回收器
  • 企业IT管理——信息安全策略纲要【模板】
  • TIM 编码器接口
  • listen() 函数详解
  • 表单重复提交、以及重复消费的幂等性问题解决方案
  • 企业如何便捷地使用宝塔面板管理系统服务和网站:一键全能部署与高效运维
  • 062_Arrays类与数组操作
  • 在飞牛OS上部署MoonTV:一站式影视聚合播放器安装教程
  • [spring6: @EnableWebMvc]-源码分析
  • MySQL 事务和锁
  • Webpack 和 Vite 的关键区别
  • 在Luckfox Lyra(Zero W)上将TF卡格式化为ext4文件系统
  • 人工智能——图像梯度处理、边缘检测、绘制图像轮廓、凸包特征检测
  • 递归查询美国加速-技术演进与行业应用深度解析