☰
南自以太网103规约及上位机代码拆解与调试指南
2026/9/30 22:02:17 网站建设 项目流程

简介:面向电力自动化与变电站通信开发人员,这套资料聚焦南自以太网103规约(基于IEC 60870-5-103)的协议要点与上位机实现,可用于理解规约帧结构、服务类型及透明传输机制,并快速搭建与南自设备通信的应用程序。压缩包内共有2个文件,包含1份zip规约说明文档和1个cpp上位机源码,整体大小788KB;zip部分梳理数据帧构造及控制域、地址域、信息域、校验域等核心概念,cpp源码则演示报文构造、编码解码、序列号管理、错误检测与重传、连接管理及心跳报文等关键逻辑。该规约在变电站自动化、电网监控、配电自动化、电量计量等方向广泛应用,已有1442人学习浏览。适合具备C++基础、需对照实际代码调试规约通信的中高级开发者,可据此完善TCP/IP环境下的链路检测与数据分包处理,缩短项目开发周期。 收到这份项目文件时,同事发我的时候也没多说,就一句“南自以太网103规约及上位机代码.zip,你研究一下”。说实话,做电力自动化这行的人看到这个文件名基本就能猜到里面是什么——一套基于IEC 60870-5-103规约的以太网通信实现,外加一套上位机示例工程。这东西在变电站监控系统、继电保护装置联调、配网自动化终端接入这些场景里,属于典型的“绕不开、但资料特别散”的硬骨头。今天我把这套文件的拆解过程、103规约的核心原理、上位机代码的关键模块,以及我自己踩过的一些坑,一次性整理出来。

先说清楚这篇内容适合谁:如果你是刚接手变电站监控后台开发、保护装置通信调试,或者正在做第三方系统对接保护装置的集成工作,那这篇文章可以直接当一份参考笔记用;如果你只是想了解103规约到底是什么、以太网方式和传统串口方式有什么区别,前两部分也够你建立整体认知了。

1. 项目概述:这套文件到底解决了什么问题

1.1 南自设备与103规约的行业背景

南京南自在电力系统里知名度不需要我多说,它的保护测控装置在变电站里装机量非常大。而103规约,全称是IEC 60870-5-103,是国际电工委员会制定的继电保护设备信息接口配套标准。这规约的核心目的,是让保护装置和变电站层监控系统之间能够互相通信——监控系统能召唤定值、接收遥信遥测、拿故障报告和波形,保护装置也能主动上送事件和扰动数据。

过去很多年,103规约主要跑在串口上,RS-232或者RS-485,一个装置一条线,通信速率通常9600bps或19200bps,速度慢、距离短、接线繁琐。后来变电站自动化系统逐步网络化,以太网接口的装置越来越多,厂商就在原有103规约基础上做了以太网传输的扩展。南自的这套以太网103,本质上就是把原本承载在串口链路层上的103应用层数据,改放到TCP/IP网络上传输。听起来就是个换传输层的操作,但实际落地的时候牵扯到会话管理、报文分帧、多客户端接入、故障文件传输等一系列工程问题。

1.2 压缩包内容合理拆解

我拿到手之后先做了个粗略的结构分析,虽然不同项目里这套文件的具体内容会有差异,但一般就这几类东西:

  • 规约说明文档,通常是PDF或者Word,描述了报文格式、ASDU类型、定值区编号、故障文件格式这些。这是最值钱的资料,网上零散的资料根本没法比。
  • 上位机示例代码,语言多见于C++、C#或者Delphi,包含通信模块、协议解析模块、界面工程。我这份代码核心是通信和解析,界面比较简单,但足够说明问题。
  • 配置文件或者配置工具,用于设置装置的IP、端口、装置地址、定值参数等。
  • 可能还有抓包样例、报文日志,方便你对照调试。

这里必须提醒一点:103规约虽然有个国际标准编号,但实际落地的时候,各家厂商都会有自己的扩展和私有定义。南自的装置、南瑞的装置、四方、许继,它们的103实现细节都存在差异。所以这套文件的价值,重点不在“103规约标准”,而在于“南自装置的103实现和对应的上位机对接方案”。你拿着这套东西去接南自的老装置,基本是正路;拿它去接其他厂商设备,只能当参考,不能照搬。

2. 103规约核心原理,为什么要走以太网

2.1 103规约的报文模型

要理解这套代码,先得弄清楚103规约的报文组织。103规约遵循IEC 60870-5系列的基本框架,分物理层、链路层、应用层。应用层的数据单元叫ASDU(应用服务数据单元),由类型标识、可变结构限定词、传送原因、公共地址、信息体地址、信息体元素等字段组成。

举几个常见类型标识,对后续看代码非常有帮助:

类型标识含义用途
1带时标的报文事件顺序记录、SOE
2带品质描述的遥测量测量值上送
5标识报文装置自识别
6时间同步对时
7总召唤全数据召唤
8定值组标识定值区信息
40带时标的扰动数据故障波形启动
45扰动数据传输波形数据

链路层在串口时代用的是IEC 60870-5-1里定义的FT1.2帧格式,有固定的帧头、控制域、地址域、帧校验和。你可以把它理解成一种带校验的“数据信封”,保证一帧数据在串口线路上传输的可靠性。应用层数据被塞进这个信封里,一次传一个或者多个ASDU。

这里我想多说一句为什么要先搞清楚报文模型,因为上位机代码里90%的逻辑都在处理这些报文的组装和解析。你如果一上来就抠代码细节,很容易被各种数组、长度字段绕晕。先建立“信封+内容”的心智模型,再去看代码,思路会清晰很多。

2.2 从串口到以太网的演变,技术和运维双维度的必然

串口103的问题,搞过现场的人一清二楚。首先是接线,每个装置一根通信线拉到监控屏,装置多了就是一个线缆迷宫;其次是速率,9600波特率传输一个完整的故障波形文件动辄要几分钟,而且串口通信半双工机制决定了一问一答的低效;再就是距离和隔离问题,RS-485虽然能到千米级,但现场干扰大时通信质量会明显下降。

以太网方式就直观多了:装置通过网线或者光纤接到站控层交换机,IP地址一配,一根物理链路承载所有装置的通信。传输速率直接到10M/100M,传送波形文件从几分钟缩短到几秒。更重要的是,TCP协议本身提供了可靠传输、重复报文检测、流量控制能力,应用层不需要再纠结链路层的重发机制。

我实际接触下来的感受是:以太网化的103规约,基本把串口时代最折磨人的几个点全部解决了。但天下没有免费的午餐,以太网也带来新问题——多个客户端同时连接的管理、TCP连接断开重连时的状态恢复、报文粘包和半包处理,这些在串口时代根本不存在。所以这份上位机代码里,通信管理部分的复杂度远高于协议解析部分。

2.3 以太网103的关键设计点

南自这套以太网103,我梳理下来有这几个关键设计:

  • 传输层采用TCP协议,装置侧作为服务端监听固定端口,上位机作为客户端主动连接。也有厂家做成上位机做服务端、装置做客户端的模式,但南自这套常见的是前者。
  • 链路层的FT1.2帧结构通常被保留,也就是把FT1.2帧整体作为TCP的负载进行传输。这样设计的好处是应用层的ASDU解析逻辑可以完全复用原来的串口代码,改动成本小。

这个保留FT1.2帧结构的做法,我特意要指出来,因为它直接影响了代码结构。你在上位机代码里会看到,接收缓冲区里处理的数据不是裸的ASDU,而是带帧头、帧尾、校验字的东西。有些刚接触的人容易疑惑:既然走TCP已经可靠了,为什么还要帧校验?答案是历史兼容,以及防止TCP数据流被异常打断时能快速重新定位帧边界。

另一个重要设计是TCP端口与会话状态。装置一般监听一个固定端口(比如2404,和IEC 104规约的常用端口一致),支持多个上位机同时连接。每个TCP连接独立维护收发状态,连接断开后装置侧会清空该连接上的上下文。上位机侧则需要实现断线重连、定时心跳(通常用总召唤或时间同步命令来试探链路状态),否则网络抖动一次,链路就静默了。

3. 上位机代码架构与关键模块实现

3.1 整体框架梳理

打开工程之后,第一件事不是看代码,而是先看目录结构和类/模块划分。我这份代码的结构大致是:

  • 通信层:封装Socket连接管理、收发线程、接收缓冲区。
  • 规约层:处理FT1.2帧的封装与解包,ASDU的组包与解析。
  • 业务层:把规约层解析出来的数据映射成逻辑对象——遥信变位、遥测刷新、事件记录、定值项。
  • 界面层:用于显示数据和手动操作,发送总召唤、对时、定值修改等命令。
  • 公共工具:日志、定时器、字节序转换、CRC校验等。

这个分层思路值得新入行的朋友学习。千万别把Socket收发的代码和ASDU解析揉在一起,不然后期维护绝对崩溃。我见过不少项目把协议解析写在Socket接收回调里,最终代码只能推倒重写。规约层和通信层解耦,你换一种传输方式(比如从TCP改成UDP),上层完全不用动。

3.2 通信层:连接管理与报文收发

通信层的核心任务是可靠地接收完整的FT1.2帧。TCP是字节流协议,没有消息边界,所以上位机必须自己做分帧处理。代码里一般维护一个累积缓冲区,每次收到数据就追加进去,然后循环查找帧头、解析长度字段、判断帧尾和校验,取出一帧完整的数据再交给规约层。

这里有一个几乎所有新手都会踩的坑:直接按固定长度去切数据包。TCP粘包时,一次recv可能收到两帧甚至三帧;TCP半包时,一帧数据被拆成两次甚至多次到达。我写过一个简单的接收循环逻辑,可以给做以太网103的同学参考:

// 伪代码示意:TCP数据接收和FT1.2帧分帧 void OnDataReceived(const char* buffer, int len) { recvBuffer.Append(buffer, len); while (true) { int frameLen = recvBuffer.FindCompleteFrame(); if (frameLen <= 0) break; // 数据不足,等待下一包 std::vector<uint8_t> frame = recvBuffer.Take(frameLen); ProcessFrame(frame); // 交给规约解析层 } }

注意这段逻辑里最关键的是FindCompleteFrame,它需要根据FT1.2的帧格式,先定位起始字符(一般是0x68),然后读长度字段,最后用帧校验和确认。遇到校验不对的帧,直接丢掉并重新同步,而不是硬解析。

3.3 规约解析层:ASDU解析、定值/故障文件处理

规约层处理的东西比较杂,但归根到底就是两件事:组包和解析。

组包就是按照103规约的格式,把类型标识、传送原因、公共地址、信息体地址等字段组装成链路帧发送出去。解析就是逆过程,收到帧后拆出ASDU,再根据类型标识分发到不同的处理函数。比如类型标识是1的报文,代表带时标的SOE事件,解析出保护动作类型、动作时间、动作相别等信息,然后推到界面刷新和数据库记录。

定值处理是103规约里比较繁琐的一环。定值区通常有多个区,每个区里包含数十个定值项,值和属性的格式五花八门(整数、浮点数、ASCII字符串)。上位机代码一般会把这些定值的定义抽象成一张表,每个表项包含定值编号、名称、数据类型、单位、格式,这样召唤定值和修改定值都可以通过这张表驱动,而不是为每个定值写死代码。

故障文件和波形数据的处理更特殊。扰动数据通过类型标识40的ASDU启动,装置先告诉上位机“我这里有一份波形文件,大小多少字节”,然后上位机用类型标识45的报文逐块召唤数据。因为数据量大,往往需要配合重传机制和校验机制。这部分代码通常最复杂,也是最容易出Bug的地方。后面我会专门讲一个常见问题。

3.4 界面与数据服务

界面层在示例代码里往往很朴素,无非就是设备列表、遥信状态表、遥测曲线、事件窗口、定值管理窗口。但它的价值在于验证协议层是否正确。我建议调试的时候,优先把事件窗口和原始报文日志窗口打开,一个显示解析后的结果,一个显示收发的原始报文。两边对照着看,定位问题最快。

数据服务这块容易被人忽略。上位机不只是显示数据,还要把SOE事件、故障报告存下来,所以代码里通常有数据库封装或者文件存储模块。我在实际项目中见过只做界面不做存储的上位机,结果现场要追查三个月前的一次保护动作,数据早就没了。做上位机,存储功能一定不能省,哪怕只是按天记录CSV文件,也比没有强。

4. 实操建议:如何把手里的这套代码跑起来

4.1 环境准备与依赖检查

拿到代码后,先别急着编译。我建议按这四步走:

  1. 确认开发环境。看工程文件是VC++的.sln还是C#的.csproj,或者别的,直接决定了你要不要装对应版本的Visual Studio。老项目大概率是VC6或者VS2008时代写的,新系统编译时会出一堆兼容性问题。
  2. 检查第三方依赖。有些示例代码用到了第三方串口库、数据库组件、图表控件,这些依赖没装齐,编译必然过不去。
  3. 找装置或者模拟器。真机联调最理想,但如果没有装置,可以先用支持103规约的模拟器软件顶替,或者用之前抓包保存的报文文件做回放。
  4. 准备报文分析工具。Wireshark抓包一定要会看,TCP层的交互一目了然。

4.2 配置要点:IP、端口、装置地址

配置是联调的第一步,也是问题高发区。需要注意几类参数:

  • 本机IP和装置IP要在同一个网段,掩码、网关要对。这个看似简单,但现场经常因为IP冲突或者掩码错误导致通信失败。
  • 端口号要一致。装置监听哪个端口,上位机就得连哪个端口,端口错了就连不上。
  • 公共地址(Common Address)必须匹配。103规约里每个ASDU都带公共地址,装置侧和上位机侧对不上,收发的报文都会被丢弃。
  • 装置地址、链路地址有时候和公共地址是一个值,有时是两个值,要看文档说明。

配置这块我的建议是:第一次联调时,把装置侧日志、上位机日志、Wireshark抓包三方同时打开。出了问题,先看抓包,确定TCP有没有建立,再看应用层有没有数据交互,最后看解析是否报错。一层一层往下查。

4.3 联调步骤与验证方法

联调建议从最基础的功能开始,逐步增加复杂度:

  1. 先做TCP连接测试。上位机连装置的端口,观察连接是否建立成功。
  2. 发送总召唤命令。这是最基础的链路确认手段,装置收到后会上送所有的遥信遥测状态。如果总召唤能成功,说明链路层和应用层的基本功能是通的。
  3. 测试时间同步。让上位机下发对时命令,然后看装置是否回确认,时间是否更新。这一步能验证双向通信的完整性。
  4. 测试SOE上送。在装置上模拟一个保护动作或者开入变位,观察上位机事件窗口是否出现带时标的事件记录。
  5. 最后测试定值召唤和故障文件传输,这两块涉及更多报文交互,放到后面单独验证。

5. 常见问题与排查技巧实录

5.1 TCP连不上,抓包看不到连接建立

这是最基础也是最高频的问题。大部分情况是IP或者端口配置错误。但也有一种容易被忽略的情况:装置侧的TCP连接数满了。有些装置的嵌入式系统对并发连接数有限制,比如只允许4个客户端,如果之前的连接没有正常关闭,新连接就进不来。

排查思路:先ping通装置IP,再用telnet测试端口连通性。如果端口不通,看装置的连接列表,把无效连接清掉再试。上位机侧要做好连接的异常关闭处理,程序退出时主动断开Socket,避免占着连接不释放。

5.2 总召唤有响应,但数据解析不出来

这通常不是链路问题,而是ASDU解析的细节对不上。常见原因有三类:

  • 公共地址不匹配,导致报文被过滤掉。这种问题在抓包里能看到完整报文,但代码里没有任何反应。
  • 字节序问题。103规约里的多字节整数一般是高字节在前(大端),但有些装置在实现时用了低字节在前。代码里需要提供字节序转换的开关,或者根据报文特征自动识别。
  • 类型标识或者传送原因没覆盖全。装置上送了一种代码没处理的报文类型,解析逻辑走到default分支直接丢弃了。

经验之谈:解析类问题,最好的办法是拿一份标准报文或者已知正确的报文日志,逐字节对照。把打印日志做到位,每个ASDU的字段都打出来,对照标准一比,很快就能看出哪里偏了。

5.3 故障波形文件传输总是不完整

这个问题在以太网103里相当典型。故障文件数据量大,TCP传输过程中一旦出现网络抖动,或者发送端和接收端的缓冲区设置不当,就容易丢数据。上位机侧的典型症状是:波形文件能开始传输,但传到一半卡住,或者传完后校验失败。

我当时的排查步骤是:第一步看TCP是否有重传(Wireshark里能看到),如果有,说明网络质量不好或者TCP缓冲区太小;第二步看装置的故障文件分帧逻辑,是不是每次发送的数据块过大,导致TCP层分片后接收端重组出错;第三步看接收端的缓冲区大小,必须比装置最大单帧数据大,否则会截断数据。

后面我采用了一个比较稳妥的方案:接收端动态扩容缓冲区,同时增加数据完整性校验,传完后对文件CRC做验证,失败就自动重新召唤一次。这个方案在现场用了很久,稳定性提升很明显。

5.4 时间同步成功但SOE时间还是不对

SOE时标不对,这问题和规约关系不大,更多是装置侧的时钟源头问题。就算上位机下发了对时命令,如果装置本身没有可靠的时钟源,时间走几天又会漂。所以现场一定要保证装置能正常对时,常见做法是配置GPS/北斗对时,或者依赖于站控层定期广播对时命令。

上位机侧的代码也要注意:SOE解析出来的时间是装置自己记录的,上位机不要做任何时区转换。有些新手看到时间不对,习惯性加个8小时偏移,结果过几天又发现差了8小时,来回折腾。先确认原始报文里的时间值,再决定要不要处理。

问题现象可能的根因排查建议
TCP连接建立失败IP/端口配置错误、连接数满先ping后telnet,检查装置连接列表
总召唤有响应但无数据公共地址不匹配、字节序错误、类型未处理对照报文逐字节解析
波形文件传输不完整网络抖动、缓冲区设置不当、分帧逻辑问题抓包看重传,校验文件CRC,失败重召
SOE时间不正确装置时钟源不准、时区处理错误确认原始报文时间值,检查对时源

最后说几句实在的

这套“南自以太网103规约及上位机代码.zip”折腾下来,我最深的体会是:在电力自动化这个领域,规约这东西永远是“标准给你画了框架,细节全靠自己趟”。103规约的标准文档你可以从各种渠道拿到,但南自装置具体怎么实现、上位机代码里哪些地方做了兼容性处理,这些只能靠实际工程积累。

如果你正要开始接触这个项目,我的建议是三个字:先抓包。任何文档、任何代码,都不如一份真实的报文日志来得直观。把报文结构吃透了,再看上位机代码,你会发现那些看似复杂的函数都变得很好理解。而如果你是想把这套方案移植到自己的项目里,记住别把通信层、规约层、业务层揉在一起,这个架构原则比任何具体代码都重要。

最后再分享一个小技巧:调试103上位机的时候,在代码里加一个“原始报文备份”功能——把所有收发的报文按时间顺序完整记录到本地文件。现场出了问题,远程把日志要过来,本地回放报文,很多问题不去现场就能定位。这个习惯帮我在无数个远程支持场景里省下了大量时间。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询