news 2026/9/28 1:51:32

ARXML文件操作全指南:从导入到删除报文,搞定CANoe数据库管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ARXML文件操作全指南:从导入到删除报文,搞定CANoe数据库管理

1. 先搞明白:ARXML到底是什么,为什么CANoe项目里绕不开它

做汽车电子通信开发的人,早晚会碰到arxml。无论是做AUTOSAR软件组件、ECU提取描述,还是处理以太网Some/IP服务接口,你都会拿到一个甚至几个几十MB的.arxml文件。这东西在CANoe里既是数据源也是调试基础——你定义的信号、PDU、报文能不能被识别出来,直接决定总线仿真的成败。我见过太多人拿着arxml不知道怎么导入、不知道怎么删一段报文,只好把整个文件推倒重新导出,白白浪费一天。这篇就围绕CANoe场景下arxml数据库的创建、编辑与管理展开,把我这些年踩过的坑一次讲清楚。

ARXML,全称是AUTOSAR XML,是基于XML格式的AUTOSAR标准描述文件。它不关心你用的是CAN还是CAN FD,也不管是以太网还是FlexRay,它描述的是“谁在什么时刻、通过什么数据单元、携带哪些信号”这一整套契约。和传统的DBC只描述CAN网络信号不同,ARXML覆盖的范围大得多:从系统级(System Level)的拓扑描述,到ECU级(ECU Extract)的软件组件接口、诊断能力、通信矩阵,全都能塞进这一个格式里。

1.1 从XML到ARXML:一套被定了标准的“契约”

XML大家都不陌生,ARXML就是在XML之上规定了严格的标签语义,所有元素都带命名空间,根节点固定为<AUTOSAR>,内部用<AR-PACKAGES>、<AR-PACKAGE>、<ELEMENTS>分层承载各种对象。你用Notepad打开一个ARXML文件,会看到密密麻麻的<SHORT-NAME>、<CATEGORY>、<I-SIGNAL>、<I-PDU>、<FRAME>等标签,这些就是被标准化的“契约条款”。

为什么说它是契约?因为AUTOSAR工具链之间靠它传递信息。上游的PREEvision、SystemDesk等系统设计工具输出系统描述ARXML,下游的CANoe、DaVinci、EB tresos等工具负责消费这份描述。任何一方改了信号定义,只要重新导出ARXML,另一方重新导入就能拿到最新的“约定”。这比DBC那种散装的Excel导出要可靠得多,也正因为这个机制,ARXML在项目里天然承担着“数据源”的角色。

1.2 ARXML与DBC的分工与取舍

多数从CANoe入门的朋友,最早接触的数据库文件是DBC。DBC简单、直观,CANdb++打开就能看到报文和信号,几十个信号的网络用DBC完全够用。但DBC有它的天花板:它没有软件组件概念,不支持诊断描述,对以太网服务接口更是无能为力。ARXML恰恰补上了这些短板,代价是复杂度上了一个台阶。

我用一个表格把两者的区别列出来,方便你对照选型:

对比维度DBCARXML
主要用途CAN/CAN FD信号级描述系统级/ECU级完整描述
支持网络类型CAN、CAN FDCAN、CAN FD、以太网、FlexRay、LIN
软件组件描述不支持支持SWC、Port、Interface
诊断描述不支持支持ODX、诊断会话控制
工具链生态Vector独有AUTOSAR标准,多工具通用
文件结构扁平文本XML树形结构
编辑工具CANdb++XML编辑器、AUTOSAR工具链

实际项目里最常见的组合方式是这样的:如果只是做CAN总线的网络仿真验证,DBC足够;如果项目涉及AUTOSAR软件架构、需要从系统设计工具导入通信矩阵,或者要同时仿真CAN和以太网,那ARXML是更合适的选择。而且现在很多OEM直接把ARXML作为交付物,供应商拿到的就是“只能读不该乱动”的既成文件,这种情况下你不学会ARXML操作,连门都进不去。

2. 创建ARXML数据库:三条可行的路径

ARXML文件怎么来?这个问题听起来基础,但很多新人会被卡住。你以为它是用某个专用软件“新建”出来的,其实并不完全是。ARXML的本质是XML,它可以从工具链导出,可以在CANoe里通过导入向导生成,也可以手写。三条路径适应不同场景,我逐一拆开讲。

2.1 工具链导出:最省心的正路

正规项目里,ARXML绝大多数不是人写的,而是从系统设计工具里导出的。常见的源头工具包括PREEvision、SystemDesk、DaVinci Developer、Artop平台上的各种插件。在这些工具里画好网络拓扑、定义好信号和PDU、配置好ECU软件组件,然后选择“导出System Description”或“导出ECU Extract”,工具会按AUTOSAR schema生成一份或多份ARXML。

为什么强调这是一条“正路”?因为工具导出的ARXML经过了schema校验,命名空间、元素层级、引用关系基本都是完整的。手写或者抓一个文件随便改,很容易漏掉某个必需属性,导入CANoe时直接报错。我在项目里处理过的ARXML文件,动辄几十MB,里面光<SHORT-NAME>就有上万个,这种量级根本没有手写的可能性。

如果你所在的团队还没有统一的设计工具,也可以借助开源或免费的方案。比如用AUTOSAR官方的Artop基础平台,再配合一套简单的建模脚本,从Excel格式的通信矩阵自动生成ARXML。这听起来复杂,但一旦跑通,比手工维护ARXML可靠得多。后面我会讲到Python生成ARXML的方法,思路与之类似。

2.2 在CANoe里直接建ARXML:轻量场景够用

有读者问,CANoe自己能不能创建ARXML?能,但别指望它像CANdb++建DBC那样所见即所得。CANoe的ARXML“创建”通常是变相实现:你在Simulation Setup里加了网络节点、定义了系统变量和信号,然后通过File → Export功能导出对应的ARXML描述。

不过说实话,直接用CANoe导出的ARXML主要用于“记录当前工程配置”,或者作为给上游工具的反馈。它不像PREEvision那样面向系统设计,所以在软件组件建模、接口设计方面能力有限。我建议的用法是:当你需要快速做一个仿真Demo,不想打开沉重的设计工具,就用CANoe的建模功能把信号和PDU搭起来,然后导出ARXML交付给下游同事。等后续需求复杂了,再回到专业工具里去维护正式模型。

2.3 手写最小模板:应急和查错必备

不要以为手写ARXML毫无用处。当你需要排查“为什么某条报文在CANoe里不显示”,或者需要手工清理几条冗余信号时,能看懂XML结构、能手工改几处标签,比重新走一遍工具链快得多。手写的目标不是“创建一个完整ARXML”,而是“正确修改一个已有ARXML的小片段”。

下面给一个极简的ARXML片段,展示I-SIGNAL的基本结构。这不是完整可发布的系统文件,但结构足够让你看懂信号定义长什么样:

<?xml version="1.0" encoding="UTF-8"?> <AUTOSAR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://autosar.org/schema/r4.0" xsi:schemaLocation="http://autosar.org/schema/r4.0 autosar_422.xsd"> <AR-PACKAGES> <AR-PACKAGE> <SHORT-NAME>DemoProject</SHORT-NAME> <ELEMENTS> <I-SIGNAL> <SHORT-NAME>EngineSpd</SHORT-NAME> <CATEGORY>SIGNAL</CATEGORY> <LENGTH>16</LENGTH> <SIGNAL-TYPE>INTEGER</SIGNAL-TYPE> </I-SIGNAL> </ELEMENTS> </AR-PACKAGE> </AR-PACKAGES> </AUTOSAR>

每个I-SIGNAL必须有唯一的<SHORT-NAME>,<LENGTH>告诉接收方这个信号占几个位,<SIGNAL-TYPE>描述数据类型。看到这个结构,你再回去打开项目里的ARXML,就不会觉得一头雾水了。先认识I-SIGNAL,再顺着找I-PDU和FRAME,整个通信矩阵的脉络就清晰了。

注意:手写或修改ARXML时,务必保持命名空间一致。根节点的xmlns如果被改动,所有标签都会失效,CANoe导入时直接报“Root element not found”或“Namespace error”,这种低级错误最浪费时间。

3. 把ARXML装进CANoe:导入流程与版本匹配

ARXML文件拿到手里,第一步永远是导入。这个环节没那么简单,版本不匹配、schema解析失败、引用缺失,随便哪个都能让你卡在起点。我建议把导入当作一个“验证工具链”的过程,而不是简单点两下菜单。

3.1 导入操作步骤

在CANoe中导入ARXML,版本不同菜单名称略有差异,核心路径是这样的:

  1. 新建或打开一个CANoe工程,建议先选好总线类型(CAN、CAN FD或以太网),因为总线类型会影响后续ARXML中报文和PDU的解析方式。
  2. 在Simulation Setup窗口,找到左侧的“Databases”,右键选择“Add/Import Database”。
  3. 在文件选择对话框中,把文件类型切到ARXML(.arxml),选中目标文件。
  4. 如果你导入的是系统级描述(System Description),CANoe通常会弹出“Select ECU”或“Select Network”对话框,让你选择仿真中要使用的ECU实例或网络簇。这一步很关键,选错了后面信号全乱。
  5. 点击确定后,观察Error Window和Write Window,确认没有报错。

我用过CANoe 16和CANoe 2024,界面细节有变化,但整体思路一致。另外,如果你用的是以太网Some/IP场景,ARXML里可能还包含了Service Interface定义,导入后需要到“AUTOSAR Modules”或者Services面板中确认服务实例是否映射到正确的网络节点。

3.2 导入后必做的三项检查

导入成功不代表万事大吉。我在实际项目中总结了三项必做检查,每次导入后都会过一遍:

第一,看“Database”面板中是否生成了完整的信号树。展开后应能看到Network、ECU、PDU、Signal等层级,数量与ARXML源文件大致对应。如果某个根节点是空的,说明该部分对象没有被解析。

第二,检查总线波特率和通道设置。ARXML导入通常会默认设置速率,但很可能与你仿真环境不符。在CANoe的“Network”配置里,把波特率、采样点、容差等参数与实际总线对齐。否则数据库正常,上车却一帧都收不到。

第三,确认报文与信号是否能关联到你要监控的节点。打开Trace窗口,发送一个测试报文,观察ID和Name是否正常显示。如果ID能显示但Name为空,多半是数据库关联问题,具体排查方法我会在第6节详细讲。

版本匹配是最容易被忽略的暗坑。AUTOSAR schema版本(4.0、4.2、4.3、4.4)与CANoe版本之间不是完全兼容的。老版本CANoe读新版schema的ARXML,会提示“XML Schema not supported”,这时要么升级CANoe,要么让上游工具导出低版本schema的ARXML。很多所谓“文件损坏”,其实只是版本不对应。

4. 编辑ARXML:改信号、删报文到底怎么操作

ARXML的编辑是重头戏,也是热搜词里“arxml怎么删除报文”背后的真实需求。这里我先说一个原则:能小改就不大改,能用脚本改就不用鼠标改。ARXML文件的结构嵌套深、引用关系多,手工大动干戈极易引入隐性错误。

4.1 编辑器选型与XML结构理解

编辑ARXML,别用Windows自带的记事本,也别盲选Notepad++。几十MB的文件,普通编辑器一打开就卡死。我推荐VSCode配XML扩展(比如XML Language Support by Red Hat),或者用XMLSpy这类专业工具。它们的好处不只是显示语法高亮,还能在文件内跳转引用关系,方便跨标签查看信号与PDU的映射。

打开文件后,核心要理解三层结构:最外层是<AR-PACKAGE>,代表一个包,通常是一个子系统或一个ECU的命名空间;包的<ELEMENTS>里放着各种元素对象,包括I-SIGNAL、I-PDU、FRAME、SYSTEM-SIGNAL等;再往下是每个对象的具体属性,如<SHORT-NAME>、<LENGTH>、<CATEGORY>、各种REF引用。

编辑ARXML,记住一个铁律:任何删除操作,必须检查这个对象是否被其他元素引用。比如你要删一个I-PDU,它连着的信号可能没人管,但如果有PDU-TO-FRAME-MAPPING引用了这个PDU,不一起删掉,导入时就会报“Referenced element not found”。

4.2 删除一条完整报文的具体步骤

以“删除一条CAN报文”为例,AUTOSAR里这条报文一般以<FRAME>形式存在,也可能以<I-PDU>存在,不同工具链导出的建模粒度不一样。实际操作时,我建议按下述顺序查找并清理:

  1. 在VSCode中打开ARXML,用Ctrl+Shift+F全局搜索目标报文名(例如MMS_EngineSpeed)。
  2. 找到命中项所在的位置,向上找到完整的<FRAME>或<I-PDU>元素块。确认它的<SHORT-NAME>就是你要删的目标。
  3. 选中整个元素块(从<FRAME>到</FRAME>),剪切并粘贴到临时文件备份。先别急着删除,后面校验有用。
  4. 继续在全文搜索这个报文名。如果它出现在PDU-TO-FRAME-MAPPING、FRAME-PORT、I-SIGNAL-TO-I-PDU-MAPPING等位置,说明存在引用关系。把这些引用整块删除,或根据需求修改引用目标。
  5. 保存文件,用CANoe重新导入,确认无报错后再把临时备份删掉。

第4步最容易出问题。举个例子,一个FRAME里往往承载多个I-PDU,你只删了其中一个PDU,但FRAME还在,那么PDU-TO-FRAME-MAPPING里指向已删除PDU的引用必须同步清理。否则CANoe导入时就会提示“PDU MMS_EngineSpeed not found,referenced in ...”。

4.3 用Python脚本做批量修改

当需要删除一批信号、改一批信号长度,或者批量重命名时,手工逐个操作效率太低。我习惯用Python配合lxml库处理ARXML。写脚本的关键是处理XML命名空间,否则find和iter都找不到元素。

下面是一段删除指定I-PDU的示例脚本,你可以直接改目标名单来复用:

from lxml import etree NS = 'http://autosar.org/schema/r4.0' targets = {'MMS_EngineSpeed', 'MMS_BrakeForce'} tree = etree.parse('EcuExtract.arxml') root = tree.getroot() removed = [] for pdu in root.iter(f'{{{NS}}}I-PDU'): sn = pdu.find(f'{{{NS}}}SHORT-NAME') if sn is not None and sn.text in targets: pdu.getparent().remove(pdu) removed.append(sn.text) tree.write('EcuExtract_cleaned.arxml', encoding='utf-8', xml_declaration=True) print('Removed:', removed)

同理,你可以在循环里遍历FRAME、I-SIGNAL、EVENT等元素,做增删改。我实际用到过的一个场景是:项目切换版本时,需要对所有I-SIGNAL的<LENGTH>批量加8位,这种操作如果手点,几百个信号能点到你怀疑人生,脚本几秒搞定。

提示:用lxml处理ARXML时,write前记得保持命名空间声明。如果文件头部的xsi:schemaLocation或xmlns被丢失,CANoe有可能拒绝加载。最简单的方式是不修改根节点,只操作目标元素。

5. 高效管理:版本、拆分与多文件协同

ARXML文件不会只有一份,同一个项目里可能有系统级ARXML、ECU Extract ARXML、诊断ARXML,还有不断迭代的新版本。放任不管,最后就是文件散落、命名混乱、改完不知影响谁。这里分享一下我在多个项目里落地过的管理方案。

5.1 文件名、目录与版本管理

先定一个命名规范,强制所有文件统一。我习惯用“项目名_系统层级_版本号_日期”的格式,例如BMS_V1.2_SysDesc_20250115.arxml。目录上分出source、imported、archived三个区域,source放上游交付的原文件,imported放经过校验后可导入CANoe的文件,archived放历史版本。

版本管理别只靠文件名后缀,建议把ARXML纳入Git等版本控制系统。ARXML是文本格式,Git可以追踪任意一行改动。但几十MB的ARXML会让仓库很膨胀,所以最好把大文件按AR-PACKAGE拆开,或者用一个单独的仓库存ARXML,不给主代码仓库增加负担。

我踩过的坑:有一次改动版本时,直接基于最新ARXML在VSCode里手动删了几条报文,然后整个文件就用不了了。后来才意识到,那不是最新导出版本,中间有上游同事改过一版,我手里的文件过期了。从那以后,凡是进入修改流程的ARXML,我都先用脚本记录文件哈希值(MD5或SHA256),再做任何改动。导入异常时,先核对哈希,能立刻判断是不是基于旧版改的。

5.2 大文件拆分与合并

超过50MB的ARXML在日常项目里并不少见。文件太大,不光编辑器卡,CANoe导入也慢。拆分的原则很简单:按AR-PACKAGE边界拆,每个包独立成文件。模块A的SWC描述、模块B的通信描述,分别拆成独立文件,互不干扰。

拆分用Python脚本按AR-PACKAGE切割就行,生成每个子文件时,保留根节点和必要的命名空间头。合并则反向操作——确保所有子文件的根节点命名空间一致,然后把多个AR-PACKAGE节点拼到一个根AR-PACKAGES里。合并后的文件需要做一次引用完整性检查,最靠谱的方式就是交给CANoe导入,让错误窗口帮你找出引用断裂的位置。

拆分/合并脚本有一个要注意的细节:ARXML内部很多对象是通过REF DEST="..."来引用的,比如I-PDU里引用了I-SIGNAL的路径。拆分文件时,这些跨包引用还是沿用原始路径,不能因为文件拆了就改动内部引用路径,否则下游工具沿路径找不到目标。路径是/包名/元素名这种格式,与文件切分没有关系。

5.3 ARXML与DBC/CDD协同的实战教训

很多工程在从DBC向ARXML迁移的过渡期,会同时保留DBC和ARXML文件。但CANoe工程里,同一信号的重复定义会导致符号冲突。我的做法是分阶段切换:先在Simulation Setup里只添加ARXML,确认所有信号都能被解析后,再把旧的DBC从工程中移除。两边并存时间尽可能短,否则Trace里的信号名有时来自DBC、有时来自ARXML,排查问题时会非常混乱。

还有一种常见情况是ARXML负责通信矩阵,CDD(CANdela诊断描述文件)负责诊断。两者有少部分重叠,比如诊断报文的ID与会话ID。遇到这类重合,务必以CDD为准。CANoe加载时如果检测到ARXML和CDD中的诊断描述冲突,会出现“Diagnostic description inconsistent”警告。正确做法是在ARXML里把诊断相关部分剔除,只保留网络通信所需的信息。这个动作通常由上游工具完成,手工干预的代价太高,而且容易漏。

6. 常见故障速查与避坑实录

ARXML这块的坑,我用血泪史换来了不少经验。下面这些故障,网上搜索量都很大,我把排查思路和解决办法集中整理出来,希望能帮你省下大量瞎折腾的时间。

6.1 导入失败,错误窗口一堆报错

导入ARXML最怕的就是Error Window刷屏,而找不出头绪。根据我的经验,90%的导入失败原因逃不过这三类:

一是schema版本不匹配。解决方法:确认CANoe版本支持的AUTOSAR schema版本,再和ARXML文件头部的xsi:schemaLocation对比。如果文件是4.4,而你的CANoe只读到4.2,就请对方重新导出,或者升级CANoe。

二是引用关系断裂。报错信息里一般带有类似“Reference not found: XXX”的提示。排查方法:搜索XXX在文件中是否存在,确认大小写是否一致、路径层级是否对得上。AUTOSAR的引用对大小写敏感,<SHORT-NAME>EngineSpd</SHORT-NAME>和路径/DemoProject/EngineSpd差一个字符都不行。

三是文件编码问题。有些工具导出ARXML时带BOM头,有些则不带。CANoe不一定兼容所有编码,遇到解析奇怪地失败,先用Notepad++或VSCode把文件另存为UTF-8无BOM格式,再重新导入。

6.2 Trace窗口没有ID和Name,整行空白

这个问题的经典场景是:总线数据能收到,但CANoe的Trace窗口里ID和Name列是空的,无法解析成报文名。排查顺序要由浅入深,我一般这样走:

  1. 检查Simulation Setup里是否真的添加了ARXML数据库。有时候新开工程忘了拖数据库,数据流确实有,但无法解析。
  2. 检查数据库与仿真通道的关联。不同总线通道对应不同数据库,ARXML加在“CAN 1”上,但你监测的是“CAN 2”,自然解析不了。
  3. 检查Trace窗口的显示列配置。右键Trace窗口,选择“Display Columns”,确认ID、Name列未被隐藏,并刷新一次数据映射。
  4. 如果上述都没问题,那大概率是ARXML导入时符号未能完全解析。回到第3节的内容,重新检查ECU实例选择,或重新导入。

6.3 删了报文还报错,残留引用怎么清理

这一问题最隐蔽。你可能在ARXML里把一个I-PDU删得干干净净,但导入CANoe时依然报“Element X not found”。原因几乎都是残留引用——某个HEADER-EXTRACT、P-DU-TO-FRAME-MAPPING、I-SIGNAL-TO-I-PDU-MAPPING或FRAME-PORT还指向你删除的对象。

我的处理习惯是“先备份,再全局搜索”。用VSCode搜索目标元素名,把所有出现的位置都过一遍,确认每一处引用的上下文。如果你是删I-PDU,就要连P-DU-TO-FRAME-MAPPING一起处理;如果是删FRAME,还要检查网关表、网络拓扑描述里的引用。

写脚本清理比手工逐个删更可靠。上面4.3的脚本示例,其实可以在删除PDU之前,先把所有引用该PDU的mapping节点也收集起来一起移除。用XML解析的好处是,程序不会像人一样疲劳漏看,删得彻底、删得干净。

6.4 文件损坏了怎么办

ARXML文件突然打不开,先别急着问别人要新文件。用XMLSpy或VSCode的XML格式化功能打开,看能否定位到具体错误位置。常见的是某个标签没有闭合,或者某一行被截断。

如果错误位置指向文件的末尾,大概率是不完整写入,比如从U盘拷贝时中断,或者工具异常退出。这种没法修,只能重新导出一份或者从版本管理恢复。如果错误位置在中间,可能是手工编辑时误删了闭合标签,把前后文对照着补回去就行。

这里我特别强调一个习惯:所有ARXML改动完成并通过CANoe导入验证后,立刻提交到Git,或者做一次压缩备份。你不确定下次会改出什么幺蛾子,有备份才是最大的安全感。我就靠这个习惯,无数次把濒临报废的文件捞了回来。

另外,如果你收到的ARXML在源工具里是好的,一进CANoe就报错,别先怀疑文件,先怀疑中间环节。比如邮件传输、网盘同步、压缩解压,任何一个步骤都可能悄悄改变文件编码或截断内容。遇到这种情况,先用文件哈希对比源文件和收到的文件,不一致就找传输链路的问题。


最后分享一个个人经验:ARXML的“高效管理”核心不在工具技巧,而在流程纪律。你得有一个固定的导入验证动作,有一个明确的分工边界(哪些文件来自上游、哪些可以本地改、哪些改动必须回归上游),并且每次改动都留痕。这套流程一旦建立,ARXML再大、版本再多,也不会浪费你一整天去还技术债。

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

STM32 ADC多通道采集:DMA配置与软件滤波实战

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

作者头像 李华
网站建设 2026/9/28 1:50:23

M2 MacBook外接显示器:Type-C转DP与HDMI选线指南

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

作者头像 李华
网站建设 2026/9/28 1:50:18

fastboot刷机原理与Android分区镜像深度解析

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

作者头像 李华
网站建设 2026/9/28 1:49:50

双模SoC实现BLE5.4与私有2.4G融合:无线门锁低时延联动实测

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

作者头像 李华
网站建设 2026/9/28 1:49:29

塑料瓶缺陷检测数据集实战:YOLO格式标注与训练全流程

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

作者头像 李华
网站建设 2026/9/28 1:48:38

QMI8658 I2C驱动开发实战:从硬件连接到稳定数据输出

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

作者头像 李华