从零写一个工控多协议通讯库(一):架构与取舍

发布时间:2026/9/15 6:44:09

从零写一个工控多协议通讯库(一):架构与取舍 本文首发于我的个人博客 talkplc.com同步发布于 CSDN。原文链接https://talkplc.com/2026/07/18/talkplc-architecture/上一篇把 Modbus 一帧报文逐字节拆开讲了。这一篇往上走一层与其每个项目都重写一遍 Modbus/西门子/三菱的收发不如把它做成一套能长期用、能跑嵌入式、还能给上位机绑定的库。这是这个系列的第一篇先把架构和取舍说清楚——协议实现的细节留给后面每一篇。项目代号talkplc。纯净室开发只依据公开协议规范个人时间与设备。为什么又要造一个通讯库工控现场的协议是一堆的Modbus RTU/TCP、西门子 S7、三菱 MC、欧姆龙 FINS/Hostlink、CODESYS…… 每接一个新设备、每起一个新项目都在重复写“打开串口 → 拼一帧 → 算校验 → 收一帧 → 解出寄存器”。已有的轮子里HslCommunication很成熟但主要面向 .NET。我想要的不太一样以 C 为核心能直接跑在嵌入式 Linux / 网关上不背运行时对外暴露干净的 C API方便再包一层给 C# / Python 做上位机模块解耦用哪层链哪层别一上来就拖一坨依赖。对我个人它同时是三样东西一个开源作品集、这个博客的选题引擎每实现一个协议写一篇以及一个长期想做下去的方向。一开始就定死的几条原则纯 C11 内核 干净 C API——最大可移植性绑定友好。传输与协议分离——协议层不关心底下是串口、TCP 还是内存模拟。每层单独成库、可单独链接——只想要 Modbus 帧逻辑那就只链协议模块不拖串口。没有硬件也能测——内置一个内存里的从站模拟帧逻辑不靠真设备就能验证。架构总览分层大概长这样依赖方向自上而下、绝不反向应用 / 上位机 / 绑定 (C#、Python…) │ ┌──────────▼──────────┐ │ gui Qt 监视界面 │ 可视化可选 └──────────┬──────────┘ ┌──────────▼──────────┐ │ poll 后台轮询线程 │ C11 线程对外只给“线程安全快照” └──────────┬──────────┘ ┌──────────▼──────────┐ │ driver 点位(tag)模型 │ 地址类型 → 值连续寄存器批量读 └───┬──────────────┬───┘ ┌───────▼──────┐ ┌─────▼──────────┐ │ modbus 协议 │ │ datatype 类型解码 │ └───────┬──────┘ └────────────────┘ ┌───────▼──────┐ │ serial 传输后端 │ 串口以后加 TCP └───────┬──────┘ ┌───────▼───────────────────────────┐ │ core 状态码 传输接口 收发帧回调 │ 人人依赖的地基 └───────────────────────────────────┘每层的职责模块干什么依赖core状态码、传输接口、收发帧回调trace—serial串口 I/OWindows / POSIX以后同法加 TCPcoremodbusModbus 帧的拼装 / 解析 / 校验不关心串口coredatatype寄存器 ↔ 数据类型u16/i16/u32/i32/f32/bool 字序—driver点位模型 轮询 批量读modbus, datatypepoll把驱动跑在后台线程上对外给线程安全快照drivergui工业风监视界面Qtpoll下面挑三个最关键的设计点讲讲——只讲思路代码点到为止。设计一传输层是一个“字节管道”整套库的地基是把“底层怎么收发字节”抽象成一个接口。协议层只认这个接口永远不知道自己是在串口上、TCP 上还是在一段内存里/* 一个字节管道。串口 / TCP / 内存模拟都实现它就行。 */typedefstructtp_transport{void*ctx;int(*read)(void*ctx,uint8_t*buf,size_tlen,inttimeout_ms);int(*write)(void*ctx,constuint8_t*buf,size_tlen);void(*flush)(void*ctx);void(*close)(void*ctx);}tp_transport_t;就这么几行换来两个大好处以后加Modbus TCP协议帧逻辑一行不用改只写一个新的传输后端测试时塞一个内存里的假从站进去不用真设备就能把收发全流程跑通。设计二协议层只管“一帧”Modbus RTU 的一帧结构很朴素细节见上一篇拆解┌────────┬────────┬──────────────┬────────┬────────┐ │ 从站号 │ 功能码 │ 数据 │ CRC 低 │ CRC 高 │ │ 1 B │ 1 B │ N 字节 │ 1 B │ 1 B │ └────────┴────────┴──────────────┴────────┴────────┘校验用的是 CRC-16/MODBUS公开标准算法多项式0xA001uint16_tcrc16(constuint8_t*p,size_tn){uint16_tcrc0xFFFF;while(n--){crc^*p;for(inti0;i8;i)crc(crc1)?(crc1)^0xA001:crc1;}returncrc;}小验证对 ASCII 串123456789算出来应是0x4B37——这是 CRC-16/MODBUS 的标准校验值拿它当单元测试的“已知答案”很省心。协议层还做了一件对界面很有用的事每收发一帧就通过一个回调把原始字节抛给上层。上层想怎么显示HEX / ASCII、要不要记录都随意——这就是监视界面里“收发帧”那一栏的数据来源。设计三点位模型 后台线程再往上“寄存器地址 数据类型”被抽象成点位tag。你只描述“我要读哪个地址、当成什么类型”轮询之后值就自动填好typedefstruct{charname[32];tp_area_tarea;/* 线圈 / 保持寄存器 / 输入寄存器 … */uint16_taddress;tp_datatype_ttype;/* uint16 / int16 / float32 / bool … *//* ↓ 轮询后自动填充 */doublevalue;bool valid;}tp_tag_t;这一层还顺手做了两件事批量读把同一区域里地址连续的点位合并成一次Modbus 请求而不是一个点位发一帧——少一半以上的往返并发放在 C 库里轮询跑在一个后台线程上C11threads.h那套 API界面只去读一份线程安全的快照。于是就算某个从站不应答、读超时卡住界面照样丝滑不会连“断开”都点不动。值得一提的是并发没有塞进界面框架里——它在纯 C 层。这样哪天不用这个界面、换别的前端甚至做成命令行守护进程后台采集这套照样能用。配套一个工业风监视界面光有库不够直观所以配了个 Qt 写的监视器左边选协议右边配串口、列采集点位、看实时值支持不同数据类型显示底下是收发帧监视可在 HEX / ASCII 之间切。界面只依赖最上面的poll那层通过线程安全快照拿数据——它对底下协议一无所知以后加了新协议界面几乎不用动。反过来界面本身也是可换的。它只和纯 C 的poll层打交道所以 Qt 只是“其中一种前端”桌面 / 上位机拿 Qt 写省事而同一套 C 内核也能驱动一个 LVGL 写的界面直接跑在嵌入式 HMI、触摸屏上。正因为核心是纯 C、不背运行时这条“下沉到设备端”的路才走得通——这也是当初咬定纯 C 的原因之一。接下来这个系列会一个协议一篇往下写Modbus TCP复用现成的帧逻辑换个传输后端 MBAP 头西门子S7、三菱MC、欧姆龙FINS/Hostlink……界面也不只一种桌面 / 上位机继续用 Qt嵌入式 HMI 用LVGL两者共用同一套纯 C 内核——协议、驱动、后台采集一行都不用改。每加一层都会回来对照这张架构图看看——如果新协议逼着我改了地基那多半是当初某个抽象没做对。这也是我留着这套分层、公开写出来的原因之一架构是会被新需求反复拷问的。下一篇Modbus TCP。
延伸阅读

更多相关文章

2026/9/15 6:41:37

AI前端面试黄金准备期:SSE流式处理与TypeScript类型守门实战

1. 为什么9月8号是今年AI前端面试准备的黄金启动日?如果你正盯着日历,犹豫“现在开始准备AI方向的前端面试,到底来不来得及”,那我得先告诉你一个反直觉但被上百份真实offer验证过的结论:9月8号不是太晚,而…

2026/9/15 6:41:37

联合储能系统在配电网优化调度中的应用与Matlab实现

1. 项目概述:联合储能在配电网中的关键作用电力系统正经历着从传统化石能源向可再生能源转型的关键时期。在这个转型过程中,配电网作为连接发电侧和用户侧的"最后一公里",面临着前所未有的挑战与机遇。我最近完成的一个研究项目&am…

2026/9/15 6:41:37

专业图片去水印技术解析与高效工具实操指南

1. 图片去水印工具的核心价值与应用场景作为一名经常处理图片素材的视觉设计师,我深知水印对作品完整性的破坏有多严重。无论是从网络获取的参考图、客户提供的带版权标记的素材,还是自己早期添加水印后需要重新编辑的旧作品,水印的存在往往成…

2026/9/15 6:41:37

别再滥用Redis!后端缓存设计的三个致命误区

去年,我们一个商品详情服务接入了Redis,QPS从两千涨到了两万,团队欢呼雀跃。三个月后,一次缓存雪崩,数据库被打穿,服务瘫痪了四十分钟。复盘时才发现,我们把Redis当成了万能药,却踩了…

2026/9/15 6:36:37

AI论文写作工具评测与职称论文高效写作方案

1. AI论文写作工具的价值与现状作为一名科研工作者和学术编辑,我亲历了从传统论文写作到AI辅助写作的转变过程。职称论文作为专业技术人员晋升的重要依据,其质量直接影响职业发展。但现实中,许多专业人士面临时间紧张、写作经验不足、格式规范…

2026/9/15 4:54:30

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/15 0:01:16

AI英语单词APP开发:自适应学习算法与移动端优化实践

1. 项目概述 作为一名在移动应用开发领域摸爬滚打多年的老手,我最近完成了一个AI英语单词APP的开发项目。这个项目将传统单词记忆方法与现代AI技术相结合,打造了一款能够智能适应不同用户学习习惯的英语学习工具。 市面上大多数单词APP都存在一个通病&a…

2026/9/15 0:01:16

Flutter与OpenHarmony结合开发手语学习APP实战

1. 项目背景与核心价值作为一名同时接触过Flutter和OpenHarmony的开发者,最近我完成了一个基于Flutter for OpenHarmony的手语学习APP实战项目。这个项目最大的特点在于实现了跨平台框架与国产操作系统深度结合的创新实践——用Flutter开发的应用能完美运行在OpenHa…

2026/9/15 0:01:16

六个月成为机器人工程师:从ROS2到SLAM的实战路径

1. 六个月的紧迫感从哪来:先搞清楚你要成为哪种机器人工程师说实话,六个月的期限并不是一个宽松的时间线。市面上任何一本正经的机器人学教材都超过五百页,ROS2的官方文档可以翻到你怀疑人生,再加上ABB、KUKA这些工业机器人厂家动…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码