IEC 104协议一次发送大量I帧数据

一、IEC协议结构

第一个字节:启动字符68H,十进制为104(正好代表104规约),二进制为:0110 1000。
第二个字节:APDU长度,注意APDU长度并不包括1字节的启动字符和1字节的APDU长度本身,而由于只有1字节代表数据长度,其最大值为255(2^8 - 1),所以最大值为255 - 2 = 253,又由于APCI除了这两个字节外还包括了4个字节的控制域(1~4),那么剩下的ASDU(可选的应用服务数据单元)长度为253 - 4 = 249字节。
正是由于ASDU的长度限制,所以一帧104 I格式报文能传送的数据信息是有限的。而不同数据类型占用的字节长度可能不一样,所以一帧报文能发送的最大IOA数量也不一样,下面就拿遥信和遥测分析。

二、遥信和遥测

根据104调度规约,基地址取值范围:

遥信:1H------4000H                ----->对应十进制  1-----16384

遥测:4001H------5000H          ----->对应十进制  16386----20480

        假设某次总召唤需要上传的数据将遥信和遥测的地址都占满了,也就是需要发送20480组数据响应总召唤!这么多的数据即使是TCP层也不可能一包全部发完,必须要分包发送。

遥信

01———不带时标的单点遥信,每个遥信占1个字节

03———不带时标的双点遥信,每个遥信占1个字节

14———具有状态变位检出的成组单点遥信,每个字节8个遥信

遥测

09———带品质描述的测量值,每个遥测值占3个字节

0a———带3个字节时标的且具有品质描述的测量值,每个遥测值占6个字节

0b———不带时标的标度化值,每个遥测值占3个字节

0c———带3个时标的标度化值,每个遥测值占6个字节

0d———带品质描述的浮点值,每个遥测值占5个字节

0e———带3个字节时标且具有品质描述的浮点值,每个遥测值占8个字节

15———不带品质描述的遥测值,每个遥测值占2个字节

        根据104调度规约,遥信数据最短为一个字节(当类型为01),如果ASDU里遥信数据全部占满的话能发249组遥信数据,然而并不是,首先ASDU字段里还有Type,VSQ,COT等要占用字节数,更重要的是VSQ代表信息体的数量,也就相当于VSQ限制了信息体的个数,而且VSQ只占一个字节,最大值为127(最高位为是否连续标志),因此发送一包包含遥信的帧最多只能发送127组数据,16384/127=129.007,超过了129也就是需要130包数据帧才能发送完成。

遥测数据最短为2个字节(当类型为15),如果取VSQ最大值的话,2*127=254>249,所以比遥信组数要少,(249-1-2-2-3-1)/2=120,所以发送一包包含遥测的帧最多只能发送120组数据,4096/120=34.13,也就是需要35包数据帧才能发送完所有遥测数据。

因此所有遥信包+遥测包=130+35=165包I帧报文。

三、IEC 104参数设置

k和w参数

        104规约规定了两个参数K和W,其取值为1到32767,其中K表示发送方在有K个I格式报文未得到对方的确认时,将停止数据发送;W表示接收方最迟在接收W个I格式报文后应发出认可。104规约规定K和W的默认值分别为12个APDU和8个APDU,推荐关系式为w<k*2/3。
  在实际中,K和W的具体取值可以根据TCP连接双方的数据通信量加以确定。对于从站RTU来说,每收到一个调度端的I格式报文都应立即响应,其W的取值实际上为1,由于RTU端可以循环向主站发送遥信、遥测等信息,因此K的取值与其循环发送的定时周期有关,通常12到20个APDU就足够了;对于主站端,由于不停接收RTU数据,因此应及时地给以确认,通常W取小于8个APDU的值。

t0、t1、t2、t3参数
  当未确认I格式APDU达到K个时,发送方停止发送。如果t1超时仍未收到确认,则重启链路。
为了能对TCP连接进行检查和维护,104规定了几个超时时间:t0、t1、t2、t3。它们的取值范围为1~255s,准确度为1s。
  t0规定了主站和从站建立一次TCP连接的最大允许时间,即主站端一直发出连接请求,在t0时间内得不到连接建立成功的状态下,要向应用层提示,说明无法建立连接,一般可设置进行多次连接,当每次连接都超过t0无法建立成功时都应给出提示。默认值30s。
  t1规定发送一个I格式报文或U格式报文后,必须在t1的时间内得到接收方的认可,否则发送方认为TCP连接出现问题并应重新建立连接。这个过程是双向的,即对于厂站端和主站端当这个过程任一方发生时,两方的连接都需关闭,重新建立连接。默认值15s。
  t2规定接收方在接收到I格式报文后,若经过t2时间未再发送新的I格式报文,则必须向发送方发送S格式帧对已经收到的I格式报文进行认可,显然t2必须小于t1。默认值10s。
  t3规定主站或从站每接收一个I,S,U报文将重新触发计时器t3,若再t3内未能接收到任何报文,将向对方发送测试链路报文(U帧)。发送测试帧后,若在t1时间内没有收到测试确认,则连接关闭,若达到t3时间,则再次发送测试链路报文(U帧)。默认值20s。

        当网速较好的情况下发送多包数据时,t0、t1、t2、t3的默认值都能满足,而k和w参数的默认值当要满足发送165包情况是远远不够的,根据w<k*2/3的关系,可修改为k=180,w=120。当然这里只考虑发送地址连续而且数据是最短的理想情况,在实际中如果地址不连续或数据类型占用数据多几个字节,k和w数值可适当的调大些。

# IEC104 Protocol of IEC104 and IEC101 ## by chendajie 2014-2015 ## 电网IEC104/IEC101通信协议 ============================== 隔离协议内容与平台或者硬件相关性,已经在stm32平台和linux平台移植测试通过,可轻松移植到其他平台。 ============================================================================ 队列实现的隔离,目前实现简单的先入先出队列,可根据需求用其他队列算法替换。 移植调用实现: 1.在不同平台下,实现_iec10x结构体的函数指针(利用函数指针实现的接口)。 2.调用RegisterIEC10XMoudle,注册实现的_iec10x接口。 3.创建线程一调用Iex104_Receive管理收包解析。 4.创建线程二调用Iec10x_Scheduled实现出队调度。 5.创建线程三实现状态机Iec104_StateMachine,实现协议状态管理,协议包组包入队。 代码内容 IEC0x目录 iec101.c iec101协议包内容 iec104.c iec104协议包内容 iec10x.c 队列初始化,入队出对实现,队列优先级等相关实现,队列调度实现 PRIO_QUEUE_Iec10x.c 队列具体算法实现 test目录 linux上简单测试代码,仅供参考,作者具体协议应用在stm32上,利用状态机控制数据包入队与出队调度 重要函数: Iec10x_Scheduled:出队调度 IEC10X_Enqueue:入队函数 IEC10X_Dequeue:出队函数 IEC10X_FindQHead:查找最高优先级数据IEC10X_XXX:前缀为IEC10X_的函数为各个协议包的组包函数 Iec104_StateMachine: 104协议状态机 Iex104_Receive:收包解析 RegisterIEC10XMoudle:协议模块注册,初始化 重要结构体: 用函数指针实现的移植接口,根据不同平台与硬件特性,选择性实现以下接口 typedef struct _iec10x { char * name; int (* Init)(void); void (* Delay_ms)(uint16_t); void (* CloseLink)(void); void *(* Malloc)(uint8_t NumByte); void (* Free)(void *buffer); uint8_t (* enqueue)(Iec10x_PrioQueue_T *QueueHdr, Iec10x_PrioNode_T *NewNode); Iec10x_PrioNode_T *(* dequeue)(Iec10x_PrioQueue_T * QueueHdr); Iec10x_PrioNode_T *(* FindQHead)(Iec10x_PrioQueue_T * QueueHdr); char (* GetPrio)(void); void (* InitQueue)(Iec10x_PrioQueue_T *PrioQueue); void (* ClearQueue)(Iec10x_PrioQueue_T * QueueHdr); uint8_t (* Send)(int socketfd,char *data,int len); uint32_t (* SetTime)(PCP56Time2a_T time); uint32_t (* GetTime)(PCP56Time2a_T time); int8_t (* GetStationState)(uint16_t Addr, uint8_t DevType); float (* GetStaValue)(uint16_t Addr, uint8_t DevType); uint16_t (* GetLinkAddr)(void); int8_t (* GetInfoNum)(uint8_t *InfoNum, uint8_t DevType); int8_t (* SetConfig)(long Value, uint32_t addr); int8_t (* SaveFirmware)(uint8_t FirmLen, uint8_t *buf,uint32_t FirmwareType, uint32_t Iec10x_Update_SeekAddr); int8_t (* CheckFirmware)(uint32_t FirmwareType, uint32_t TotalLen); int8_t (* UpdateFirmware)(uint32_t FirmwareType); int8_t (* BackoffFirmware)(uint32_t FirmwareType); #ifdef IEC10XLOCK void (* LOCK)(void); void (* UNLOCK)(void); #endif } *PIEC10X_T, IEC10X_T;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值