一种电能表通讯缓存处理方式

2018-08-30 09:15顾小峰肖五生
中国科技纵横 2018年14期

顾小峰 肖五生

摘 要:从2016年开始,电能表引入了面向对象通信协议《DL/T 698.45面向对象的用电信息数据交换协议》,而此协议与原有电能表通信协议《DL/T 645—2007多功能电能表通信协议》相比,对电能表的资源需求有了一个明显提高。主要体现是通讯缓存和记录数据的需求量大幅提升。

关键词:面向对象通讯协议;动态RAM;链路层分帧

中图分类号:TM933 文献标识码:A 文章编号:1671-2064(2018)14-0098-02

1 背景描述

从2016年开始,电能表引入了面向对象通信协议《DL/T 698.45面向对象的用电信息数据交换协议》,而此协议与原有电能表通信协议《DL/T 645—2007多功能电能表通信协议》相比,对电能表的资源需求有了一个明显提高。主要体现是通讯缓存和记录数据的需求量大幅提升。

而我们这里主要讲的是通讯缓存。通讯缓存从原先每通道212字节(数据域最大200+帧头、帧尾等帧格式数据),上升到每通道512字节;而DL/T 698.45协议还支持链路层分帧,最到可处理APDU为2000字节,而这些帧数据都用RAM的话,那么每通道RAM需求量就至少需要2000+帧头帧尾字节数据,又由于DL/T 698.45帧格式相对灵活,我们一般会预留到2K字节。这样的话,一个通道的通讯缓存RAM需求,DL/T 698.45就比DL/T 645协议增加1836字节。对三相电能表来说,可能会有4个通讯通道,要保证各通道能同时通讯,RAM需求量就需要增加1836*4=7344字节;单相表会少1个通道,需增加1836*3=5508字节。

RAM的大幅度增加,势必需要更换RAM更大的MCU,而对于成本要求很高的电能表来说,这势必又是雪上加霜。

当然我们也可以考虑将缓存数据放到其它存储器,比如EEPROM、FLASH等,但这里毕竟是通讯,要保证传输速度,而EEPROM、FLASH的存储和读取速度是相对较慢的,另外它们的使用寿命相对较小,要保证使用寿命,必须预留更多倍的存储空间,这样是非常不划算的。

2 方案设计

不管是单相电能表,还是三相电能表,虽然都设计有多个通信通道,但现场应用时,一般只有一个通信通道在使用;如模块表,基本是采用模块进行数据传输,485表只采用485口。当然也不排除现场表型混用,如模块表用于485口通讯的场合;由于通信模块即使没有采集终端对其通讯,它也会经常从电能表获取数据,这时对电能表来说,就有可能涉及到2个通讯通道同时通讯。

由此,我们可以看出,对于电能表经常通讯的通道其实顶多就2个。另外,其实我们也知道平常通讯时每次操作(读取、设置等)时,APDU数据并不会达到最大可处理APDU的数据量。这样我们完全可考虑,分配一块并不是很大的RAM缓存用动态分配的形式,供各个通道使用,先到先得,用完立即释放。下面我们就对这种通讯缓存的分配方式进行详细说明。

2.1 动态RAM的分配

由于电能表一般都采用普通单片机,基本不使用操作系统设计,因此我们这里需要单独分配一块RAM区作为动态RAM。这块区域可以根据系统RAM资源进行适当调整,这个区域不能小于一个通道所需要的缓存(2Kbyte)。为了便于内存的分配和回收,可以建立两张信息表:内存分配表、空闲分区表。

2.1.1 内存分配表

(1)此表可存储M条信息;

(2)每条信息内容包括:标识、分区起始地址、长度;

标识:某作业内存名称(1字节);用非0数据表示,0-空栏目;

分区起始地址:该作业区内存起始地址(2字节);当标识为0时,无效;

长度:该作业区内存分配长度(2字节);当标识为0时,无效;

2.1.2 空闲分区表

(1)此表可存储N条信息;

(2)每条信息内容包括:分区起始地址、长度、标识;

标识:某空闲内存标志(1字节);0-空栏目,1-未分配;

分区起始地址:该空闲区内存起始地址(2字节);当标识为0时,无效;

长度:该空闲区内存分配长度(2字节);当标识为0时,无效;

2.1.3 分配内存

分配内存步骤如下:

(1)从“空闲分区表”中找到标识为“1”(未分配)且满足作业需求内存大小的最小空闲区。

(2)判别该空闲区大小与作业所需内存的差值是否小于最小值MinSize;如果小于,那么将该空闲区标识改为“0”,同时在“内存分配区”中找到标识为“0”的空栏目,并将新的作业名称、起始地址、长度登记进去;如果差值大于等于MinSize,将该部分区域分成两部分,一部分做为作业区内存,另一部分仍旧做空闲区,这时只要更改该空闲区长度,并把新装入的作业内存登记到“内存分配区”。

2.1.4 回收内存

回收内存步骤如下:

(1)先将“内存分配表”对應的标识改为“0”(空栏目);

(2)检查“空闲分区表”中标识为“1”(未分配)的栏目,查找是否有相邻的空闲区;如果有,合并处理,修改该空闲区起始地址和长度;如果没有,在“空闲分区表”中找到标识为“0”的栏目,将该栏目标识改为“1”,同时将回收的内存起始地址和长度记录到相应位置。

内存分配表和空闲分区表的信息条数,可以根据系统实际使用情况分配。

2.2 链路层分帧数据的管理

上面提到用动态RAM来维持正常情况下的通讯缓存开销,但也会有偶尔出现这样的情况,动态RAM已被占用完,这时又有其它通道有通讯产生(如现场红外抄读数据);为了保证这种情况下通讯正常,这时我们就需要启动备用缓存方案,而备用缓存可以采用非易失性存储器(如EEPROM、FLASH等)。由于备用缓存应用频率较低,只要预留少部分资源就可以满足寿命需求。

考虑到链路层分帧时完整的APDU数据是通过一帧帧的数据组成的,而每一帧的数据小于512字节;另外,链路层分帧每帧包含的APDU片段都是不可自解析的,因此在所有帧接收完成前,是不知道的APDU数据总长度的。为了不浪费资源,我们需要根据接收帧逐块申请缓存。

由于是逐块申请缓存,那么一个完整的APDU缓存就可能是几个地址不连续的块组成,这样我们就需要有一个管理信息来表达每个通道的APDU缓存。

本方案每个通道数据管理信息包括:数据信息缓存、数据总长度。

数据信息缓存:4字节数组(接收时最小申请内存大小为512byte),用来存放内存块标识名;此数组长度可以根据实际情况调整。每个字节最高位表示存储类型,0表示动态RAM,1表示非易失性存储器;低7位为标识名,最高位为1時(空间分配在非易失性存储器),标识名不做识别,分配空间统一按2K大小处理;信息字节为0xFF,表示未使用;要求信息从第一个字节开始放置,没用到的信息字节填0xFF,建议使用前将信息初始化为0xFF。动态RAM类型的标识名,每个标识代表一个数据块,前面数据块内数据都是有效数据,最后一个有效标识的有效数据数是与数据总长度有关的,即:L末=L总-L前;

L末:最后有效标识代表的数据块的有效数据长度;

L总:数据总长度;

L前:前面所有数据块长度之和。

数据总长度:保存数据的总长度。

2.3 链路层分帧数据存储实现

698通讯上用到的链路层分帧有两种情况:接收链路层分帧和发送链路层分帧。接收时数据存储内存需要一块一块申请,发送时可以根据需要发送数据的长度一次性申请。下面就具体说明一下这两种情况的处理方法(以下都是按通道单独处理):

(1)接收:当需要保存接收分帧的APDU片段时,先识别是否有已分配空间,如果有且够用就直接保存数据并更改存储信息;如果没有已分配空间或不够用,就申请空间,再保存数据且更改存信息。

(2)发送:需要分帧发送时,存储相对就简单了,只要根据需要发送数据的长度,申请存储空间,进行数据保存且更改存储信息就可以了。

不管是接收保存还是发送保存,其中都会涉及到申请存储空间的操作。由于存储RAM空间有限,申请存储空间时不一定能申请到动态RAM,这时申请到的存储空间就会是非易失性存储器的存储空间。

需要注意的是,接收申请存储空间过程中,在申请动态RAM时,由于不知道后面具体有多少数据,且接收一帧最大长度为512byte,为了减少浪费RAM的使用,每次申请都只申请512byte的内存。

另外,在每次保存数据后,都需要更改管理信息,申请空间需要增加一个数据信息队列数据并更改存储数据总长度,不申请空间只需要更改存储数据总长度。

分帧数据存储功能对外接口参数:通道号、保存数据指针、数据长度、数据偏移。

2.4 链路层分帧数据读取

上面讲的是存储链路层分帧的APDU数据,这里就需要说一下如何读取这些存储的数据。

由于根据上面数据的存储方式,这些存储数据并不是连续的,而是分块的,甚至是不同设备中存储的,因此读取就不可能像我们平时读取其它数据一样,简单地根据起始地址和数

据长度得到。我们需要根据存储信息队列,找到待读数据的存储位置,然后再从找到的位置开始逐块读取,直到读到需要的数据量为止。

分帧数据读取对外接口参数:通道号、输出数据指针、数据长度、数据偏移。

3 结语

本方案宗旨是在通讯时尽量采用动态RAM资源,使用完成后,需及时释放资源。在RAM资源紧缺时临时采用非易失性存储器,保证在这种情况下的通讯成功率。另外需注意,如果在使用非易失性存储器存储或者读取失败时,也需要做好合理的应答,不能产生不可预知的错误。

参考文献

[1]郑天,曹凯,杨东华,贺云隆.智能电能表的发展与应用探讨[J].科技展望,2015,(27)105.