深入理解统一诊断服务(UDS)【上】

参考教程:https://www.bilibili.com/video/BV1aP4y1p7Vo/?spm_id_from=333.1387.favlist.content.click&vd_source=8f8a7bd7765d52551c498d7eaed8acd5

一、概述

1、UDS是什么

UDS的全称是Unified Diagnostic Services,其中:

U表示统一性,可以基于任意总线

D表示诊断,即诊断通信协议

S表示服务,即诊断服务

2、诊断的定义

从字面意义上看,诊断就是检查问题

在病人看病的情景中,医生使用听诊器对病人的身体状况进行诊断

在汽车问题排查的情景中,工程师使用诊断测试仪对汽车各模块的问题进行排查,诊断测试仪和车辆通过总线相连接(一般诊断仪连接车辆的诊断网),通过诊断协议与汽车中的各模块通讯,即可读取到车辆各模块ECU的内部信息,如ECU的软件版本号和故障信息等,进而确定系统中的问题

诊断测试仪还可向ECU写入数据,如软件刷写

3、诊断通信协议

(1)诊断测试仪要读取汽车模块ECU中的信息和向ECU中写入数据,首先需要有通信媒介让诊断测试仪与ECU能够建立通信连接,这个通信媒介在汽车中称为汽车总线(可以CAN网络、LIN网络、以太网等),通过这个通信媒介用于诊断通信的通信协议则称为诊断协议。

(2)诊断仪通常通过主驾方向盘下的OBD接口接入汽车的诊断网,进而与各模块ECU建立通信连接。

4、UDS的总线应用示例

(1)车外的诊断测试仪Tester通过OBD的接口连接整车的网关Gateway。

(2)网关会分出以太网络Ethernet支线、CAN网络支线、CANFD/FlexRay网络支线,部分CAN网络可能会继续分出LIN网络。

(3)各个ECU都有自己的地址,诊断测试仪通过寻址通信与目标ECU建立通信连接(物理寻址),也可以通过寻址通信在同一个网段下进行功能寻址,关于寻址的内容后续会有详细介绍。

5、诊断通信机制

汽车领域的诊断通信定义了一种基于客户端服务器架构的请求和响应机制,在整个诊断通信的过程中有两个角色------客户端Client和服务器Sever

客户端是诊断请求的提出者,负责发送诊断请求,将请求的服务通过诊断请求报文的形式发送至总线,供服务器接收,如发送读取某个ECU的软件版本号请求

服务器是诊断响应的提供者,当接收到客户端的诊断请求后会对请求进行处理,生成诊断数据,并通过诊断响应报文的形式发送至总线,供客户端接收,如某个ECU接收到诊断请求后,将故障码信息通过诊断响应报文的形式发出

诊断报文不同于常规的总线周期报文,诊断报文是典型的事件触发型报文,有请求时才会响应,比如客户端有诊断请求时才会发出诊断请求报文,服务器收到诊断请求报文后才会发出相应的诊断响应报文

6、车辆诊断的作用和实现条件

(1)诊断在车辆的研发过程、生产过程和售后维修中都有着广泛的应用,如读取模块软硬件版本号/VIN码、故障检测(读取ECU记录的故障码)、程序升级、EOL下线检测、通过诊断测试仪直接控制ECU行为等。

(2)要想在车辆中实现诊断功能,要求诊断测试仪和整车中各模块的ECU都遵循诊断规范(协议),诊断规范描述一系列的诊断服务,定义了诊断仪与ECU之间的请求/响应规则,并定义了ECU对于请求报文的处理行为以及请求/响应报文信息的含义。

7、诊断协议的发展历史(截止至2025年)

(1)历史发展线:

(2)几个诊断规范的区别:

①KWP2000:

对应于ISO 14230,可以基于CAN总线或K线

在欧洲,已规定自2008年起,新下线的车不再使用基于KWP2000的诊断系统,而是使用ISO 15765的诊断系统;在国内,UDS基本处于重要地位,且有发展为统治地位的趋势

②OBD:

对应于ISO 14230-4/ISO 15765-4,可以基于CAN总线或K线

OBD是具有强制标准需要参照的,是由法规要求的,最初目的是环保,同时方便售后维修

③UDS:

对应于ISO 14229,可以基于任意总线

与OBD最大的区别就在"Unified"(统一)上,它是面向整车所有ECU的,而OBD只是面向排放系统ECU的

UDS的本质是一个应用层协议,所以它既可以在CAN网络中实现,也能在以太网、LIN网络等网络中实现

二、统一诊断服务(UDS)简介

1、统一性的核心思想

前面讲到了UDS的本质是一个应用层协议,那么在进行诊断功能的开发时,不需要关心底层的数据链路层和物理层是如何实现的,硬件和软件可以分别进行开发,其核心思想就是在网络层/传输层和会话层之间抽象出一个虚拟的PDU(协议数据单元),它作为统一诊断服务PDU和任何通信协议之间的接口

简单说就是,在不同的通信网络中,底层的通信数据具有不同格式,但通过虚拟PDU处理后,对上层的会话层、应用层是没有区别的,同样地,上层的会话层、应用层往下层传输数据,通过虚拟PDU处理后,数据格式自动适配通信网络要求的格式

2、UDS相关的基本概念和术语

(1)《计算机网络》相关内容回顾:

在计算机网络体系结构中,对通信双方所交互的数据包有专门的术语:

①把对等层次之间传送的数据包称为该层的协议数据单元(PDU),如下图所示(运输层对等实体逻辑通信的数据包一般根据协议而定),主要由协议控制信息(PCI)和数据(Data)组成

②把同一系统内,层与层之间交换的数据包称为服务数据单元(SDU)

③多个SDU可以合成为一个PDU,一个SDU也可划分为几个PDU

(2)客户端:

诊断请求的提出者,一般是诊断测试仪;通常诊断测试仪还有其它功能,如人机交互

(3)服务器:

诊断响应的提供者,一般是车内某个模块的ECU

(4)本地客户端和本地服务器:

客户端连接到与服务器相同的本地网络(即同一"网段"),并且是与服务器相同的地址空间的一部分,则它们互称为本地客户端和本地服务器

(5)远程客户端和远程服务器:

客户端与服务器处于不同"网段",需通过远程地址标识,则它们互称为远程客户端和远程服务器

(6)诊断通信框架------对等实体通信:

在支持UDS协议的前提下,应用层可分为基础功能应用层和诊断应用程序

每一层的作用都是为上层提供服务,基础功能应用层则是为诊断应用程序提供服务

每一层提供的服务可在该层的服务访问点(SAP)获得,它可以是程序中的函数接口,亦或者是其它形式的接口

以软件、硬件或软硬件的任何组合实现的每层的活动部分称为实体,在OSI模型中,通信发生在不同节点中的同一层的实体之间,同一层的这种通信实体称为对等实体

(7)物理寻址与功能寻址:

物理寻址:客户端与服务器之间采用一对一的诊断通信方式,如对某一个ECU进行软件刷写

功能寻址:客户端与服务器之间采用一对多的诊断通信方式,客户端向一个功能组的多个服务器发出同一功能寻址的诊断请求(同时进行通信),如清除功能组中所有ECU的故障码

(8)源地址和目标地址:

源地址指的是报文发送节点地址,目标地址指的是报文接收节点地址

地址和报文ID有关,诊断报文的ID为基地址+节点地址,以某个ECU物理寻址为例,基地址为0x700,诊断仪节点地址为0x01,ECU节点地址为0x08,那么诊断仪对此ECU的物理寻址请求ID为0x701(0x700+0x01),ECU的响应ID为0x708(0x700+0x08)

功能寻址一般为特定ID,如0x7DF

三、应用层服务

1、服务的概念

(1)应用层服务用于基于客户端-服务器的系统,以执行诸如车载服务器的测试、检查、监视或诊断之类的功能。

①客户端(通常称为外部诊断仪)使用应用层服务来请求在一个或多个服务器中执行诊断功能。

②服务器(通常是作为ECU一部分的功能)使用应用层服务将请求的诊断服务提供的响应数据发送回客户端。

(2)诊断应用程序层的服务访问点提供了许多具有相同通用结构的服务,对于每个服务,指定6个服务原语(service primitive):

①服务请求原语(Service Request Primitive)。

②服务请求确认原语(Service Request-Confirmation Primitive)。

③服务指示原语(Service Indication Primitive)。

④服务响应原语(Service Response Primitive)。

⑤服务响应确认原语(Service Response-Confirmation Primitive)。

⑥服务确认原语(Service Confirmation Primitive)。

【上层要使用下层所提供的的服务,必须通过与下层交换一些命令,这些命令称为服务原语,可将其理解为"带有参数传递接口的函数"】

2、确认的服务和未确认的服务

(1)确认的服务:

首先客户端的应用层向客户端下层发送服务请求(Service Request),客户端下层接收请求后通过电平信号将请求报文发送至总线上,同时回读总线电平信号,确认请求是否成功发送,如成功发送,会向客户端的应用层返回服务请求确认(Service Request-Confirmation)

服务器底层接收到服务请求报文并解析其中的内容后,向服务器应用层发送服务指示(Service Indication),服务器应用层对服务请求进行处理,得到响应数据,然后向服务器下层发送服务响应(Service Response),服务器下层接收响应信息后,通过电平信号将请求报文发送至总线上,同时回读总线电平信号,确认信息是否成功发送,如成功发送,会向服务器的应用层返回服务响应确认(Service Response-Confirmation)

客户端底层接收到服务响应报文并解析其中的内容后,向客户端应用层发送服务确认(Service Confirmation)

(2)未确认的服务:

首先客户端的应用层向客户端下层发送服务请求(Service Request),客户端下层接收请求后通过电平信号将请求报文发送至总线上,同时回读总线电平信号,确认请求是否成功发送,如成功发送,会向客户端的应用层返回服务请求确认(Service Request-Confirmation)

服务器底层接收到服务请求报文并解析其中的内容后,向服务器应用层发送服务指示(Service Indication),服务器应用层对服务请求进行处理

3、服务原语的格式

(1)所有应用程序层服务原语都具有相同的通用格式:

service_name.type(parameter A, parameter B, parameter C[, parameter 1, ...])

service_name是诊断服务的名称,如诊断会话控制DiagnosticSessionControl

type表示服务原语的类型,例如服务请求原语

parameter A, ...是A_SDU(应用层服务数据单元),作为服务原语传递的值列表,或者说寻址信息

parameter A, parameter B, parameter C是包含在所有服务调用中的必须参数

, parameter 1, ...\]是可选参数,可有可无,取决于服务的类型 (2)6种服务原语的形式: ①特定应用程序层服务的请求和指示原语始终具有相同的参数和参数值。 服务请求原语:请求原语由诊断测试仪应用程序中的客户端功能使用,以启动服务并将关于所请求的诊断服务的数据传递给应用层 > service_name.request( > > A_MType, > > A_SA, > > A_TA, > > A_TA_type, > > \[A_AE,

A_Length,

A_Data

, parameter 1, ...

)

服务指示原语:应用层使用指示原语来指示对ECU诊断应用程序有意义的内部事件,并将关于所请求的诊断服务的数据传递给ECU诊断应用程序的服务器功能

service_name.indication(

A_MType,

A_SA,

A_TA,

A_TA_type,

A_AE,

A_Length,

A_Data

, parameter 1, ...

)

②特定应用程序层服务的响应和确认原语始终具有相同的参数和参数值。

服务响应原语:响应原语由ECU诊断应用程序中的服务器功能使用,以启动服务并将请求的诊断服务提供的响应数据传递给应用层

service_name.response(

A_MType,

A_SA,

A_TA,

A_TA_type,

A_AE,

A_Length,

A_Data

, parameter 1, ...

)

服务确认原语:应用层使用确认原语来指示对客户端应用程序有意义的内部事件,并将关联的先前服务请求的结果传递给诊断测试仪应用程序中的客户端功能,它不一定表示远程对等接口上的任何活动,例如,如果服务器不支持所请求的服务或者通信中断

service_name.confirm(

A_MType,

A_SA,

A_TA,

A_TA_type,

A_AE,

A_Length,

A_Data

, parameter 1, ...

)

③服务请求确认原语和服务响应确认原语的参数和参数值不一定相同。

服务请求确认原语:应用层使用请求确认原语来指示对客户端应用程序很重要的内部事件,并将关联的先前服务请求的通信结果传递给诊断测试仪应用程序中的客户端功能

service_name.req_confirm(

A_MType,

A_SA,

A_TA,

A_TA_type,

A_AE,

A_Result

)

服务响应确认原语:应用层使用响应确认原语来指示对服务器应用程序很重要的内部事件,并将关联的先前服务响应的通信结果传递给ECU应用程序中的服务器功能

service_name.res_confirm(

A_MType,

A_SA,

A_TA,

A_TA_type,

A_AE,

A_Result

)

④各参数的数据类型和定义:

A_MType------应用层消息类型:

数据类型:枚举

枚举定义:diagnostic、remote diagnostic

说明:如果A_MType = diagnostic,则service_name原语应包含参数A_SA、A_TA和A_TA_type;如果A_MType = remote diagnostic,则service_name原语应包含参数A_SA、A_TA、A_TA_type和A_AE

A_SA------应用层源地址:

数据类型:2字节无符号整数

取值范围:0x0000~0xFFFF

说明:参数A_SA应用于编码客户端和服务器标识符

A_TA------应用层目标地址:

数据类型:2字节无符号整数

取值范围:0x0000~0xFFFF

说明:参数A_TA应用于编码客户端和服务器标识符

A_TA_type------应用层目标地址类型:

数据类型:枚举

枚举定义:physical、functional

说明:参数A_TA_type是参数A_TA的扩展,用于表示为消息传输选择的寻址方法(物理寻址或功能寻址)

A_AE------应用层远程地址:

数据类型:2字节无符号整数

取值范围:0x0000~0xFFFF

说明:参数A_AE用于扩展可用的地址范围以编码(远程)客户端和(远程)服务器标识符;A_AE只能用于实现本地服务器和远程服务器概念的车辆;远程地址代表其自己的地址范围,并且独立于主网络上的地址;A_AE可以表示远程目标地址或远程源地址,具体取决于携带A_AE的消息的方向

A_Length------数据长度:

数据类型:4字节无符号整数

取值范围:0~232-1

说明:参数A_Length表示要发送/接收的数据长度

A_Data------数据:

数据类型:字符串

长度:取决于A_Length

说明:参数A_Data包含由更高层实体交换的所有数据

A_Result------传输结果:

数据类型:枚举

枚举定义:ok、error

说明:服务请求确认原语和服务响应确认原语使用该参数指示信息是否成功传输

4、应用层服务和应用层协议之间的关系

应用层服务(A_SDU)和应用层协议(A_PDU)之间通过服务原语进行信息传递(服务原语可以传递参数),它们之间的交互如下图所示

四、应用层协议

1、应用层协议数据单元

应用层协议数据单元(A_PDU)由应用层服务数据单元(A_SDU)和应用层协议控制信息(A_PCI)组成,其格式如下:

A_PDU(

MType,

SA,

TA,

TA_type,

RA,

A_Data = A_PCI + [parameter 1, ...],

Length

)

MType、SA、TA、TA_type、RA、Length为应用层地址信息(A_AI),与A_SDU中使用的参数相同

A_Data是为每个单独的应用层服务定义的字节数据字符串,应以A_PCI开头,后跟A_SDU中每个服务指定的所有服务特定参数

Length为A_Data的字节数

2、应用层协议控制信息

(1)应用层协议控制信息(A_PCI)有两种格式,根据第一个字节是否为0x7F区分:

①第一个字节为服务标识符SI(Service Identifier,也称SID),取值为非0x7F,适用于请求服务和肯定响应。

②第一个字节为否定响应服务标识符NR_SI(Negative Response Service Identifier),取值为0x7F,适用于否定响应。

③需要注意的是,对于服务ReadDataByPeriodicIdentifier(0x2A)中定义的周期性数据响应消息的传输,应用层协议数据单元(A_PDU)中不存在A_PCI。

(2)所有服务标识符的定义:

(3)诊断测试仪和ECU的诊断通信交互方式:

①诊断测试仪发送诊断请求服务,这个诊断请求服务可以是诊断通信管理请求、数据请求、故障码请求、输入/输出控制、安全访问、软件刷写和重新编程请求等。

请求服务标识符(SID)

数据类型:1个字节,无符号整数

范围:0x00~0xFF(0x7F除外)

SID格式:(X0XXXXXX)b(SID的第6位为0)

示例:ReadDTCInformation(0x19)服务请求的SID为(00011001)b(=0x19+0x00)

②ECU接收到请求后进行处理,如果符合条件且能够计算出相应的结果,则回复肯定响应。

肯定响应服务标识符(SID)

数据类型:1个字节,无符号整数

范围:0x00~0xFF(0x7F除外)

SID格式:(X1XXXXXX)b(SID的第6位为1)

示例:ReadDTCInformation(0x19)服务响应的SID为(01011001)b(=0x19+0x40)

③ECU接收到请求后进行处理,处理后发现当前不符合条件(如ECU不支持对应的服务),或者不能够及时计算出结果,就会回复否定响应,响应消息A_Data由NR_SI、请求服务的SID和NRC组成,其中NRC为否定响应代码,用于指示诊断服务失败或无法及时完成的原因。

否定响应服务标识符(NR_SI)

数据类型:1个字节,无符号整数

范围:0x7F

④常见的NRC(其它NRC可参考ISO14229-1):

|--------|---------------------------------------------------------|---------|
| 字节值 | NRC | 助记符 |
| 0x10 | generalReject(通用拒绝) | GR |
| 0x11 | serviceNotSupported(服务不支持) | SNS |
| 0x12 | sub-functionNotSupported(子功能不支持) | SFNS |
| 0x13 | incorrMessageLengthOrInvalidFormat(消息长度错误或格式无效) | IMLOIF |
| 0x22 | conditionsNotCorrect(条件不正确) | CNC |
| 0x31 | requestOutOfRange(请求超出范围) | ROOR |
| 0x78 | requestCorrectlyReceived-ResponsePending(请求已正确接收-响应待处理) | RCRRP |
| 0x7E | sub-functionNotSupportedInActiveSession(子功能在非活动会话中不受支持) | SFNSIAS |
| 0x7F | serviceNotSupportedInActiveSession(服务在非活动会话中不支持) | SNSIAS |
| ...... | ...... | ...... |

3、子功能

(1)不同诊断服务的应用层协议数据单元格式:

①A_PDU参数约定:

|------|-------------|-----------------------------|
| Type | Name | Description |
| M | Mandatory | 该参数必须存在于A_PDU中 |
| C | Conditional | 该参数可以基于某些标准存在于A_PDU中 |
| S | Selection | 该参数是必需的(除非另有说明),并且是参数列表中的选择 |
| U | User option | 取决于用户的动态使用,该参数可以存在或不存在 |

②没有子功能的请求A_PDU:

|----------------------------------------------|--------------------------------------------------------|------------|
| A_PDU parameter | Parameter Name | Cvt |
| MType | Message Type(应用层消息类型) | M |
| SA | Source Address(应用层源地址) | M |
| TA | Target Address(应用层目标地址) | M |
| TAtype | Target Address type(应用层目标地址类型) | M |
| RA4 | Remote Address(应用层远程地址) | C |
| A_Data.A_PCI.SI | <Service Name>Request SID(请求服务对应的SID) | M |
| A_Data.Parameter 1 ...... A_Data.Parameter k | data-parameter#1(数据参数1) ...... data-parameter#k(数据参数k) | U ...... U |
| Length | Length of A_Data(数据长度) | M |
| C:RA(远程地址)PDU参数仅在远程寻址的情况下存在 |||

③带有子功能的请求A_PDU:

|----------------------------------------------|----------------------------------------------------------|------------|
| A_PDU parameter | Parameter Name | Cvt |
| MType | Message Type(应用层消息类型) | M |
| SA | Source Address(应用层源地址) | M |
| TA | Target Address(应用层目标地址) | M |
| TAtype | Target Address type(应用层目标地址类型) | M |
| RA | Remote Address(应用层远程地址) | C |
| A_Data.A_PCI.SI | <Service Name>Request SID(请求服务对应的SID) | M |
| A_Data.Parameter 1 | sub-function = [ parameter ](子功能参数) | S |
| A_Data.Parameter 2 ...... A_Data.Parameter k | data-parameter#1(数据参数1) ...... data-parameter#k(数据参数k-1) | U ...... U |
| Length | Length of A_Data(数据长度) | M |
| C:RA(远程地址)PDU参数仅在远程寻址的情况下存在 |||

④肯定响应的A_PDU:

|----------------------------------------------|----------------------------------------------------------|------------|
| A_PDU parameter | Parameter Name | Cvt |
| SA | Source Address(应用层源地址) | M |
| TA | Target Address(应用层目标地址) | M |
| TAtype | Target Address type(应用层目标地址类型) | M |
| RA | Remote Address(应用层远程地址) | C |
| A_Data.A_PCI.SI | <Service Name>Response SID(请求服务对应的SID+0x40) | S |
| A_Data.Parameter 1 ...... A_Data.Parameter k | data-parameter#1(数据参数1) ...... data-parameter#k(数据参数k-1) | U ...... U |
| Length | Length of A_Data(数据长度) | M |
| C:RA(远程地址)PDU参数仅在远程寻址的情况下存在 在请求支持子功能参数字节的情况下,data-parameter#1是包含在来自请求消息的子功能参数字节内的7位子功能参数值的回应,其中Bit7设置为0,不回应子功能参数字节中的suppressPosRspMsgIndicationBit |||

⑤否定响应的A_PDU:

|--------------------|-----------------------------------|-----|
| A_PDU parameter | Parameter Name | Cvt |
| SA | Source Address(应用层源地址) | M |
| TA | Target Address(应用层目标地址) | M |
| TAtype | Target Address type(应用层目标地址类型) | M |
| RA | Remote Address(应用层远程地址) | C |
| A_Data.A_PCI.NR_SI | NR_SI(0x7F) | M |
| A_Data.A_PCI.SI | SI(请求服务对应的SID) | M |
| A_Data.Parameter | Negative Response Code(否定响应代码NRC) | M |
| C:RA(远程地址)PDU参数仅在远程寻址的情况下存在 |||

(2)请求消息子功能参数定义:

①它是一个字节长度的数据。

②其第7位(Bit7)表示抑制肯定响应消息指示位(SPRMIB):

'0'= FALSE,不抑制肯定响应消息(被寻址的服务器需要发送肯定响应消息)

'1'= TRUE,抑制肯定响应消息(被寻址的服务器不应发送肯定响应消息)

③其第6位到第0位是子功能的参数值,除了SPRMIB之外,支持子功能参数值的服务应支持子功能参数表中定义的子功能参数值。如果某诊断服务本身支持SPRMIB,但是没有子功能参数值表,它也要因为SPRMIB而不得不填充SF这个字节,此时SF为0x00或0x80,例如TesterPersent服务。

4、请求响应机制

(1)如果采用CAN网络,则可通过CAN报文ID标识ECU的请求地址和响应地址,详细信息参见IS015765-2规范,下面以正常寻址为例进行介绍。

(2)物理寻址:

①诊断测试仪在某个网段内广播发出诊断请求报文(如ID为0x514的报文),网段上的所有ECU都能接收到,但只有该诊断请求报文ID对应的ECU需要接收该请求,其它ECU会将该ID的报文过滤掉,该ID就是这个ECU的物理寻址请求地址。

②ECU处理请求后,在网段内发送响应报文(如ID为0x114的报文),诊断测试仪收到该响应报文后,通过报文ID能判断出是对应ECU的响应,该ID就是这个ECU的响应地址。

(3)功能寻址:

①诊断测试仪在某个网段内广播发出诊断请求报文(如ID为0x7DF的报文),网段上的所有ECU都能接收到,且该诊断请求报文ID对应的所有ECU会将该请求接收,该ID就是这些处于同一功能组的ECU的功能寻址请求地址。

②任何一个ECU处理请求后,都会在网段内发送响应报文,每个ECU的响应报文ID都不同,诊断测试仪收到响应报文后,通过报文ID能判断出是哪一个ECU的响应。

5、服务器的响应行为

(1)服务器的响应行为永远是物理寻址。

(2)服务器处理一个客户端的请求流程:

(3)服务器处理多个客户端的请求流程,可参考ISO14229-1。

相关推荐
上海合宙LuatOS13 小时前
LuatOS核心库API——【i2c】I2C 操作
linux·运维·单片机·嵌入式硬件·物联网·计算机外设·硬件工程
proware17 小时前
嵌入式单板项目之2025
嵌入式·项目
上海合宙LuatOS17 小时前
LuatOS核心库API——【io】 io操作(扩展)
java·服务器·前端·网络·单片机·嵌入式硬件·物联网
Zevalin爱灰灰1 天前
深入理解统一诊断服务(UDS)【下】
物联网·嵌入式·uds·车联网
『往事』&白驹过隙;1 天前
系统编程的内存零拷贝(Zero-Copy)技术
linux·c语言·网络·c++·物联网·iot
济6171 天前
ARM Linux 驱动开发篇---新版led驱动实验程序编写-- Ubuntu20.04
嵌入式·嵌入式linux驱动开发
『往事』&白驹过隙;1 天前
在ARM开发中 volatile与const关键字的关键用途
c语言·arm开发·mcu·物联网·学习·iot
风痕天际2 天前
ESP32-S3开发教程6:硬件定时器
单片机·嵌入式硬件·嵌入式·esp32·freertos·esp32s3
小灰灰搞电子2 天前
ESP32+ESP-IDF 使用MQTT协议连接阿里云物联网平台源码分享
物联网·阿里云·esp32