news 2026/9/25 4:41:48

UDS诊断0x06子功能深度解析:读取DTC扩展数据记录与实战避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UDS诊断0x06子功能深度解析:读取DTC扩展数据记录与实战避坑指南

1. 从一次冷启动失火说起:0x06解决的是“快照解决不了的问题”

1.1 那次排查,真正起作用的是“病历记录”而不是“现场照片”

上个月帮朋友处理一台冷启动偶发失火的试驾车,故障码是P0302。DTC状态位已经是confirmed,但你用UDS 0x19服务读出来的快照数据(Snapshot)完全正常——转速、负荷、水温全部落在常规区间,这是最典型的偶发故障场景:车开到工位上时,故障现场早就过去了,现场照片没什么信息量。真正帮我把问题锁定的,是0x19服务底下那个经常被忽略的子功能0x06,全名reportDTCExtendedDataRecordByDTCNumber,也就是“按DTC编号读取DTC扩展数据记录”。

这个子功能把2缸失火的历史环境温度、燃油修正量,以及三个平时容易被当成“没用的数字”的计数器全部翻了出来。把这些数据按时间顺序摆在一起,能清楚看到失火只发生在冷却液温度低于20℃、燃油修正量偏大的工况下;再结合计数器增长节奏,最后定位到气门室盖内一根偶发搭铁的线束。整个过程里,快照只提供了“故障存在”的证据,扩展数据才提供了“故障为什么存在”的线索。

如果你做车载诊断、ECU标定、售后诊断工具开发,或者正在啃UDS协议栈源码,0x19的0x06迟早会出现在你的调试日志里。这篇文章不打算重复那些随便就能搜到的协议表格,而是从一次真实排查出发,把报文格式、NRC语义、OEM实现差异、协议栈实现要点,以及最近圈子里越来越受重视的UDS威胁与防御串起来讲清楚。

1.2 0x19家族有二十多个子功能,0x06排在什么位置

0x19服务叫ReadDTCInformation,是整车诊断里用得最频繁的服务之一。整个0x19家族可以粗分成几组:按状态掩码统计和列出DTC(0x01、0x02),按快照记录读取冻结帧(0x03、0x04、0x05),按扩展数据记录读取DTC附加信息(0x06、0x11、0x13),以及永久DTC、镜像内存、故障检测计数器等更细的分支。

0x06在这一大家子里的定位非常明确:它针对“某一个具体DTC、某一条具体扩展数据记录”做精确读取。它不等同于0x11(reportDTCWithExtendedDataRecord)。0x11是把所有带扩展数据的DTC一次性列出来,响应体很大,适合“先看看全车有哪些故障带附加信息”;0x06是拿着你已知的DTC编号去点名取数据,响应体小、目的性强,适合在确认了具体故障码之后做深挖。

我见过不少刚接触UDS的工程师把0x11和0x06搞混,理由是“都是读扩展数据”。实际上两者一个是“目录浏览”,一个是“按名字查档案”。诊断工具的交互逻辑通常应该是:先用0x19 0x02拉出当前所有DTC列表,再用0x06逐个查询关注的DTC,而不是指望0x06替你枚举故障。

1.3 扩展数据和快照数据,到底差在哪

快照数据(Snapshot)本质上是“一组DID键值对”:在故障检测的那一瞬间,ECU把发动机转速、车速、冷却液温度、蓄电池电压等一组预定义信号抓下来存好,之后通过0x04或0x05读取。它解决的问题是“故障发生的瞬间,整车状态是什么样”。

扩展数据(Extended Data)则更像是“一条条结构化的故障病历”。它同样挂在某个DTC下面,但每条记录的含义由OEM自行定义。标准里只对0号记录做了统一约定:DTC扩展数据记录0是故障发生次数计数器(failure occurrence counter),用来统计这个DTC自上次清码之后被检测到的次数。其他记录可以是老化计数器、最近一次失败的工况参数、环境温度、油品品质相关的修正数据,甚至ECU内部诊断标志位。

用一句话总结两者的差别:快照是现场照片,扩展数据是病情记录和统计报表。照片帮你回忆现场,病历和统计帮你判断病情走向。0x06读的就是后者,尤其是那个0号计数器,很多时候比DTC状态位本身更能说明问题到底是一次偶发,还是在稳定恶化。

2. 报文格式逐字节拆解:请求、肯定响应和否定响应

2.1 请求帧:一个DTC编号加一个记录号

0x06的请求帧格式很紧凑,在经典CAN总线上通常就是6个字节:

19 06 06 03 02 01 │ │ └──┬─── └─ │ │ │ └─ recordNumber:要读取的扩展数据记录号 │ │ └─ 3字节DTC编号 │ └─ 子功能 0x06 = reportDTCExtendedDataRecordByDTCNumber └─ 服务ID 0x19 = ReadDTCInformation

这里的3字节DTC编号按ISO 14229-1的UDS格式排列,高位在前。要注意,3字节DTC不是简简单单把一个16位数字拆成三份:最高字节的高2位承载故障组信息(动力、底盘、车身、网络),剩余位和中间、低字节一起编码DTC数值,很多OEM还会在自有诊断规范里重新定义这套编码。为了稳妥,本文举例统一假设某OEM把P0302编码为06 03 02,但你在实际项目里务必先查该ECU的诊断数据库,不要拿别人的编码硬套。

recordNumber在ISO 14229-1:2013版本里是必填的,取值0x00到0xFE,其中0x00就是标准约定的故障发生次数计数器,0xFF保留。到了2020版本,标准把recordNumber改成了可选:请求里不带记录号,服务器要返回该DTC支持的所有扩展数据记录。这个变化看着不大,但对工具链兼容性影响很直接——存量ECU里既有只认6字节请求的2013实现,也有按2020实现却又只实现了“带记录号”分支的固件,甚至有个别实现会把5字节请求当成错误长度直接回0x13。厂商造车节奏不同,新旧版本并存是常态,这也是后面要讲的避坑重点。

另外,子功能字节的最高位是抑制肯定响应位(suppressPosResponseMsgBit)。发送19 86 ...时,ECU即使处理成功也不回肯定响应,只会在出错时回否定响应。这个位在标定和自动化测试里很实用,可以减少总线负载,但调试阶段不建议用,否则报文日志里会少掉一半信息。

2.2 肯定响应:两个版本之间只差一个字节

0x06的肯定响应SID是0x59,也就是0x19加0x40。数据结构如下:

59 06 DTCFormatIdentifier DTC(3) statusOfDTC(1) DTCExtendedDataRecord(N)

在2013版本里,DTCFormatIdentifier这个字节还没有被引入,响应直接是59 06 + DTC(3) + statusOfDTC(1) + DTCExtendedDataRecord(N)。2020版本为了兼容OBD的2字节DTC格式,在DTC之前加了一个格式标识符:0x00表示ISO 14229-1的三字节DTC格式,0x01表示ISO 15031-6的两字节格式,其余值保留或由OEM自定义。解析响应的第一步应该是读这个字节,再决定后面按3字节还是2字节切DTC。我见过有人把0x01格式的响应硬按3字节解析,结果一个DTC对不齐,整条报文全部错位,排查了半天才发现是格式标识符没处理。

statusOfDTC是1字节状态掩码,每一位代表一种故障状态。实际排查中我最常用的是bit2和bit3。bit2是pendingDTC,表示故障本循环已经发生但还没达到确认阈值;bit3是confirmedDTC,表示已经满足确认条件并且被锁定在故障内存里。读0x06之前先看一眼statusOfDTC,能避免拿pending状态的数据去做“是否要维修”的判断。

Bit含义典型值
0testFailed0x01
1testFailedThisOperationCycle0x02
2pendingDTC0x04
3confirmedDTC0x08
4testNotCompletedSinceLastClear0x10
5testFailedSinceLastClear0x20
6testNotCompletedSinceThisOperationCycle0x40
7warningIndicatorRequested0x80

DTCExtendedDataRecord这一段是变长区域,标准只规定“它是这个DTC扩展数据记录的载体”,内部到底怎么排布完全由OEM定义。常见的形态有:2字节或4字节的计数类字段、1字节枚举状态、按DID格式打包的环境参数。解析这一段唯一可靠的方式是查OEM提供的诊断规范或CDD/ODX数据库,任何想当然的“通用解析模板”都会在下一家OEM的车上翻车。

2.3 否定响应:NRC速查与判断顺序

0x06出错时,ECU回7F 19 NRC。下面这张表是我这几年踩过的NRC场景汇总:

NRC含义常见触发场景
0x11serviceNotSupportedECU根本没实现0x19服务
0x12subFunctionNotSupported0x06在当前软件版本里未使能
0x13incorrectMessageLengthOrInvalidFormat新旧版本recordNumber必填/可选不一致,请求长度与ECU期望不符
0x22conditionsNotCorrect会话模式不对或安全等级不够
0x31requestOutOfRangeDTC不在故障内存中、recordNumber超出支持范围、该DTC没有扩展数据记录
0x33securityAccessDenied0x06被OEM放在安全访问之后,解锁失败或无解锁资格
0x7FserviceNotSupportedInActiveSession当前会话(如编程会话)不支持0x19

这里要特别提醒:NRC值为0x7F时表示“服务在当前会话不支持”,注意这个0x7F是NRC取值,不要和否定响应报文的固定首字节0x7F混淆。另外,同一个“DTC不存在”的场景,不同ECU可能回不同的NRC:有的严格按标准回0x31,有的图省事回0x13,还有的会在“DTC存在但记录号不支持”时回0x22。诊断工具在UI上应该把原始NRC完整显示出来,而不是做一层“翻译”之后丢给用户一个模棱两可的“读取失败”。我见过售后工程师因为工具把0x31翻译成“系统内部错误”,直接放弃了排查,实际上只是DTC被清码了而已。

3. 三个实战场景:售后、产线和台架验证

3.1 售后场景:用扩展数据区分“偶发”和“早期失效”

0x06在售后最值钱的应用,是帮你把“偶发故障”和“零部件早期失效”分开。

举个例子:两台车报了同一个DTC,都处于confirmed状态。车A的0号计数器是1,环境温度记录显示故障只出现在零下10℃的冷启动工况;车B的0号计数器已经到15,环境温度记录横跨-10℃到35℃。同样的DTC,前者指向线束、接插件这类受温度影响的偶发问题,后者更可能指向零部件本身的退化或软件逻辑缺陷。如果不读0x06,只看状态位,两台车在你面前表现完全一样,维修方案只能靠猜。

诊断工具的实际操作链路建议是:先用0x19 0x02按confirmedDTC状态掩码拉列表,再用0x19 0x06加特定记录号读取计数器和环境参数。注意,读之前要看一眼statusOfDTC,如果当前只是pendingDTC而不是confirmed,计数器可能刚刚清零或者只加了1,这时候下结论为时过早。还有一个容易被忽略的点:清码之后故障内存里的扩展数据也会被清除,此时读0x06大概率收到0x31。这不是ECU坏了,而是你把“病历本”给扔了。

3.2 产线EOL与刷写后的验证

刷写相关的流程,比如我们常说的UDS刷写流程里最典型的几步:10 02进入扩展会话、27 01/02安全解锁、31 01擦除、34/36请求下载和传输数据、37退出传输、11 01复位。整套跑完之后,最容易忽略的一步是“验证故障内存状态”。很多产线只检查刷写是否成功、版本号是否更新,却忘了在EOL下线检测阶段把故障内存清干净并确认没有新增DTC。

0x06在这里有两个用法。第一个用法是刷写后读关键DTC的0号计数器:如果某个DTC的计数器在刷写后异常增长,说明刷写过程或初始化流程里存在不稳定因素。第二个用法是在EOL功能测试结束后,利用扩展数据记录里的“下线测试标志”或“累计循环计数”字段,确认测试项确实执行到位,而不只是“没有报故障”。有些ECU的老化计数器会记录测试循环次数,读出来和产线工位上传的数据一对比,马上就能发现漏测。

这里有个时序坑:刚完成刷写并复位后,故障内存可能还没有完成初始化,此时立刻发0x19 0x06大概率会收到0x31。正确做法是先发0x19 0x02确认DTC表可用,或者等ECU上电自检完成后再读。产线节拍再紧,这个等待也省不掉,否则就是拿误报去浪费返修工位的时间。

3.3 台架耐久和数据统计:把计数器变成质量决策依据

台架或耐久测试里,0x06的计数器数据可以做成趋势曲线。我过去在项目里做过一个脚本:每跑完一个循环,自动用0x06读取目标DTC的故障发生次数计数器和老化计数器,写入数据库。几百个循环下来,哪些DTC在稳定增长、哪些DTC突然跳变,一目了然。这种“长时间序列”比单次读到的绝对值更有价值。

批量读取时要注意总线效率。经典CAN的单个数据帧最多8字节,而0x06的响应里有DTC、状态位和一大段扩展数据,通常需要ISO-TP多帧传输。如果对几十个DTC轮询,响应时间会明显拉长。我的建议是只对测试关注的那几个DTC做0x06轮询,不要图省事用0x11去一次拉全量——那个响应体更大,而且会把你不需要的DTC数据也倒出来,统计时还得做过滤。

4. 避坑指南:OEM实现差异和协议栈兼容性是主要痛点

4.1 坑一:DTC编号编码方式,别拿别人的车套自己的解析

3字节DTC的编码并不是全行业统一的“大端16位”。ISO 14229-1规定的是整体结构和故障组的位定义,具体到某个DTC怎么映射,很多OEM在SWS软件规范里会有额外说明。更麻烦的是,一部分ECU支持ISO 15031-6的2字节DTC格式,DTCFormatIdentifier会变成0x01。你拿一个写死的3字节解析器去读,轻则解析错乱,重则把两个DTC拼成一个,导致诊断结论全错。

最稳妥的做法是让工具从CDD/ODX里加载DTC编码映射,而不是在代码里硬编码一张“P0302 -> 06 03 02”的转换表。换一个OEM、换一个平台,硬编码就是一颗定时炸弹。我在好几个项目里都遇到过“上一任工程师留下的DTC转换表”,表面上看解析正常,直到遇到一个带扩展记录的新DTC才暴露问题。

4.2 坑二:recordNumber的起始值和记录长度各有各的规矩

标准只约定了0号记录是故障发生次数计数器,但从1号开始每条记录是什么,完全是OEM自由发挥。有的OEM从1号记录开始放环境数据,有的把1号记录定义为“最近一次失败的老化计数器”,还有的OEM压根不实现0号计数器,直接从1号开始。工具侧如果写死“record 0永远是4字节计数器”,遇到不按套路出牌的ECU就会解析出负数或者天文数字。

我在做诊断工具时,把记录号、每条记录的长度和字段布局全部做成可配置项,数据来源就是OEM的CDD文件。每次适配新项目,只需要导入新的诊断数据库,不碰代码。这是目前我见过的、应对OEM差异成本最低的方案。如果你只是临时调试,也至少要把“记录长度”做成可输入项,不要写死在界面里。

4.3 坑三:会话和鉴权前置条件是隐藏的门槛

0x19在默认会话里通常可以读DTC状态列表,但0x06这种带“附加数据”的子功能,很多OEM会把它放到扩展会话里,甚至要求先过SecurityAccess。如果你的工具在默认会话直接发0x06,收到0x22别觉得奇怪,先检查自己有没有完成10 03和27服务的握手。

反过来也有一种情况:ECU刷完软件处于编程会话,0x06被禁用,此时需要发送10 01回到默认会话,或者10 03进扩展会话再读。诊断工具的流程设计里,最好把“当前会话状态”作为一个全局状态机来管理,任何子功能请求前先确认会话满足要求,而不是让用户手动去切来切去。工具自动完成10 03和27 01/02的流程,看起来是小事,但能省掉售后工程师大量电话求助。

4.4 坑四:不知道有哪些DTC时,别用0x06去猜

0x06是“已知DTC”的精确查询,不是枚举接口。如果请求里带了一个故障内存中不存在的DTC,ECU会回0x31。工具如果把这个NRC当异常处理并反复重试,只会把总线搞乱,还可能触发网关的速率限制。

正确的读取顺序永远是:先用0x19 0x02或0x0A拿到DTC列表,再用0x06对关注的DTC做深入查询。需要一次性了解全车扩展数据概况时,用0x11或0x13,不要用循环0x06去穷举DTC。这个顺序问题看似基础,但我确实见过有工具实现成“遍历所有可能的DTC编号逐个发0x06”,结果一个ECU要发几百条请求才能读完,效率极低还容易把总线打爆。

4.5 坑五:ISO-TP超时和P2/P2星参数,别用同一个socket超时糊弄

0x06的响应经常超过单帧长度。在经典CAN上,这意味着一连串FirstFrame、ConsecutiveFrame、FlowControl的ISO-TP交互。很多通用CAN工具对应用层超时和传输层超时不做区分,一旦总线负载高或者ECU响应慢,工具就误判超时,直接断开连接。

按ISO 14229-1的约定,P2是服务器响应时间,默认通常为50ms,P2星是增强响应时间,默认5000ms。慢速ECU在扩展数据准备上可能超过P2,此时应该等待P2星而不是立刻报错。ISO-TP层的帧间超时,比如N_Bs、N_Cr,也要单独设置,不要拿应用层的超时值去套传输层。这个细节在网关转发诊断请求的车型上尤其重要——网关往往会增加几十毫秒的转发延迟,你的工具超时值至少要留出网关的余量。

5. 从协议栈源码和安全视角看0x06

5.1 ECU侧实现:状态机、存储结构和组帧

如果你在做ECU端协议栈,0x06的实现路径可以拆成几步:校验服务ID和子功能是否使能,校验当前会话和安全等级是否满足,校验请求长度是否符合本版本规范,然后在故障内存中查找DTC,再按recordNumber索引扩展数据记录,最后组帧返回。

扩展数据记录通常存在Flash或EEPROM里,但不要每次收到请求都去在线查表,那样响应时间很难压进P2。上电初始化时把DTC索引和扩展数据记录的位置加载到RAM,请求来了直接查内存,效率会高很多。记录本身建议用固定长度的结构体数组管理,每条记录的第一个字段放记录号和长度,方便快速索引和合法性校验。

组帧这一步有个容易被忽略的点:扩展数据可能很长,协议栈要用ISO-TP把响应拆成多帧。如果发送队列深度不够,或者ECU的CAN发送缓冲区被其他高优先级报文占满,就会出现响应被截断或者FlowControl丢失,客户端那边看到的就是一个超时。做压力测试时,要专门构造“同时读多个DTC扩展数据”的用例,把发送队列打爆,确认不会丢帧。

5.2 工具链和自动化测试:从“能读”到“读得对”

诊断工具链比ECU协议栈更容易出现“解析死板”的问题。我建议自动化测试脚本至少覆盖这几类场景:2013版响应(无DTCFormatIdentifier)、2020版响应(有DTCFormatIdentifier)、单记录请求、全部记录请求、0x31否定响应、0x22否定响应,以及ISO-TP多帧重组。每一条都要有对应的报文日志和预期解析结果,回归测试时一键跑完。

我做自动化测试时,会让脚本直接加载OEM的CDD/ODX文件来生成预期值,而不是手工写死DTC和记录字段。这样OEM更新诊断规范后,只要重新导入数据库,测试用例自动同步,不用改一行脚本。这个方法对售后工具、产线EOL工具和台架测试脚本都适用,前期投入半天时间搭框架,后面能省下大量维护成本。

5.3 安全视角:0x06会不会成为信息泄露的突破口

最近圈子里讨论UDS威胁与防御时,很多人只盯着27服务安全访问和34/36刷写这类高危服务,却忽略了0x19 0x06这类“看似无害”的读服务。扩展数据记录里经常包含环境参数、运行计数器、ECU状态标志甚至安全相关数据。攻击者如果拿到了诊断接口,通过反复触发故障、再用0x06读取扩展数据,可以倒推出ECU内部逻辑和故障判定阈值,为后续漏洞分析做铺垫。

防御侧有几个落地做法。第一,默认会话里只开放最小集的0x19子功能,扩展数据记录按敏感程度分级,敏感记录要求扩展会话甚至SecurityAccess。第二,网关对诊断CAN做报文白名单和速率限制,发现高频0x19/0x06轮询直接丢弃或告警。第三,带远程诊断的T-Box必须做身份认证和会话审计,防止攻击者通过远程链路批量扫描故障内存。这些措施不复杂,但对缩小攻击面很有效。安全测试团队做渗透评估时,也应该把0x06纳入用例,确认它不会泄露不该泄露的记录。

6. 实测记录:一条真实报文的逐字节走读

6.1 从请求到肯定响应,完整链路长什么样

下面这条记录来自某款ECU在扩展会话且安全解锁后的实测抓包。为方便讲解,假设该OEM把P0302编码为06 03 02,要读的是1号扩展数据记录。

请求帧:

19 06 06 03 02 01

ECU在几十毫秒内返回的肯定响应,经过ISO-TP重组后如下:

59 06 00 06 03 02 08 01 2C 00 01 00 00 00 00 03 E8

逐字节拆开看:

  • 59:肯定响应SID,0x19加0x40。
  • 06:子功能回显,确认这是0x06的响应。
  • 00:DTCFormatIdentifier为0x00,表示后面是ISO 14229-1的三字节DTC格式。
  • 06 03 02:DTC编号,按OEM约定对应P0302。
  • 08:statusOfDTC,bit3置1,表示confirmedDTC。注意这里没有pending,说明故障已经被确认并存储在故障内存里。
  • 01 2C:1号记录的第1个字段,本例按OEM规范解释为环境温度原始值0x012C,乘上分辨率并减去偏移后得到实际温度。
  • 00 01:1号记录的第2个字段,按规范解释为最近一次失败的老化计数器,当前值1。
  • 00 00 00 03 E8:按本车规范解释为累计发生次数,0x03E8等于1000,说明这个DTC自上次清码以来已经累计触发了1000次。

这段数据里,最值得关注的反而不是前面的DTC和状态位,而是最后的累计次数:1000次触发但状态仍然只显示confirmed,说明这是一个一直在“反复确认、反复清除”的慢性故障,不是偶然事件。对维修决策来说,这个数字比“confirmed”两个字有价值得多。

再来一条否定响应:如果这个DTC刚被清码,故障内存里已经没有它了,请求同样的19 06 06 03 02 01,ECU返回:

7F 19 31

0x31在这里表示requestOutOfRange,即请求的DTC不在故障内存中。这是清码后非常常见的现象,不是工具故障,也不是ECU异常。工具应该把这个场景提示成“该DTC当前不存在,可能已被清除”,而不是简单的红色报错。

6.2 实测性能与超时参数

在同一台设备上连续做了50次0x06读取,单记录响应时间集中在8到15毫秒,基于500kbps的经典CAN总线,响应能用单帧或两帧完成。读取“全部记录”时,响应膨胀到几十个字节,ISO-TP拆成4到5帧,响应时间大约40到80毫秒,主要消耗在帧间间隔和FlowControl上。

批量轮询10个DTC时,我的做法是每次请求之间至少间隔10毫秒。这个间隔不是协议强制的,但能给ECU的诊断任务留出调度时间,避免高频率请求把ECU的主循环拖垮,尤其是在ECU还要同时处理其他测试设备报文的场景下。如果你用网关做诊断转发,间隔还要再放大一些,因为网关本身也会有消息调度延迟。

6.3 几条实操心得

先从最实用的一条说起:任何0x06的解析器,第一行逻辑都应该是“读DTCFormatIdentifier”,第二行逻辑才是“按版本解析”,这两步顺序反了,后面全是错。第二个心得是别迷信标准里的“通用记录定义”,一定要以具体车型的诊断规范为准,同样的record 1在不同平台上可能是完全不同的含义。

第三个心得和工具设计有关:把“2013版/2020版”“带不带DTCFormatIdentifier”“单记录/全记录”做成配置项,而不是写死。目前市面上的存量ECU横跨多个标准版本,一个工具只支持某一版,到了客户现场就是灾难。

第四个心得是关于心态的:遇到0x31先别怀疑ECU坏了,先确认DTC当前是否存在、recordNumber是否在支持范围内,再做下一步。清码之后读0x06收到0x31是正常行为,这不算故障,更不该触发工具的反复重试逻辑。

最后分享一个我常用的技巧:在自动化测试脚本里,把0x06读回来的故障发生次数计数器做成一条“爬坡曲线”。每次测试前后各读一次,对比差值。正常的耐久测试,计数器应该平稳增长;如果某一次测试前后差值突然变成几十倍,说明该轮测试里有系统性问题混进来了。这个技巧帮我在不止一个项目里提前发现了测试台架的异常,比翻几万行日志快得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 4:39:54

全志H5平台AP6212 WiFi移植实战:SDIO驱动、设备树与固件全链路调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 4:39:13

STM32学习不贪不放:核心外设组合拳与实战排错指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 4:39:08

ExternalDNS 对接 Pi-hole 自定义 DNS:从部署到验证的完整指南

云原生 【免费下载链接】external-dns Configure external DNS servers dynamically from Kubernetes resources 项目地址: https://gitcode.com/gh_mirrors/ex/external-dns 点击查看 免费下载 导读 本指南基于 external-dns 官方教程,讲解如何将 Kub…

作者头像 李华
网站建设 2026/9/25 4:38:54

单机记忆翻牌游戏开发实战:状态机、洗牌算法与移动端优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华