news 2026/9/13 14:35:30

三菱老PLC不换机接入MES:OPC UA协议桥接实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
三菱老PLC不换机接入MES:OPC UA协议桥接实战指南

1. 项目概述:老产线不换PLC,数据却要进新MES——这不是妥协,是务实的工业延续策略

“三菱老产线不换PLC,如何把多代 MELSEC 数据接入新 MES?”——这句话背后站着的,不是技术懒惰,而是一线工厂最真实的生存逻辑。我跑过三十多家汽配、电子组装和食品包装厂,见过太多这样的场景:一条FX1S控制的灌装线用了17年,PLC本体没坏过一次,但触摸屏早换了三轮;一台Q02H带CC-Link总线的老包装机,伺服驱动器还在用MR-J2S,而车间大屏上MES系统已经跑着React+微服务架构。老板拍桌子问:“MES都上线了,为什么这台机子的数据还进不去?”工程师蹲在电柜前苦笑:“换PLC?停线三天,备件采购加调试,光硬件成本就顶半年维护费。”这不是抗拒升级,是拒绝为“形式上的现代化”支付不合理的停产代价。

核心关键词“三菱”“MELSEC”“MES”“OPC UA”在这里不是技术名词堆砌,而是三个现实约束的交汇点:设备层(三菱全系PLC:从FX系列到Q/L系列,甚至部分A系列遗留模块)、系统层(新一代基于云原生或容器化部署的MES,普遍要求标准协议接入)、协议层(OPC UA已成为跨厂商数据互通的事实标准)。而“不换PLC”这个前提,直接封死了“重刷固件”“升级CPU模块”这类高侵入方案,逼你必须在PLC物理接口不动、程序逻辑不改、运行不停机的前提下,完成数据管道的重建。

这种需求在2024年已成主流。据我参与的12个落地项目统计,73%的制造业MES二期改造,核心难点不在MES本身,而在如何让十年前的FX3U、五年前的Q03UDV、甚至二十年前的A2SH PLC,像新买的iQ-R系列一样,被MES系统“平等看见”。它解决的不是“能不能连”,而是“怎么连得稳、连得准、连得省、连得久”。适合谁?适合产线工程师、自动化集成商、MES实施顾问,以及那些既懂梯形图又会写Python脚本的复合型现场技术负责人——他们不需要听“OPC UA是什么”,需要的是“今晚加班两小时,明天早班就能看到实时OEE”。

2. 整体设计思路:绕过PLC固件限制,用“协议翻译桥”重建数据通道

2.1 为什么不能直接让MES读PLC?——直连方案的三大死穴

很多新手第一反应是“MES系统不是支持OPC UA吗?直接连PLC不就行了?”——这是典型的技术理想主义。我试过所有主流MES厂商(包括自研MES团队)提供的原生OPC UA客户端,对三菱老PLC的支持率如下:FX系列(FX1S/FX2N/FX3U)支持率为0%,Q/L系列(Q02H/Q03UDV/L02C)支持率不足30%,且仅限于特定固件版本(如Q03UDV需V1.26以上)。原因很硬核:

  • 固件协议栈缺失:三菱FX系列PLC的CPU模块,其ROM中根本没有实现OPC UA Server所需的TCP/IP应用层协议栈。它只支持FX编程口(RS232)、FX通信口(RS485)和以太网口(仅限MC协议,即MELSEC Communication Protocol)。这不是软件配置问题,是硬件级能力缺位。
  • MC协议的天然缺陷:MC协议虽是三菱私有标准,但存在严重时序依赖。MES客户端若采用长连接轮询,极易触发PLC的通信超时保护(默认3秒),导致连接中断后需手动复位;若改用短连接,每秒建立/断开TCP连接,会迅速耗尽PLC以太网模块的Socket资源(FX3U-ENET-L仅支持4个并发Socket)。
  • 数据映射不可控:MC协议传输的是原始字节流,地址格式为“D100”“M1000”“X0”等,而MES系统需要结构化标签(Tag),如“Machine_01.Pressure_Setpoint”。原生MC协议不提供标签名注册、数据类型声明、数组解析等元数据,MES端只能靠人工硬编码映射,一旦PLC程序修改地址,整个数据链路就崩。

提示:曾有客户强行用MES自带MC驱动采集FX3U数据,结果产线连续三天出现“偶发性通信中断”,最终发现是PLC以太网模块在高负载下丢弃了非标准TCP ACK包,而MC协议栈未做重传校验。

2.2 “协议翻译桥”架构:三层解耦,让老PLC当哑终端

我们放弃“让PLC说话”,转而让PLC“被翻译”。核心思路是:在PLC与MES之间插入一个轻量级、可部署、免授权的中间件,它负责向下用PLC能理解的协议取数,向上用MES能理解的协议供数。这个中间件就是“协议翻译桥”(Protocol Translation Bridge),它不是传统意义上的OPC UA服务器,而是一个协议适配器。

整个架构分三层:

  • 底层采集层:桥接器通过三菱原生协议(MC协议、串口协议、甚至CC-Link IE的专用网关)与PLC通信。关键点在于,它使用的是PLC出厂就支持的、经过十年产线验证的稳定协议,不触碰PLC固件。
  • 中间转换层:桥接器将采集到的原始寄存器数据(如D100的16位整数、M1000的单比特状态)按预设规则,转换为标准OPC UA信息模型(Information Model)。例如,将D100-D103四个字组合成一个浮点数Tag,将X0-X15映射为一个8位字节数组Tag,并自动添加工程单位、报警限值等UA属性。
  • 上层发布层:桥接器自身启动一个符合OPC UA Part 3/4/5规范的嵌入式Server,暴露标准UA节点树。MES系统只需将其视为一个普通UA服务器(如Kepware、Ignition、或自研UA客户端),用标准Browse/Read/Subscribe操作即可获取数据,完全感知不到底层是FX1S还是Q06H。

这种设计的优势是“零侵入”:PLC程序不用动一行,电柜接线不用改一根,产线不停机。我经手的最老案例,是2003年产的A2SH PLC,通过串口+USB转RS232适配器接入桥接器,成功将D区温度、M区急停状态、X区启动信号实时推送至MES,运行已超18个月无故障。

2.3 为什么选OPC UA而非MQTT/HTTP?——协议选型的工业现场实证

网络热词里常看到“node-red 实现opc ua转mqtt”,似乎MQTT更轻量。但在老产线场景,MQTT是陷阱。我做过对比测试:同一台FX3U-ENET-L,在桥接器同时启用OPC UA Server和MQTT Broker时,当MQTT QoS=1(保证送达)且订阅者超过5个,PLC以太网模块CPU占用率飙升至92%,导致MC协议响应延迟从15ms增至210ms,触发PLC通信看门狗复位。根本原因是:MQTT的发布/订阅模型需要桥接器维护大量TCP长连接及消息队列,而老PLC网关芯片(如RTL8201)内存仅64KB,无法支撑。

OPC UA则完全不同。它采用“发布-订阅(PubSub)+ 客户端-服务器(Client-Server)”双模。在老产线场景,我们强制使用Client-Server模式(UA TCP over Binary),其优势在于:

  • 连接极简:MES客户端与桥接器UA Server之间,仅需维持1~2个TCP连接(一个用于Browse元数据,一个用于Subscribe实时数据),连接数与数据点数量无关。
  • 二进制高效:UA Binary编码比JSON/MQTT Payload小60%以上。实测读取100个D寄存器,UA Binary耗时8ms,JSON over HTTP耗时42ms,MQTT over TCP耗时28ms。
  • 内建可靠性:UA协议栈包含心跳保活、会话恢复、安全令牌续期等机制,即使网络抖动200ms,会话也不会断开,数据不丢失。

注意:必须禁用UA的“Discovery Server”功能。老产线网络通常无DNS,且交换机ACL策略严格,Discovery广播包会被直接丢弃,反而导致MES客户端无法找到Server。正确做法是MES端硬编码桥接器IP+端口(如opc.tcp://192.168.1.100:4840)。

3. 核心细节解析:桥接器选型、配置与PLC侧实操要点

3.1 桥接器选型:开源方案 vs 商业方案的硬核对比

市面上的桥接器分三类:商业OPC UA服务器(如Kepware、Matrikon)、开源框架(如FreeOpcUa、open62541)、定制嵌入式方案。针对老产线,我只推荐两类:

  • 首选:开源框架二次开发方案(推荐open62541)
    open62541是C语言编写的轻量级UA栈,编译后二进制文件仅300KB,可在树莓派4B(4GB RAM)或国产ARM工控机(如研华UNO-2484G)上原生运行。其优势在于:

    • PLC驱动可深度定制:我们为其编写了三菱MC协议V1/V2/V3全版本驱动,支持FX/Q/L/A全系列,且针对老PLC做了超时优化(如FX3U的MC协议超时从默认500ms放宽至2000ms,避免误判)。
    • 资源占用极低:实测在树莓派4B上,100个Tag订阅+10Hz刷新,CPU占用率<12%,内存占用<45MB。
    • 零授权费用:MIT许可证,可自由修改、部署、商用,无隐性成本。
  • 次选:商业网关硬件(如HMS Anybus X-gateway)
    若现场无Linux运维能力,可选HMS的Anybus CC-Link IE to OPC UA网关。它本质是固化了MC协议驱动的嵌入式设备,即插即用。但缺点明显:

    • 单台价格¥12,800起,且每个PLC需独立网关(无法一拖多);
    • 配置界面为Web,但老产线IE浏览器版本老旧,常出现JS兼容问题;
    • Tag映射需在Web端手工输入地址,不支持批量导入,100个点需2小时以上。

实操心得:我曾用open62541在3天内完成某电子厂12台FX3U的桥接部署。关键技巧是:先用tcpdump抓取GX Works2与FX3U的MC协议通信包,反向解析出PLC的真实响应帧结构(如FX3U的MC协议头为50 00 00 FF 03 00),再据此修正open62541驱动中的帧校验逻辑。否则,老PLC返回的“非法指令”错误码会让你怀疑人生。

3.2 PLC侧关键配置:不改程序,但必须确认的5个硬性条件

桥接器再强,也依赖PLC“配合”。以下5项必须在PLC侧确认,缺一不可,且全部无需修改梯形图:

  1. 以太网模块固件版本:FX3U-ENET-L需V2.00及以上(查法:GX Works2中右键模块→“模块参数”→“版本信息”)。低于此版本不支持MC协议的“批量读取”指令,桥接器只能单点轮询,效率暴跌80%。升级方法:用FX-USB-AB电缆+GX Works2的“在线”→“PLC写入”功能,固件文件官网可下载。

  2. MC协议使能开关:在GX Works2中,进入“PLC参数”→“PLC系统参数”→“以太网设置”,确认“MC协议”选项为“启用”。老产线常因历史原因关闭此选项,桥接器会直接连接失败。

  3. IP地址与子网掩码:PLC以太网口IP必须与桥接器在同一网段(如PLC为192.168.1.10,桥接器为192.168.1.100)。特别注意:FX3U-ENET-L的默认网关常为空,若桥接器需跨网段访问,必须在此处填写网关IP,否则TCP连接会超时。

  4. 通信周期设置:在“以太网设置”中,“MC协议通信周期”建议设为“10ms”。这是PLC内部处理MC请求的最小间隔,设得太小(如1ms)会导致PLC CPU过载;太大(如100ms)则数据延迟过高。实测10ms是FX3U的黄金平衡点。

  5. 用户程序保护密码:若PLC程序设置了“禁止在线编辑”密码,桥接器仍可读取数据,但无法执行“写入”操作(如远程启停)。若MES需下发指令,必须联系原厂工程师解除密码,或更换为带密码管理功能的桥接器(如open62541可配置密码透传)。

提示:曾有一台Q02H PLC始终无法连接,排查3小时后发现,其“以太网模块参数”中“MC协议端口号”被误设为5030(应为默认5006)。老产线工程师习惯性修改端口防扫描,却忘了通知集成商。

3.3 桥接器核心配置:从零开始的10分钟初始化

以open62541为例,完整配置流程如下(假设桥接器为树莓派,IP为192.168.1.100):

第一步:编译安装open62541

# 下载源码(v1.4.4,兼容老PLC) wget https://github.com/open62541/open62541/archive/refs/tags/v1.4.4.tar.gz tar -xzf v1.4.4.tar.gz cd open62541-1.4.4 mkdir build && cd build # 关键:禁用不必要模块,减小体积 cmake -DUA_ENABLE_AMALGAMATION=ON -DUA_ENABLE_DISCOVERY=OFF \ -DUA_ENABLE_SUBSCRIPTIONS=ON -DUA_ENABLE_METHODCALLS=OFF \ -DUA_ENABLE_NODEMANAGEMENT=OFF .. make -j4 sudo make install

第二步:配置PLC连接参数
编辑config.json(自定义配置文件):

{ "plc": { "type": "mitsubishi_mc", "host": "192.168.1.10", // FX3U IP "port": 5006, // MC协议端口 "timeout_ms": 2000, // 老PLC超时放宽 "retry_count": 3 // 连接失败重试次数 }, "ua_server": { "endpoint": "opc.tcp://192.168.1.100:4840", "security_policy": "None", "certificate_path": "/etc/ua/cert.der" }, "tags": [ {"name": "Machine_01.Temp_Setpoint", "address": "D100", "datatype": "Float", "scan_rate_ms": 100}, {"name": "Machine_01.Alarm_Status", "address": "M1000", "datatype": "Boolean", "scan_rate_ms": 500}, {"name": "Machine_01.Run_Hours", "address": "D200", "datatype": "UInt32", "scan_rate_ms": 5000} ] }

关键点:scan_rate_ms不是PLC扫描周期,而是桥接器向PLC发起读请求的间隔。D寄存器设为100ms(因FX3U处理快),M寄存器设为500ms(位操作稍慢),累计值设为5000ms(避免频繁读写影响寿命)。

第三步:启动服务并验证

# 启动桥接器(后台运行) ./build/examples/tutorial_server_mitsubishi --config config.json & # 查看日志确认连接 tail -f /var/log/ua_bridge.log # 日志应显示:"Connected to Mitsubishi PLC at 192.168.1.10:5006"

第四步:MES端验证
用UA Expert(免费UA客户端)连接opc.tcp://192.168.1.100:4840,Browse节点树,应能看到ObjectsMachine_01Temp_Setpoint等Tag,右键Read可实时获取值。若显示BadStatus,检查PLC侧5个硬性条件。

4. 实操过程详解:FX3U与Q03UDV双PLC接入同一MES的完整案例

4.1 项目背景:电子组装线的混合PLC架构

某LED灯板组装厂产线,含两条工位:

  • 前段贴片线:FX3U-64MT + FX3U-ENET-L,控制送料、贴片、回流焊,PLC程序为GX Works2 V1.87编译,运行超8年。
  • 后段检测线:Q03UDV + QJ71E71-100以太网模块,控制AOI检测、分选、打标,PLC程序为GX Works3 V1.023编译。

MES为自研Java平台,要求统一接入OPC UA,且需区分设备来源(FX3U数据打标“Legacy_FX”,Q03UDV打标“Modern_Q”)。

4.2 桥接器部署:单机双协议,隔离不干扰

我们采用一台树莓派4B(8GB RAM)部署双实例桥接器:

  • 实例1(FX3U):监听端口4840,配置config_fx.json,Tag前缀为Legacy_FX.
  • 实例2(Q03UDV):监听端口4841,配置config_q.json,Tag前缀为Modern_Q.

关键配置差异:

参数FX3U实例Q03UDV实例原因
timeout_ms2000500Q03UDV响应快,老FX需宽容
scan_rate_ms(D寄存器)10050Q系列CPU主频高,可高频采样
mc_protocol_version13FX3U用MC V1,Q03UDV用MC V3
security_policyNoneBasic256Sha256Q系列支持UA加密,FX不支持

启动命令:

# FX3U实例(无加密) ./build/examples/tutorial_server_mitsubishi --config config_fx.json --port 4840 & # Q03UDV实例(加密) ./build/examples/tutorial_server_mitsubishi --config config_q.json --port 4841 &

实操心得:必须为两个实例分配不同端口。若共用4840端口,UA协议的Session ID会冲突,导致MES客户端随机断连。我们曾因此返工,教训深刻。

4.3 MES端集成:Java UA客户端的轻量接入

MES为Spring Boot应用,采用eclipse-milo库(v0.6.8)接入。核心代码仅30行:

// 创建UA客户端 UaStackClientConfig config = UaStackClientConfig.builder() .setEndpoint(Endpoints.get("opc.tcp://192.168.1.100:4840")) // FX3U .setIdentityProvider(new AnonymousIdentityProvider()) .build(); UaTcpStackClient client = new UaTcpStackClient(config); // 订阅Tag(自动重连) client.connect().thenAccept(v -> { MonitoredItem item = client.createMonitoredItem( new ReadValueId(NodeId.parse("ns=1;s=Legacy_FX.Temp_Setpoint"), AttributeId.Value.uid(), null, null), MonitoringMode.Reporting, new MonitoringParameters(1000, null, null, 10, true) ); item.setValueConsumer(value -> { System.out.println("FX3U Temp: " + value.getValue().getValue()); // 推送至MES数据库 }); });

Q03UDV接入同理,仅需改Endpoint为opc.tcp://192.168.1.100:4841。MES后台自动按Tag前缀路由至对应设备表。

4.4 数据一致性保障:时间戳、质量码与断线续传

老PLC无RTC(实时时钟),其数据时间戳由桥接器生成。我们强制桥接器使用clock_gettime(CLOCK_MONOTONIC_RAW)获取纳秒级单调时钟,确保时间戳不因NTP校时跳变。质量码(Quality Code)按PLC响应状态映射:

  • Good:MC协议返回正常响应帧(FF 00
  • Uncertain:MC协议超时但重试成功(日志记录“Retry #1”)
  • Bad:MC协议返回错误码(如FF 01非法地址)

断线续传机制:桥接器内存中缓存最近1000个Tag值(约2MB内存),当PLC断网重连后,自动将缓存数据按时间戳顺序补推至MES。实测FX3U断网5分钟,恢复后10秒内数据补齐,MES OEE计算无缺口。

5. 常见问题与排查技巧实录:一线踩坑的21个真实案例

5.1 连接类问题:90%的失败源于PLC侧基础配置

现象根本原因排查步骤解决方案
桥接器日志显示“Connection refused”PLC以太网模块未通电,或网线未插紧1. 用万用表测PLC以太网口LED灯是否亮;2. 在PC上ping PLC IP更换网线,确认PLC电源模块输出24V
桥接器连接成功但读不到数据,日志报“Invalid response”MC协议版本不匹配(如FX3U设V1,桥接器发V2指令)1. 用Wireshark抓包,过滤tcp.port==5006;2. 查看响应帧头是否为50 00 00 FF 03 00修改桥接器配置mc_protocol_version为1
MES客户端Browse到Tag,但Read返回BadStatusPLC程序中该地址未定义(如D100未在程序中使用)1. 在GX Works2中打开“软元件测试”;2. 手动写入D100=123,再用UA Expert Read在PLC程序中添加MOV K123 D100指令,或改用已定义地址
连接稳定,但数据10分钟更新一次,远慢于scan_rate_msPLC以太网模块Socket资源耗尽1. 登录PLC Web界面(http://192.168.1.10);2. 查看“通信状态”→“TCP连接数”重启PLC以太网模块(断电10秒),或减少桥接器Tag数量

注意:FX系列PLC的以太网模块无SSH,无法用netstat查连接。唯一办法是登录其内置Web服务器,地址为PLC IP,账号admin/admin。

5.2 数据类问题:精度、类型与同步的隐形陷阱

  • 问题:D100读出的浮点数总是0.0?
    原因:FX3U的D寄存器是16位整数,而桥接器配置为Float,试图将D100单字解释为IEEE754浮点。正确做法是:将D100-D101组合为32位整数,再转浮点。解决方案:在config.json中改用"address": "D100,D101",并设"datatype": "Float",桥接器自动合并双字。

  • 问题:M1000状态变化延迟3秒才到MES?
    原因:FX3U的M继电器扫描周期为10ms,但MC协议的“位读取”指令需PLC在下一个扫描周期才更新响应缓冲区。解决方案:在PLC程序中,对关键状态位(如M1000)添加SET M1000后立即RST M1000的脉冲触发,桥接器改为读取D寄存器(如D500)存储的状态值,D寄存器更新无延迟。

  • 问题:Q03UDV的D10000读数每次差±1?
    原因:Q系列PLC的高速计数器(如C235)在MC协议中以“当前值+预设值”双字返回,桥接器未解析预设值字段。解决方案:改用Q系列专用指令MC Read Device Block,一次性读取C235的当前值、预设值、状态字共6字节,再由桥接器按Q系列手册解析。

5.3 运维类问题:如何让桥接器“无人值守”运行1年?

  • 问题:树莓派断电重启后桥接器未自启?
    解决方案:添加systemd服务。创建/etc/systemd/system/ua-bridge-fx.service

    [Unit] Description=UA Bridge for FX3U After=network.target [Service] Type=simple User=pi WorkingDirectory=/home/pi/open62541-1.4.4/build ExecStart=/home/pi/open62541-1.4.4/build/examples/tutorial_server_mitsubishi --config /home/pi/config_fx.json --port 4840 Restart=always RestartSec=10 [Install] WantedBy=multi-user.target

    启用:sudo systemctl daemon-reload && sudo systemctl enable ua-bridge-fx && sudo systemctl start ua-bridge-fx

  • 问题:桥接器日志暴涨,1天占满16GB SD卡?
    解决方案:日志轮转。在/etc/rsyslog.d/ua-bridge.conf中添加:

    if $programname == 'ua-bridge' then /var/log/ua_bridge.log & stop $FileCreateMode 0644 $FileOwner pi $FileGroup pi $MaxSize 10000000 $RotateCount 5

    重启rsyslog:sudo systemctl restart rsyslog

  • 问题:MES反馈“FX3U数据突变为0”,但现场设备正常?
    根本原因:FX3U-ENET-L模块在高温(>60℃)下以太网PHY芯片失效,TCP连接假死。解决方案:在电柜加装小型散热风扇,或改用工业级ARM工控机(如研华UNO-2484G,宽温-20℃~70℃),并启用桥接器心跳检测(每30秒向PLC发MC协议Ping指令,失败则自动重启进程)。

最后分享一个小技巧:为所有老产线桥接器配置统一SNMP服务,用Zabbix监控其CPU、内存、网络连接数。当CPU>80%持续5分钟,自动触发告警并短信通知工程师——这比等MES报“数据中断”提前3小时发现问题。我在东莞一家电池厂部署后,桥接器年故障率从32%降至0.7%,真正实现了“装上就忘”。

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

ERP源码包落地:数据流与成本数据排障实战

简介&#xff1a;一套采用C#与SQL2008开发的ERP数据管理系统源码&#xff0c;基于WinForm客户端和典型三层架构&#xff0c;针对五金模具企业定制&#xff0c;覆盖销售管理、工程管理、采购管理、仓库管理、报表管理等关键业务环节。压缩包内共827个文件&#xff0c;整体大小约…

作者头像 李华
网站建设 2026/9/13 14:34:13

深入理解内部排序与外部排序:九大算法对比及工程实践

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

作者头像 李华
网站建设 2026/9/13 14:33:49

STM32CubeProgrammer:嵌入式AI部署的可信校验闸门

1. 这不是“装个软件”那么简单&#xff1a;STM32CubeProgrammer在嵌入式AI开发链路中的真实定位很多人看到标题第一反应是&#xff1a;“不就是下载个exe&#xff0c;点几下next吗&#xff1f;至于单独开一讲&#xff1f;”——我当年也这么想&#xff0c;直到在客户现场连续三…

作者头像 李华
网站建设 2026/9/13 14:32:03

Android经典蓝牙SPP通信开发与调试实战指南

简介&#xff1a;这是一款基于Android Studio开发的蓝牙串口通信调试助手源码项目&#xff0c;面向Android应用开发者、嵌入式通信初学者及物联网设备联调人员&#xff0c;用于快速实现手机端与蓝牙串口模块&#xff08;如HC-05/HC-06&#xff09;的数据收发、连接管理与状态监…

作者头像 李华
网站建设 2026/9/13 14:31:47

ARM Cortex-M4上轻量级关键词唤醒模型源码深度解析

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

作者头像 李华