4. ASDU结构解析:类型标识、可变结构限定词、传送原因、公共地址、信息对象地址、时标

好,咱们今天来啃一块硬骨头——ASDU结构。说实话,我刚接触IEC104的时候,看着这一串串的字节,头都是大的。但后来我发现,只要把ASDU拆成几个关键字段来理解,这事儿就简单多了。

ASDU,全称是Application Service Data Unit,应用服务数据单元。你可以把它想象成一个快递包裹。包裹外面贴着快递单,里面装着你要寄的东西。ASDU也一样,它由数据单元标识信息体两部分组成。

数据单元标识就是快递单,它告诉接收方:这是什么类型的包裹?里面装了几件东西?为什么要寄?寄给谁?而信息体就是包裹里的实物,也就是具体的遥测值、遥信状态、遥控命令等。

核心记忆点:ASDU = 数据单元标识(头部) + 信息体(数据本体)

下面我带你逐个拆解数据单元标识里的六个关键字段。嗯,这六个字段,你搞懂了,ASDU就通了八成。

4.1 类型标识(Type Identifier)

类型标识,占1个字节。它告诉接收方:这个ASDU里装的是什么类型的数据。

我个人习惯把类型标识分成几大类来记:

  • 遥测类(M_ME_xxx): 比如归一化值M_ME_NA_1(09H)、标度化值M_ME_NB_1(0BH)、浮点数M_ME_TF_1(0DH)。我在储能站项目里,电池簇的电压、电流、温度,大部分都用浮点数类型,精度高,省心。
  • 遥信类(M_SP_xxx): 比如单点遥信M_SP_NA_1(01H)、双点遥信M_DP_NA_1(03H)。开关的分合闸状态,用双点遥信更安全。
  • 遥控类(C_SC_xxx): 比如单点遥控C_SC_NA_1(2DH)、双点遥控C_DP_NA_1(2EH)。下发指令时,类型标识必须和站端配置一致,否则会报错。
  • 参数类(P_ME_xxx): 比如设置参数P_ME_NA_1(64H)。

我曾经在调试一个储能PCS时,主站下发遥控命令,类型标识写的是单点遥控,但站端配置的是双点遥控。结果呢?PCS死活不动作。排查了半天,最后发现是类型标识对不上。你说冤不冤?

小技巧: 类型标识的十六进制值,建议你背下常用的几个。调试时用抓包软件一看,就知道报文是干啥的,效率翻倍。

4.2 可变结构限定词(Variable Structure Qualifier, VSQ)

VSQ,占1个字节。它描述的是信息体的结构。说白了,就是告诉你:这个ASDU里,信息体是单个的还是连续的?一共有几个?

VSQ的格式是这样的:

  • Bit 7(最高位): SQ位。SQ=0表示信息体地址不连续(离散),每个信息体都带独立的地址;SQ=1表示信息体地址连续,只需要第一个信息体的地址,后面的自动递增。
  • Bit 6~0(低7位): 信息体的数目N。取值范围1~127。注意,0是无效的,至少得有1个。

你想想看,如果我要上传100个电池单体电压,用SQ=1的方式,只需要发一个起始地址,后面99个地址自动加1。报文长度能省不少。但如果这些电压点地址不连续,那就只能用SQ=0,每个点都带独立地址。

实战经验: 在储能站里,电池管理系统(BMS)上报电池簇数据时,我建议优先使用连续地址(SQ=1)。因为电池单体地址通常是顺序排列的,用连续方式能显著减少报文长度,降低网络负载。

4.3 传送原因(Cause of Transmission, COT)

传送原因,占2个字节(IEC104中扩展为2字节)。它解释了这个ASDU为什么会被发送。

常见的传送原因有:

原因值 含义 说明
1 周期(Cyclic) 定时上送的遥测数据
2 背景扫描(Background) 低优先级扫描数据
3 突发(Spontaneous) 遥信变位、越限告警等
5 请求(Request) 响应主站的召唤命令
6 激活(Activation) 遥控、设点命令的激活
7 激活确认(Activation Confirmation) 站端确认收到激活命令
8 停止激活(Deactivation) 取消遥控或设点命令
9 停止激活确认(Deactivation Confirmation) 站端确认取消成功
10 激活终止(Activation Termination) 遥控或设点执行结束
20 站召唤(Station Interrogation) 全站数据总召
21 组召唤(Group Interrogation) 特定组的数据召唤

举个例子,储能站里电池温度越限了,站端会主动上送一个传送原因为3(突发)的ASDU。主站收到后,就知道这是告警事件,需要立即处理。

注意: 传送原因的第8位(Bit 7)是P/N位,0表示肯定确认,1表示否定确认。比如遥控命令被拒绝时,传送原因会是0x87(原因7 + 否定位)。这个细节很容易被忽略,但调试时特别有用。

4.4 公共地址(Common Address)

公共地址,占2个字节。它标识了这个ASDU属于哪个站或哪个装置。

在IEC104中,公共地址通常用来区分不同的变电站、不同的储能单元或不同的保护装置。比如一个储能站有4台PCS,每台PCS的公共地址可以设为1、2、3、4。主站通过公共地址就知道数据来自哪台设备。

公共地址的范围是1~65535。0通常保留不用。我个人习惯把公共地址和设备编号对应起来,这样看报文就能直接定位设备,省去查表的麻烦。

建议: 公共地址的分配一定要提前规划好,形成文档。我在一个项目里见过,两个设备配了相同的公共地址,结果主站收到的数据乱套了。排查起来那叫一个痛苦。

4.5 信息对象地址(Information Object Address, IOA)

信息对象地址,占3个字节。它标识了具体的数据点。比如第1个电池单体电压、第2个电池单体电压、第1个开关状态等。

IOA的分配通常由工程实施方根据点表来规划。常见的做法是:

  • 遥测地址范围: 比如4001H~4FFFH
  • 遥信地址范围: 比如5001H~5FFFH
  • 遥控地址范围: 比如6001H~6FFFH
  • 设点地址范围: 比如7001H~7FFFH

当然,这只是举例,实际项目中可以根据需要灵活划分。关键是地址不能重复,一个IOA只能对应一个数据点。

我记得有一次,现场调试时发现某个遥测值一直显示为0。抓包一看,IOA写的是4001H,但点表里4001H对应的是另一个信号。原来是配置表搞错了。所以说,IOA的分配和核对,是调试前必须做好的功课。

4.6 时标(Time Stamp)

时标,就是数据产生的时间。IEC104支持多种时标格式:

  • CP56Time2a(7字节): 最常用,包含毫秒、分钟、小时、日、月、年,还有星期几。精度到毫秒。
  • CP24Time2a(3字节): 只有毫秒和分钟,精度较低。
  • CP32Time2a(4字节): 只有毫秒,用于相对时间。

在储能站里,我强烈建议使用CP56Time2a。为什么?因为储能系统的数据需要精确的时间戳来分析故障顺序。比如电池过温告警和PCS跳闸,如果时间戳不准,你就没法判断是先有过温还是先跳闸,故障根因分析就无从谈起。

CP56Time2a的结构是这样的:

字节偏移 内容 范围
0~1 毫秒(低字节在前) 0~59999
2 分钟 0~59
3 小时(Bit 6~0) + 星期几(Bit 7~5) 小时0~23,星期1~7
4 1~31
5 1~12
6 年(相对于2000年) 0~99(表示2000~2099)

注意: 时标的字节顺序是小端模式(低字节在前)。比如毫秒值1000(0x03E8),在报文里是E8 03。很多新手在这里栽过跟头,解析时一定要留意。

知识体系结构图

下面我用一张SVG图来总结ASDU的结构,方便你整体把握:

ASDU结构解析 ASDU(应用服务数据单元) 数据单元标识(头部) 类型标识 1字节 可变结构 1字节 传送原因 2字节 公共地址 2字节 信息对象 3字节 时标 可选 信息体(数据本体) 信息对象地址 3字节(若SQ=0则每个信息体都带) 信息元素值 遥测/遥信/遥控等数据 时标(可选) CP56Time2a等 注:时标可以出现在数据单元标识中,也可以出现在每个信息体中,具体由类型标识决定

这张图把ASDU的骨架画出来了。你对照着看,是不是清晰多了?数据单元标识里的六个字段,加上信息体里的数据,就组成了一个完整的ASDU。

好了,ASDU的结构就讲到这里。这六个字段,你记住了吗?类型标识告诉你是啥数据,可变结构限定词告诉你数据怎么排列,传送原因告诉你为啥发,公共地址告诉你是谁发的,信息对象地址告诉你具体哪个点,时标告诉你啥时候发生的。六者合一,就是一个完整的数据描述。

下次你抓包看到一串十六进制数,试着按这个结构去拆解,很快就能上手。我在现场调试时,就是这么一步步练出来的。


公众号:蓝海资料掘金营,微信deep3321