ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

IEC103报文解析实战:FT1.2帧格式、ASDU解码与传输优化

IEC103报文解析实战:FT1.2帧格式、ASDU解码与传输优化 调试过保护装置通信的人多半都经历过这种时刻手里握着一串十六进制报文有68 0D 0D 68开头的长帧也有10 10 01 11 16收尾的短帧但就是说不清保护动作、SOE变位到底藏在哪几个字节里。IEC 60870-5-103业内通常简称IEC103是继电保护设备与测控后台之间的老牌通信规约报文解析做得好不好直接决定SOE上送、遥信刷新、扰动数据这些功能能不能稳定跑起来。这篇文章不打算复述标准条文而是把我在现场拆103报文、搭抓包工具、调传输参数时总结的一套实战方法完整讲一遍涵盖FT1.2链路层帧格式、ASDU应用层解码、抓包工具链搭建以及传输优化策略的落地取舍。无论你是刚接手综自后台调试的新手还是需要自研IEC103主站/从站解析模块的嵌入式工程师都可以按这篇文章的思路直接开干。1. 继保通信场景里的IEC103它到底在干什么1.1 我为什么还要回头研究一套20多年前的规约IEC103这套规约的出身可以追溯到上世纪90年代它脱胎于IEC 60870-5-101又为继电保护设备做了专门扩展。和101相比它多了两个非常有特色的东西一是专门针对保护装置的功能类型FUN和信息序号INF寻址方式二是扰动数据传输命令链。换句话说保护动作、故障录波、扰动数据这类继保特有的信息在103里有专门的数据结构来承载而101本身并不擅长这些。你会说现在不都61850了吗现实是存量变电站在未来很长一段时间里仍然有大量保护装置只支持103协议尤其是一些综合自动化改造项目的保护信息子站、规约转换器以及各种继保测试仪在模拟保护装置时最常被要求的通信接口还是103。我这两年做过好几个第三方主站对接保护装置的项目对方一律要求先支持IEC103从站仿真等调通了再谈61850。所以这套老规约不仅没有退休反而因为存量设备多、第三方接入需求大成了继保通信调试里最常遇到的“硬骨头”。研究103还有一种现实意义它的报文结构非常紧凑链路层FT1.2帧格式、应用层ASDU编码方式和101乃至104都有千丝万缕的联系。把103的报文结构吃透了再看101/104的报文很多概念是相通的。这就像一个练过手排挡的人再去开自动挡上手会快得多。1.2 主站-从站模型与报文的方向性103的通信模型很简单主站后台监控、信息子站、规约转换器作为链路层主站主动发起轮询从站保护装置被动应答。主站发请求从站回响应这是基调。主站可以下发遥控、定值、总召唤、复位命令从站上送遥信变位、SOE事件、循环遥测、扰动数据等。解析报文前第一件事永远是要问这帧报文是哪边发给哪边的方向判断错了后面全部白搭。从链路层控制域上可以直接看出来主站→从站的控制域PRM位为1典型功能码包括复位链路、请求1级数据、请求2级数据、下发用户数据从站→主站的控制域PRM位为0ACD位表示“我这边有没有1级数据等着你取”DFC位表示“我忙不过来了你慢点发”。我在项目里见过不少新手拿到一帧68 0D 0D 68 0B 01 ...第一反应“这是主站下发的召唤报文”其实控制域0B的PRM位是0这明显是从站给主站的数据响应帧方向就判断反了。后面所有字段解析都会跟着跑偏。2. FT1.2链路层先把字节流的边界画出来2.1 固定帧一问一答的轻量交互IEC103的链路层帧格式采用的是FT1.2帧结构分固定帧和可变帧两种。固定帧是短帧格式只有5个字节字节序号内容说明10x10帧头固定为0x102C控制域3A地址域一般是从站地址4CS校验和等于CA的算术和取低8位50x16帧尾固定为0x16固定帧用于链路层的轻量交互比如主站复位链路、请求链路状态、请求1级/2级数据以及从站的确认ACK或否认NACK。以最常见的固定帧为例主站复位链路地址为110 10 01 11 16这里第一个10是帧头第二个10是控制域复位链路功能01是地址11是校验和10011116是帧尾。很多人第一次看到这帧报文会愣一下怎么两个10开头记住第一个是帧头第二个是控制域。再比如从站回一个确认帧10 00 01 01 16控制域00就是从站侧功能码中的确认ACK。整个链路层的“握手”就是靠这种一问一答的短帧维持的。实际调试中如果你发现主站不停发复位帧但从站不回应先用固定帧的校验和反推一下通常能发现地址或者控制域编码不对这类低级问题。2.2 可变帧承载ASDU的“集装箱”真正携带业务数据ASDU的是可变帧。可变帧格式如下字节序号内容说明10x68帧头固定为0x682L帧长度3L与第2字节相同重复校验40x68第二个帧头再次出现用于同步确认5C控制域6A地址域7...ASDU链路用户数据长度 L - 2倒数第2CS校验和最后10x16帧尾这里的L指的是从控制域C开始到ASDU最后一字节的长度不包括两个帧头0x68和帧尾0x16。所以一个L13的帧实际总字节数是2帧头2L和重复1帧头131CS1帧尾20字节。实际调103时我建议养成一个习惯拿到一帧可变帧第一件事不是急着看ASDU内容而是先看L字段对不对再看CS校验和能不能对上。很多通信不稳定问题看起来像是“从站没回”实际上是主站组帧时L字段算错了从站在链路层直接丢弃连应用层都到不了。2.3 校验和与帧长字段的边界陷阱CS校验和的计算范围是很多资料里写得比较含糊的地方。固定帧很简单CS (C A) 0xFF。可变帧稍微有一点绕CS从第二个0x68帧头开始累加加上控制域、地址域以及ASDU的所有字节取低8位。我用一个实际帧演示。假设收到一帧从站上送的带时标事件报文68 0D 0D 68 0B 01 06 01 03 01 80 01 00 01 10 05 17 2D 16计算CS时从第二个68开始累加68 0B 01 06 01 03 01 80 01 00 01 10 05 17 104 11 1 6 1 3 1 128 1 0 1 16 5 23 301301取低8位301 - 256 45 0x2D正好和帧末的2D对上说明这帧数据在链路层面没有损坏。这里有一个我踩过的坑少数厂家的103实现CS计算范围不包含第二个0x68只从控制域开始累加。如果你照标准算出来总是不对而又确认物理链路没有问题就去找该设备的协议手册确认它的CS口径。不过绝大多数设备都遵循标准做法从第二个0x68开始累加。帧长字段的边界也值得说。有些人在分析报文时把L算成了“整个帧的总长度”导致解析错位。L的正确含义我在上面已经说明了它是“控制域地址域ASDU”的长度。一帧ASDU最多可以带多少字节L最大255控制域和地址域各占1字节ASDU最多253字节。实际工程中常见的数据帧L值在9到几十之间很少会撑满。3. ASDU应用层从“看起来像乱码”到“每条都像明码”3.1 类型标识、传送原因、公共地址报文的三个身份标签当你确认链路层无误后就可以开始拆ASDU了。ASDU的通用结构如下字段长度说明类型标识TYP1字节这帧ASDU是什么类型的业务数据可变结构限定词VSQ1字节信息体个数及排列方式传送原因COT1字节数据为什么会出现在这里公共地址COA1字节应用层地址通常是保护装置地址功能类型FUN1字节保护功能组编号信息序号INF1字节具体信息点的编号信息体元素集多变状态、测量值、时标、品质描述等三个“身份标签”分别是类型标识、传送原因、公共地址。拿到一帧ASDU先把这三个字节读出来基本能判断它在整个通信流程中扮演什么角色。类型标识TYP常见值以我在多个项目里的经验汇总如下TYP含义0x01带时标的总召唤0x02不带时标的总召唤0x03不带时标的循环数据0x04带时标的循环数据0x05不带时标的突发事件0x06带时标的突发事件SOE0x07扰动数据总查询0x08扰动数据查询命令0x0A扰动数据不同类型有细分0x14通用分类数据需要特别说明不同厂家、不同标准版本对个别类型标识的细分定义会有差异比如扰动数据相关的0x0A到0x0E在有些设备里还会继续拆分。所以这张表适合给你“快速定方向”最终落地点表配置必须以设备厂家协议手册为准。传送原因COT最常用的几个COT含义0x03突发事件触发0x04激活主站下发命令0x05激活确认0x08激活结束0x14总召唤响应0x1E扰动数据传输举个实际流程主站下发总召唤TYP0x01COT0x04从站先回一帧COT0x05的激活确认然后上送多帧COT0x14的总召唤响应数据最后再回一帧COT0x08的激活结束。这一整套流程能跑通链路层和应用层的“对话逻辑”就基本没问题了。3.2 一个可变帧ASDU的逐字节解码还是用上面那帧报文完整拆一遍68 0D 0D 68 0B 01 06 01 03 01 80 01 00 01 10 05 17 2D 16我已经算过L0x0DCS0x2D正确。去掉链路层头尾ASDU部分是06 01 03 01 80 01 00 01 10 05 17逐字节解读06TYP带时标的突发事件也就是常说的SOE。01VSQbit6-01这帧里只有1个信息体bit70表示信息体地址不连续。03COT突发说明是装置主动上送的事件。01COA公共地址1对应设备地址1。80FUN功能类型128在大量厂家规约里128通常对应线路保护主保护功能组。01INF信息序号1。具体含义看厂家映射这里我们假设是“保护动作跳A”。00状态信息体元素假设00分位、01合位这里是分位。01品质描述bit0有效这组数据可用。10 05 17时标CP24Time2a结构具体编码顺序按厂家手册解析。实际做SOE校验时我最关心的就是状态位、品质位和时标三个部分。品质位一旦不是0x00或0x01就要怀疑数据有效性时标字段的毫秒、分钟换算不同设备可能还有“基准时间”差异。这些都是现场对时告警、SOE时间错乱问题的排查重点。3.3 FUNINF保护功能地址映射是查手册还是猜规律IEC103最让新手头疼的就是FUN和INF这套寻址方式。它不像104那样给你一个线性的信息体地址而是分成“功能类型”和“信息序号”两层。FUN指向一组保护功能INF指向该功能下的具体信息点。常规规律可以这样记FUN 128~159通常对应各类保护功能组例如128是主保护129是后备保护等INF低值区1~63多用于状态类信息比如跳闸、重合闸、告警INF中值区64~127多用于测量和扰动相关INF高值区128~255多涉及通用分类、参数读写。但这条规律只是帮你在看报文时建立直觉真正干活时没有厂家手册寸步难行。我见过一个项目第三方设备的手册失踪了后台点表信息又不全现场只能靠“触发变位抓包比对”来反推FUN/INF映射让现场人员操作一次开关分合闸观察报文里出现哪组FUN/INF再对照装置面板指示确认含义。这个方法笨但有效尤其在紧急消缺时能救命。4. 抓包与解析工具链搭对了效率翻倍4.1 RS485/RS232链路如何把报文“提”出来做103调试第一步是把链路上跑的字节流原原本本拿到手。很多后台软件自带规约诊断窗口能看到收发报文这是最省事的。但如果后台没有这个功能或者你是做第三方主站对接就必须在物理链路上“插一根分线”。RS485链路建议这样搭监听准备一个带隔离的USB转RS485工具A接AB接B从通信线上把A、B信号并联引出到转换器不要串接在链路中间避免改变总线拓扑软件侧设置与设备一致的波特率、数据位、停止位、校验位。103最常见的是9600bps、8数据位、1停止位、偶校验也有些厂家用无校验或19200。用任意串口助手以十六进制显示接收数据就能看到链路层原始报文。RS232链路类似但要注意电平标准和串口线序仔细区分TD和RD。用USB转RS232调试时如果发现完全收不到数据先检查是交叉线还是直连线这是串口调试最常见的第一坑。还有一点抓包工具和被监听设备要共地。RS485虽然通常是差分信号但转换器和被测装置之间如果地电位差太大轻则报文乱码重则烧毁接口。用带隔离的转换器能省掉很多麻烦。4.2 用CANoe和脚本把IEC103解析自动化如果只是抓一两帧报文串口助手手工看完全够用。但你要是做整套主站/从站联调或者需要长时间模拟故障、大量收包分析纯手工就不行了。我常用的组合是CANoe加自写解析脚本以及Python离线解析。CANoe本身不是为103准备的协议工具它最强的场景是CAN/LIN总线的仿真和测试但它通过VHSP等串口硬件完全可以接RS232/RS485链路再用CAPL脚本自己实现103的报文解析。我做过的最初版逻辑是设置好串口参数后在CAPL中维护一个接收缓冲区收到字节先找0x68或0x10帧头根据帧类型读取长度字段按L切分完整帧计算CS校验通过后再按ASDU字段逐字节拆分。有了这套基础后续就能自动统计每秒收帧数、连续丢帧数、事件报文类型分布这对定位“偶尔丢SOE”这种间歇性问题非常有价值。CAPL写不下去的时候我会把抓包文件导出用Python写离线解析脚本。Python处理二进制数据非常顺手几十行代码就能把整段抓包记录里的ASDU全部解码成可读内容。说句实在话做这类协议解析工具只是辅助核心是把第2、3节讲的帧结构烂熟于心。工具能帮你省时间但不能替代你对帧结构的理解。4.3 手工解析练习的价值很多人觉得有工具了就不用手工拆报文了我完全不同意。至少在103这类规约调试里工具只负责显示而判断“这帧数据合不合理”必须靠人。我在培训团队时会要求每个人都亲手把类似下面这样的一帧报文完整拆一遍68 0D 0D 68 0B 01 06 01 03 01 80 01 00 01 10 05 17 2D 16流程是固定的同步帧头→验L→验CS→拆ASDU字段→解析业务语义。这个过程做十遍以后你看到任意一帧103报文脑子里会条件反射地标出每个字节的位置。等到了现场周围全是噪音干扰、厂家售后催促、后台刷新超时的压力下这种肌肉记忆才是你能保持冷静的底气。5. 传输优化的四个着力点更快、更稳、更准时5.1 波特率与物理层参数调整的边界103默认跑9600bps的情况很常见但在一些信息点多的场合9600确实有点吃力。一帧20字节的报文在9600bps下大约要传21毫秒每个字节约10位位时间约104微秒如果一秒要轮询几十个装置光链路传输时间就很可观。提高波特率是最直接的优化19200把每帧时间砍半38400再砍半。计算很简单1字节10位字节时间 10 / 波特率。9600下约1.04毫秒38400下约0.26毫秒。一帧30字节的数据从31毫秒降到7.8毫秒差别非常明显。但波特率不是想调多高就调多高。我遇到过老旧电缆井里敷设的RS485线屏蔽层已经破损38400下误码率高得离谱退回19200就基本稳定。所以调高波特率前先确认物理层条件最好用误码率测试跑一段时间再定档。物理层还有几个容易被忽略的点RS485总线两端要分别接120欧终端电阻尤其链路较长时屏蔽层单端接地不要两端都接否则容易形成地环路手拉手接线优于星型接线尽量避免长距离T型分支。5.2 信息体合并与召唤策略减少无效交互应用层传输效率的优化核心是减少“无效交互”。103的ASDU支持通过VSQ字段在一个帧里塞多个信息体例如VSQ0x05就表示这帧里有5个连续的信息体。这样一次链路交互就能上报多条数据比一个信息体一帧要高效得多。但要注意拿捏帧长链路质量好、通道干净时多塞信息体收益很大链路质量差时一帧越长单个字节错误导致整帧重传的代价也越大。我在一个强干扰现场就是故意把VSQ从0x0A降到0x03让事件分帧上送虽然帧数变多但每帧成功率明显提高整体上送时间反而更快。主站侧的召唤策略也要配合调整。总召唤是必要的数据同步手段但频率过高会占用大量链路时间。我的经验是如果事件量不大靠突发数据就能保持状态刷新总召唤可以放到链路建立、设备重启、人工触发几个节点如果需要周期刷新测量值再把循环数据TYP0x03/0x04的周期调大一些给突发事件让路。5.3 1级/2级数据调度让突变量压过周期量103链路层把数据分为1级数据和2级数据两个优先级。1级数据是事件类、扰动类的高优先级数据2级数据是循环量、总召唤响应这类周期数据。主站的轮询逻辑应该保证只要从站ACD位为1就优先发请求1级数据的帧把事件及时取回来。很多现场SOE上送慢问题就出在这个调度顺序上。后台可能每隔几帧才查一次1级数据或者ACD位处理逻辑有缺陷导致从站的事件一直憋在缓冲区里。我排查这类问题时会在抓包记录里统计两样东西一是主站每发多少帧请求2级数据后才会发一次请求1级数据二是从站置ACD1到主站下发请求1级数据之间的时间差。如果ACD位已经置1主站却在长时间轮询2级数据那必然导致事件延迟这个锅在主站调度逻辑去改从站时标没有意义。反过来如果ACD位一直是0、从站缓冲区里又确实有事件那就要查从站侧的事件生成逻辑可能是防抖时间太长把事件“消化”掉了。扰动数据的调度优先级更高。一旦从站开始传送扰动数据主站应该切换到专门的扰动数据读取流程这个状态下不要再频繁插入普通总召唤不然会打乱从站内部的故障数据处理节奏。5.4 超时、重传与链路测试参数的工程取舍链路层超时重传参数的设置是我在项目里调整最多的部分也是最容易“用力过猛”的地方。主站发一帧请求后不可能无限等从站回复需要设置超时时间。超时时间太短正常稍慢的从站也会被误判为无响应引发没必要的重传超时时间太长链路真正中断时主站要等很久才能切换备用通道。工程上我一般先按500毫秒到1秒起步跑一段时间看抓包里的超时重传记录再微调。重传次数同样要克制。现场最容易出现的问题是链路干扰导致偶尔丢帧主站却在短时间内连续重传6~8次结果每次重传又碰到干扰反而把总线占满形成“重传风暴”。比较稳妥的做法是链路层允许重传1~3次连续失败超过阈值就置链路异常转入手动或自动恢复流程而不是无限重试。链路测试帧的间隔也值得一调。主站会定时发链路测试帧确认从站还在线。间隔太短占总线资源间隔太长链路断了不能及时发现。我习惯按30秒到120秒之间配置具体取多少看业务对“断链告警及时性”的要求。另外从站侧在收到链路测试帧后应该立即回应有些装置把链路测试响应和事件处理混在一起导致测试帧响应延迟主站认为链路超时这种问题要从站侧单独去查。6. 两个实战排障案例报文不会骗人6.1 案例一综自后台偶尔漏SOE问题出在ACD位处理有次一个综自后台改造项目后台偶尔收不到开关变位的SOE但遥信刷新看起来正常。现场人员怀疑保护装置坏了隔离了好几次都没找出原因。我过去以后先在RS485链路上并上抓包工具蹲了一会儿抓到了完整的变位过程。从抓包看从站确实上送了一帧TYP0x06的SOE事件而且这帧响应帧控制域里的ACD位是1表示它还有1级数据要上送。问题出在后台侧后台收到SOE后没有按照ACD位指示再去请求后续1级数据而是继续按自己的轮询周期去请求2级数据。结果从站缓冲区里的部分事件一直没被取走直到下一轮总召唤时才被当成遥信状态覆盖掉SOE就“丢”了。这个案例的教训是SOE漏上报不要急着去查从站事件记录先看抓包里ACD位和主站请求1级数据的时序。链路层ACD位是整个事件上送链路的“第一道门槛”它负责通知主站“我有重要数据”。主站调度逻辑不响应ACD位应用层做得再花哨也没用。6.2 案例二强干扰环境下频繁“掉线”链路测试帧和校验暴露了真相另一个项目在开关场附近后台频繁报链路中断主站过一会儿又自动恢复。保护装置厂家坚称设备没问题后台厂家怀疑电磁干扰双方僵住了。我在现场抓到一大段报文后发现坏帧的概率确实高得吓人。统计下来的干净帧CS校验错误占了大部分还有少量帧长字段明显错乱。链路层大量坏帧直接导致主站连续重传失败进而触发链路中断逻辑。这类问题的根子在物理层。检查后确认是RS485屏蔽层接地方式不对导致电缆在开关操作时感应出很高的共模电压打坏了部分信号。处理方案并不复杂屏蔽层改单端可靠接地总线两端补上终端电阻把通信电缆和动力电缆拉开间距同时后台的重传策略从激进改为稳健连续3帧失败才判定链路异常。调整后再抓包坏帧数量明显下降链路中断告警再也没出现。这个案例值得记住的一点是任何上层解析异常最后都要回到报文本身去找证据。链路层校验错误率、坏帧分布、重传频率这些指标比单纯的“有没有收到数据”更能反映物理层健康状况。6.3 排障方法论从现象反推字节级的证据链做了这么多年103调试我总结了一套排障顺序遇到问题按这个顺序走基本不会乱第一层物理层。先确认波特率、校验位、数据位、停止位是否一致RS485的A/B有没有接反屏蔽层接地是否可靠终端电阻是否存在。这一层的典型证据是完全收不到任何报文或者抓到的数据全是乱码。第二层链路层。看帧头能否同步L字段是否正确CS校验是否通过控制域的PRM方向是否符合预期。这一层的典型证据是能抓到帧但大量坏帧或者主站发出去的帧从站没有任何回应。第三层应用层。看TYP、COT、FUN、INF和时标等字段是否和业务场景匹配。这一层的典型证据是链路层交互正常但后台点表不刷新、SOE时间错乱、扰动数据调不出来。每一层都需要抓包数据作为支撑。“好像”“大概”“感觉是”这类词在报文分析里没有意义。你手里的每一帧报文都是当时通信链路状态最忠实的记录只要拆解得够细原因一定能找出来。最后说一个我自己的习惯每次调试103我都会先录一段通信正常时的“基线报文”存档。链路正常时主站轮询的节奏、从站响应的控制域特征、总召唤响应的帧长范围都记录下来。等哪一天现场说出问题了翻出基线报文一对比是物理层异常、链路层异常还是应用层配置被改过一眼就能看出来。另外我通常会把常用的ASDU解码逻辑整理成Python脚本遇到新设备时先离线解析一遍抓包文件确认帧格式和字段含义后再上链路联调。这套“先离线、后在线”的流程帮我避开了很多现场踩雷的坑。
返回列表