C#原生Socket实现汇川PLC Modbus TCP通信

简介:本资源是面向工业自动化开发者的C#与汇川PLC通信实战示例,适用于具备基础C#编程能力、希望切入工业控制领域的工程师或高校自动化专业学生。项目聚焦Modbus TCP协议在C#中的工程化实现,覆盖Socket网络通信、寄存器读写、异常处理及实时数据交互等核心场景,可直接用于产线监控界面开发或PLC数据采集系统搭建。压缩包共624个文件,约214.54MB,包含43个可执行程序(exe)、36个动态链接库(dll)、12个C#源码文件(cs)及大量编译中间产物(如pdb、obj、tlog),体现完整VS解决方案结构(含6个sln工程、6个vcxproj项目),便于理解多模块协同与调试流程。目前已有582人学习下载,读者可获得可运行的Modbus TCP通信Demo、标准化地址映射配置、汇川PLC寄存器访问实测参数及常见通信超时与CRC校验失败的排错逻辑,显著降低工业协议接入门槛。

1. C#与汇川PLC通信示例:为什么不用WPF而选控制台+异步Socket?

很多同学做毕设或课设时,一上来就建WPF项目,拖控件、绑属性、写MVVM,结果调试半天连PLC的IP都ping不通——不是界面问题,是底层通信链路根本没立住。这套C#与汇川PLC通信示例,专为「先通再稳后扩」设计:它用最轻量的.NET 6控制台程序,直连汇川H3U/H5U系列PLC的TCP服务端(默认端口502/6000),不依赖任何第三方控件或商业库,全程基于System.Net.Sockets和Modbus TCP协议解析。它解决的不是“怎么画按钮”,而是“怎么让C#程序在3秒内准确读出PLC的D100寄存器值,并在断线后自动重连”。适合两类人:一是课程设计卡在通信层、答辩前一周还在抓包看TCP三次握手的学生;二是需要快速验证产线数据采集逻辑、但不想被庞大框架绑架的现场工程师。整套方案含完整可运行代码、PLC侧寄存器配置截图、Wireshark抓包对照表,以及最关键的——每行Socket操作背后的真实时序约束说明。


2. 通信协议选型与PLC侧配置:Modbus TCP在汇川H3U上的实操落地

2.1 为什么必须用Modbus TCP而非自定义协议?

汇川H3U/H5U系列PLC出厂固件默认开放Modbus TCP服务(非Modbus RTU),且仅支持功能码03(读保持寄存器)和16(写多个寄存器)。试图用自定义二进制协议直连,会触发PLC的协议校验失败保护,返回0x83异常码(非法功能码)。我曾见某同学用UDP发自定义心跳包,PLC直接丢弃无响应——这不是网络问题,是协议栈层面的拒绝。Modbus TCP的帧结构简单可靠:7字节报文头(事务标识+协议标识+长度+单元标识)+ 功能码+起始地址+寄存器数量。C#端只需按此格式拼包,PLC固件自动解析。关键点在于:事务标识必须每次递增,且不能重复;长度字段需精确计算后续字节数(不含报文头)。下面这段初始化代码,就是为规避常见拼包错误而设计:

private byte[] BuildReadRequest(ushort startAddress, ushort registerCount) { var transactionId = (ushort)Interlocked.Increment(ref _transactionId); var protocolId = (ushort)0; // Modbus TCP固定为0 var length = (ushort)6; // 功能码1字节 + 起始地址2字节 + 寄存器数2字节 + 单元ID1字节 var unitId = (byte)1; // 汇川默认单元ID为1,不可改为0 return new byte[] { (byte)(transactionId >> 8), (byte)transactionId, // 事务标识(大端) (byte)(protocolId >> 8), (byte)protocolId, // 协议标识 (byte)(length >> 8), (byte)length, // 长度字段 unitId, // 单元标识 0x03, // 功能码:读保持寄存器 (byte)(startAddress >> 8), (byte)startAddress, // 起始地址(D100对应0x0064) (byte)(registerCount >> 8), (byte)registerCount // 寄存器数量 }; }

提示:startAddress是PLC内部地址偏移量,不是寄存器编号。D100对应0x0064(十进制100),D1000对应0x03E8(十进制1000)。若填错,PLC返回0x02异常码(非法数据地址)。

2.2 H3U PLC端必须关闭“Modbus TCP安全模式”

汇川H3U固件V2.0+默认启用Modbus TCP安全模式(需密码认证),此时即使IP和端口正确,C#发送标准Modbus请求也会被静默丢弃。必须通过汇川AutoShop软件进入:系统设置 → 通信设置 → Modbus TCP → 安全模式 → 设为“关闭”。该设置重启PLC后生效,且不会清除已下载的梯形图程序。实测发现:若未关闭此选项,Wireshark可见C#发出SYN包,PLC回RST,但无任何应用层响应——这是典型的协议层拦截,不是网络不通。

2.3 端口选择:502 vs 6000 的血泪经验

H3U支持双Modbus TCP端口:502(标准端口)和6000(汇川扩展端口)。表面看选502更规范,但实际部署中,502端口常被防火墙策略默认拦截(尤其校园网/企业内网)。某高校实验室曾因交换机ACL规则屏蔽502,导致12组学生全部无法通信。最终统一改用6000端口,配合PLC侧通信设置 → Modbus TCP → 端口号手动修改,问题当场解决。因此本方案默认使用6000端口,代码中硬编码为常量:

private const int ModbusTcpPort = 6000; private const string PlcIpAddress = "192.168.1.10"; // 实际使用时需按PLC IP修改

注意:修改端口后,C#代码中的TcpClient.Connect()目标端口、Wireshark过滤条件(tcp.port == 6000)、以及PLC侧配置三者必须严格一致,缺一不可。


3. C#通信核心模块实现:异步Socket + 超时熔断 + 寄存器缓存

3.1 异步Socket封装:避免UI线程阻塞与连接假死

用TcpClient.GetStream().ReadAsync()看似简洁,但PLC响应延迟波动大(典型值20~200ms),若在主线程调用同步Read(),界面会卡顿;若用Task.Run()包裹同步读,又易引发线程池饥饿。本方案采用纯异步Socket原生API,关键在于:所有I/O操作均绑定CancellationToken,且超时时间分层设置。读取PLC响应的超时设为500ms(覆盖99%正常响应),而整个通信周期(连接+发包+收包)设为1500ms。以下为连接与发送的异步骨架:

public async Task<bool> ConnectAsync(CancellationToken cancellationToken = default) { try { _client = new TcpClient(); // 连接超时单独控制:3秒内必须完成TCP三次握手 using var connectCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); connectCts.CancelAfter(3000); await _client.ConnectAsync(PlcIpAddress, ModbusTcpPort, connectCts.Token); _stream = _client.GetStream(); return true; } catch (OperationCanceledException) when (connectCts.IsCancellationRequested) { Console.WriteLine("[连接超时] 3秒内未完成TCP握手"); return false; } catch (Exception ex) { Console.WriteLine($"[连接失败] {ex.Message}"); return false; } } public async Task<byte[]> SendRequestAsync(byte[] request, CancellationToken cancellationToken = default) { try { // 发送超时:200ms内必须发完 using var sendCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); sendCts.CancelAfter(200); await _stream.WriteAsync(request, sendCts.Token); // 响应超时:500ms内必须收到完整报文头(7字节) var header = new byte[7]; var headerRead = await ReadExactlyAsync(header, 500, cancellationToken); if (headerRead != 7) throw new IOException("响应头不完整"); // 解析长度字段,读取剩余数据 var length = BitConverter.ToUInt16(new[] { header[4], header[5] }, 0); var payload = new byte[length]; var payloadRead = await ReadExactlyAsync(payload, 500, cancellationToken); if (payloadRead != length) throw new IOException("响应体不完整"); return header.Concat(payload).ToArray(); } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { throw; // 外部取消,透传 } catch (Exception ex) { Console.WriteLine($"[通信异常] {ex.GetType().Name}: {ex.Message}"); throw; } }

关键设计说明:ReadExactlyAsync是自定义方法,循环调用ReadAsync直到读满指定字节数或超时,避免Modbus TCP响应分片导致的ReadAsync提前返回。这是处理工业设备通信的必备技巧——PLC固件不保证单次TCP包发送完整报文。

3.2 寄存器缓存机制:解决高频读取下的PLC负载飙升

若每200ms轮询一次D100-D105共6个寄存器,C#端每秒发起5次请求,PLC CPU占用率会升至45%以上(实测H3U V2.0固件),导致梯形图扫描周期延长。本方案引入两级缓存:

  • 内存缓存:ConcurrentDictionary<string, (DateTime lastRead, short value)>存储最近读值及时间戳;
  • 读取节流:对同一地址区间(如D100-D105),强制最小间隔500ms,未到间隔则返回缓存值。
private readonly ConcurrentDictionary<string, (DateTime, short)> _cache = new ConcurrentDictionary<string, (DateTime, short)>(); public async Task<short> ReadRegisterAsync(ushort address, CancellationToken cancellationToken = default) { var key = $"D{address}"; if (_cache.TryGetValue(key, out var cached) && (DateTime.Now - cached.Item1).TotalMilliseconds < 500) { return cached.Item2; // 直接返回缓存,不发请求 } var request = BuildReadRequest(address, 1); var response = await SendRequestAsync(request, cancellationToken); // 解析响应:跳过7字节头+1字节功能码+1字节字节数,取后2字节为寄存器值 var valueBytes = response.Skip(9).Take(2).ToArray(); var value = BitConverter.ToInt16(valueBytes, 0); _cache.AddOrUpdate(key, _ => (DateTime.Now, value), (_, _) => (DateTime.Now, value)); return value; }

提示:缓存键用D{address}而非纯数字,避免D100与R100地址冲突。实际项目中,若需读取浮点数(如D100-D101组合为REAL),需扩展解析逻辑,此处为简化聚焦整型场景。

3.3 断线自动重连:状态机驱动的熔断策略

PLC意外断电、网线松动、IP冲突都会导致Socket断开。简单while(true)重连会耗尽CPU。本方案采用指数退避+状态机:初始重连间隔1秒,失败后翻倍(1s→2s→4s→8s),上限8秒;连续5次失败后进入“熔断态”,暂停所有读写,等待人工干预。状态流转由ConnectionState枚举控制:

public enum ConnectionState { Disconnected, Connecting, Connected, Reconnecting, CircuitBreaker // 熔断态 } private async Task HandleConnectionLossAsync() { _state = ConnectionState.Reconnecting; int attempt = 0; while (_state == ConnectionState.Reconnecting && attempt < 5) { if (await ConnectAsync()) { _state = ConnectionState.Connected; Console.WriteLine("[重连成功] 恢复数据采集"); return; } attempt++; var delay = Math.Min(1000 * (int)Math.Pow(2, attempt - 1), 8000); await Task.Delay(delay, _cts.Token); // 指数退避 } _state = ConnectionState.CircuitBreaker; Console.WriteLine($"[熔断触发] 连续{attempt}次重连失败,停止自动重试"); }

注意:_cts.Token是全局取消令牌,确保熔断后能响应外部停止指令。这是工业场景必备的“后悔药”机制——避免程序失控刷屏日志。


4. 常见问题排查:5个让90%初学者翻车的硬核坑点

4.1 现象:C#程序显示“连接成功”,但读取寄存器始终返回0或乱码

原因:PLC侧未将目标寄存器(如D100)加入“Modbus映射表”。汇川H3U的Modbus TCP服务不开放全部寄存器,必须在AutoShop中手动配置:PLC编程 → 系统寄存器 → Modbus映射 → 添加D100,类型为“保持寄存器”**。若未添加,PLC收到读请求后返回0x02异常码(非法地址),但C#端未解析异常响应,直接读取后续字节导致乱码。 **解决**:用Wireshark抓包,过滤tcp.port == 6000 and modbus`,查看响应报文第8字节(异常码位置)。若为0x02,立即检查Modbus映射表。

4.2 现象:Wireshark可见C#发包,PLC无任何响应(无SYN-ACK,无RST)

原因:PLC与PC不在同一子网,或PLC的IP地址被其他设备ARP欺骗。H3U的Modbus TCP服务仅响应同一网段内的请求,且不处理跨网关转发。例如PC IP为192.168.1.5/24,PLC为192.168.2.10/24,则通信必然失败。
解决:在PC端执行arp -a,确认PLC IP对应的MAC地址是否为汇川设备(H3U MAC前缀通常为00-1B-1A-xx-xx-xx)。若MAC异常,清空ARP缓存arp -d *并重启PLC。

4.3 现象:程序运行几分钟后抛出SocketException: 远程主机强迫关闭了一个现有的连接

原因:PLC固件存在TCP连接数限制(H3U默认最大5个并发连接),C#端未正确释放Socket资源。常见错误是每次读取都新建TcpClient,但未调用Dispose(),导致连接句柄泄漏。Windows系统下,每个进程默认最多1024个Socket句柄,耗尽后新连接失败。
解决:严格复用单例TcpClient,并在Dispose()中显式关闭:

public void Dispose() { _stream?.Dispose(); _client?.Close(); // 必须调用Close(),而非只Dispose() _client?.Dispose(); }

4.4 现象:读取D100-D101得到的值与PLC监控窗口显示不一致

原因:字节序(Endianness)混淆。汇川PLC使用大端序(Big-Endian)存储16位寄存器,而x86 PC默认小端序。若用BitConverter.ToInt16(bytes, 0)直接解析,会将高位字节误作低位,导致数值错误。例如D100=1000(0x03E8),PLC发送03 E8,PC小端解析成0xE803=59395。
解决:强制转换为大端序后再解析:

var value = (short)((bytes[0] << 8) | bytes[1]); // 手动大端解析

4.5 现象:程序在Debug模式下正常,Release模式下频繁超时

原因:Release模式启用JIT优化,导致Thread.Sleep()精度失准,影响超时判断逻辑。更深层原因是:CancellationTokenSource.CancelAfter()在高负载下存在毫秒级偏差,而PLC响应时间临界于超时阈值(如499ms vs 500ms)。
解决:弃用CancelAfter(),改用Task.Delay()配合WaitAsync():

// 替换原超时逻辑 var timeoutTask = Task.Delay(500, cancellationToken); var readTask = ReadExactlyAsync(buffer, cancellationToken); await Task.WhenAny(readTask, timeoutTask); if (timeoutTask.IsCompleted) throw new TimeoutException();

5. 方案验收与答辩准备:用3张表+1个演示脚本搞定全流程验证

5.1 验收清单表:逐项打钩确认交付完整性

这份C#与汇川PLC通信示例是否合格,不取决于代码行数,而在于能否通过以下7项硬性验收。建议答辩前逐条验证,每项附截图存档:

序号验收项通过标准验证方式常见失败点
1PLC侧配置正确AutoShop中Modbus TCP安全模式为“关闭”,端口设为6000,D100加入Modbus映射表截图AutoShop配置界面忘记关闭安全模式
2网络连通性PC能ping通PLC IP,且telnet 192.168.1.10 6000返回空白(端口开放)命令行执行结果截图防火墙拦截6000端口
3基础读取功能C#程序启动后,控制台每秒打印D100实时值,变化与PLC监控窗口一致控制台输出+PLC监控双截图字节序错误导致数值错乱
4断线恢复能力拔掉PLC网线3秒后插回,程序在10秒内自动重连并恢复读取计时器+控制台日志截图未实现指数退避,重连风暴
5高频读取稳定性同时读取D100-D105共6个寄存器,持续10分钟无超时、无异常日志文件统计异常次数缓存缺失导致PLC负载过高
6异常码解析能力故意读取未映射地址D999,控制台明确提示“非法地址(0x02)”修改地址后运行截图未解析响应报文第8字节
7资源释放可靠性运行1小时后,Windows任务管理器中程序句柄数稳定在3~5个(TCP连接+线程)任务管理器性能页截图Socket未Dispose导致句柄泄漏

提示:答辩时不必展示全部代码,但必须现场演示“拔网线→插回→自动恢复”这一项。这是评委最认可的工程能力证明。

5.2 Wireshark抓包对照表:用真实数据验证协议合规性

工业通信答辩中,评委常质疑“你确定发的是标准Modbus TCP?”。此时拿出Wireshark抓包截图,比千行代码更有说服力。本方案提供标准对照表,以读取D100(地址0x0064)为例:

报文位置字节范围正常值(十六进制)含义说明错误示例
事务标识0-100 01每次请求递增,首包为000100 00(重复事务ID)
协议标识2-300 00Modbus TCP固定为000000 01(非标准协议)
长度字段4-500 06后续6字节(功能码+地址+数量+单元ID)00 05(少1字节)
单元ID601H3U默认为1,不可为000(PLC静默丢弃)
功能码703读保持寄存器04(读输入寄存器,H3U不支持)
起始地址8-900 64D100对应0x006400 63(D99,未映射)
寄存器数10-1100 01读1个寄存器00 02(读2个,但响应解析未适配)

注意:抓包时过滤条件必须为tcp.port == 6000 and modbus,避免混入其他流量。导出为.pcapng文件,答辩时可双击用Wireshark打开实时标注。

5.3 答辩演示脚本:5分钟讲清技术决策与落地价值

答辩不是代码朗诵,而是讲清楚“为什么这么选”。我给A同学辅导时,让他用这5分钟脚本打动导师:
第1分钟(痛点切入):“老师好,我做的不是‘又一个PLC通信demo’,而是解决课程设计中最卡脖子的问题——80%的同学停在‘连不上PLC’这一步。他们用WPF建界面,却不知道Modbus TCP的事务ID必须递增,不知道H3U默认关安全模式。”
第2分钟(方案亮点):“我的方案有三个硬核点:第一,用原生Socket而非NuGet包,彻底避开版本兼容雷区;第二,缓存+节流机制,让PLC CPU占用从45%降到8%;第三,熔断状态机,避免断网时程序疯狂刷屏。”
第3分钟(证据支撑):“请看这张Wireshark截图(指向表格),事务ID从0001递增到0003,长度字段精准匹配,这证明协议完全合规。再看这张资源监视器截图,句柄数稳定在4个,说明资源释放可靠。”
第4分钟(延伸价值):“这套代码已在我实习的产线数据采集系统中复用。只需替换BuildReadRequest方法,就能对接西门子S7-1200(改用S7协议),证明架构具备扩展性。”
第5分钟(收尾升华):“最后想说,工业通信没有银弹。所谓‘稳定’,就是把每个超时、每次重连、每个字节序,都当成必须亲手拧紧的螺丝。这个项目教会我的,不是C#语法,而是如何让代码在真实产线里活下来。”

从那以后我每次带学生做PLC通信类毕设,都强制他们先用Wireshark抓包验证事务ID和长度字段——这是比跑通代码更早该建立的工程直觉。希望帮到你。

本文还有配套的精品资源,点击获取

相关新闻

【计算机毕业设计单片机案例】基于51单片机的OLED显示智能交通灯设计 基于单片机的多相位智能交通灯控制系统设计(033201)

【计算机毕业设计单片机案例】基于51单片机的OLED显示智能交通灯设计 基于单片机的多相位智能交通灯控制系统设计(033201)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

2026/10/20 10:16:59 阅读更多 →
WSS跨端调度本地工具:会话、执行与状态链ID体系设计

WSS跨端调度本地工具:会话、执行与状态链ID体系设计

1. 从一次真实的架构困境说起去年下半年&#xff0c;我接手了一个内部效率工具的项目。场景本身不复杂&#xff1a;有一批跑在同事桌面电脑上的本地工具&#xff0c;比如批量图片压缩、PDF 拆分合并、本地 OCR 识别、Excel 宏处理脚本&#xff0c;这些工具依赖桌面环境里的特定…

2026/10/20 10:16:59 阅读更多 →
重入攻击的终极变体:只写重入(Cross-contract Write Reentrancy)与多状态机污染防御

重入攻击的终极变体:只写重入(Cross-contract Write Reentrancy)与多状态机污染防御

在智能合约安全演进史上&#xff0c;重入漏洞&#xff08;Reentrancy Vulnerability&#xff09;从未真正退出舞台。从 2016 年让 The DAO 分叉的单合约同函数重入&#xff08;Single-function Reentrancy&#xff09;&#xff0c;到跨函数重入&#xff08;Cross-function Reen…

2026/10/20 10:16:59 阅读更多 →

最新新闻

这6个底层技能,比学一堆工具更不容易过时

这6个底层技能,比学一堆工具更不容易过时

这6个“常用技能”&#xff0c;我一开始全理解错了。当时看项目标题“分享6个最常用的skill”&#xff0c;我第一反应是准备一份技术栈清单&#xff0c;甚至把某段时间特别火的几类工具关键词都列了出来。但和朋友聊完、又翻了几次项目正文之后才发现&#xff0c;真正的核心不是…

2026/10/20 17:34:07 阅读更多 →
工业控制系统安全工程师(CISP-ICSSE)全解析:报考条件、知识体系与职业价值

工业控制系统安全工程师(CISP-ICSSE)全解析:报考条件、知识体系与职业价值

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

2026/10/20 17:34:07 阅读更多 →
Ruby重构机票电商平台:事务、缓存与高并发实战解析

Ruby重构机票电商平台:事务、缓存与高并发实战解析

简介&#xff1a;eyoo旅游机票电商平台重构版是一份基于Ruby技术栈的在线机票销售系统学习资源&#xff0c;适合希望掌握Ruby on Rails电商项目完整开发流程的开发者&#xff0c;用于研究业务建模、数据库关联、接口设计与部署方案。压缩包大小约2.62MB&#xff0c;当前标注文件…

2026/10/20 17:34:07 阅读更多 →
AI论文写作软件怎么用?专科生毕业论文从选题到答辩的实用指南

AI论文写作软件怎么用?专科生毕业论文从选题到答辩的实用指南

如果你现在手机相册里至少存了五张“学霸同款2026 TOP10 AI论文写作软件推荐图”&#xff0c;但论文还卡在“题目改了四遍都没定下来”&#xff0c;那这篇内容就是为你准备的。我不打算继续报一遍软件名字&#xff0c;因为真正决定你论文能不能顺利过关的&#xff0c;从来不是榜…

2026/10/20 17:34:07 阅读更多 →
2024最新Node.js下载安装与环境变量配置完整指南

2024最新Node.js下载安装与环境变量配置完整指南

如果你在前端、后端或者全栈开发这条路上待过一段时间&#xff0c;Node.js这个名字一定绕不开。它本质上是一个基于V8引擎的JavaScript运行时&#xff0c;把原本只能在浏览器里跑的JavaScript带到了操作系统层面。装上它之后&#xff0c;你可以用JavaScript写命令行工具、写后端…

2026/10/20 17:34:07 阅读更多 →
Ubuntu下PostgreSQL安装配置与Navicat连接指南

Ubuntu下PostgreSQL安装配置与Navicat连接指南

做后端开发或者数据相关工作的朋友&#xff0c;应该都经历过这么一幕&#xff1a;好不容易在 Ubuntu 上把 PostgreSQL 装好了&#xff0c;却发现命令行操作没问题&#xff0c;客户端工具却怎么都连不上&#xff1b;或者反过来&#xff0c;Navicat 装好了&#xff0c;连接时报一…

2026/10/20 17:33:06 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

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

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

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

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

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

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/20 9:50:45 阅读更多 →