第一部分:链路层HDLC部分的详述
先问自己一个问题,拿到一个牵扯内容繁复、逻辑结构复杂的项目应该从哪里起跑? 之前,包括这个项目的实现我都选择了由具体至结构,结构丰满后再抽象的去审视整个架构。
这个协议栈的实现收尾时,我回顾了整个项目的设计和实现过程,才敢肯定起初的选用实践方法是对的。不是因为最终我用这种方式实现了这个项目这样说,而是我经历过了整个繁复的设计与实现过程之后,我才更清晰认知62056这套协议族背后的真正意义和绝妙之处。
像大多数刚接触到这套协议族的实现者一样起初完全摸不着头脑。九个标准协议文档(21.41.42.46.51.52.53.61.62)与都标注着65056关键字的各种学术与研讨文档,还不算DLMS协会发布的标准四色书(White、Green、Blue、Yellow book)。
全本的英文标准和整套的协议文档更是让初入者一头雾水。加之,国内中文的各种以62056关键字标注的相关论文和研讨文章更是厚此薄彼、避重就轻的讲述一些协议标准中阐述的繁复内容。对于初入者完全就是一场噩梦和磨难。在那些文档中(请原谅我已经不能全部罗列出众多参考过的学术文档),唯一能现在还让我想起和感谢的就是一些真实截取的数据帧信息和旁边给予的简单备注。
可能是个人的全局分析能力薄弱,所以最终我选择了从最具象的真实数据帧入手。恰恰是选用的这种实现方法,决定了我整个协议栈的实现过程流向和这篇文章的结构层次安排。
链路层这部分余下的内容我会用较多的实用信息,以及较少的关键解释和备注来完成。
HDLC帧基本格式:
0x7e 帧类型与帧长 目的地址 源地址 控制域 帧校验 0x7e
0x7e 帧类型与帧长 目的地址 源地址 控制域 帧首校验 LLC 数据信息 帧校验 0x7e
帧首校验:帧类型与帧长+目的地址+源地址+控制域(CRC16)
1. 帧类型与帧长:2个字节
(MSB) 1010 S LLLLLLLLLLL (LSB)
帧类型 帧长
DLMS使用Frame Type为3, 恒为0x0A(1010 B)。
S bit 用于说明数据帧是否被分割。(置0为不分割)
帧长 字节为单位,不包括首尾两个0x7e特殊字。
2. 地址域:某一地址字节的最低位为0,则表示该地址域没有结束;如最低位为1,表示地址域结束。
Client端的地址永远是一个字节,且最低位为1。所以该地址只能有128个。
Server端 Upper address总是有的,表示逻辑地址。
Lower address在确定不需要的时候可以不出现,用于表示物理地址。
S端的地址结构:
一字节,只出现HDLC高位一字节地址。(Upper address 1)LSB
两字节,HDLC高位一字节地址,HDLC低位一字节地址。(Upper 0 Lower 1)
四字节,只出现HDLC高位两字节地址,和HDLC低位两字节地址。
(Upper.high 0 Upper.low 0 Lower.high 0 Lower.low 1)LSB
3. 控制域:
负责通讯中的帧链路计数,以及特殊数据帧的标识。
I RRR P/F SSS 0
RR RRR P/F 000 1
SNRM 100 P 001 1
DISC 010 P 001 1
UA 011 F 001 1
DM 000 F 111 1
FRMR 100 F 011 1
RNR RRR P/F 010 1
UI 000 P/F 001 1
各种帧格式的详细定义请参照相关协议标准文档中的定义,此处不赘述。
RRR 接收帧计数器
SSS 发送帧计数器
P/F Poll bit 由client发送,置1时表示server端回应,置0时表示不允许回应。
Final bit 由server发送,置1时表示一次数据帧的发送结束,置0表示还未发送完。
Final bit只有在通讯窗口window size大于1时才有意义。
在window size =1时,由server端返回的数据帧的这一位始终置1。
帧类型对应如下:
Commands Responses
I I
RR RR
RNR RNR
SNRM UA
DISC DM
UI UI
Excption FRMR
4. 帧校验:
标准协议文档中给予的16位CRC校验公式为(-46 附录A)
X**0 + X**5 + X**12 + X**16
关于CRC16校验部分的具体实现会在本文的第三部分工具模块中给出。
关于长数据帧的传输:
在数据帧被分割传输时,帧类型与帧长字段中的S位,将被置1。
Client 通过发送RR数据帧来请求被分割的数据帧的其余部分。
UA数据帧所包含的链路参数:
Window_size 通讯的双方一次发送数据帧的数目。(默认值为1)
Maximun_infomation_field_length 链路数据帧中用户数据的最大长度。(默认值为128)
Transmit_maximum_infomation_field_length
Receive_ maximum_infomation_field_length
Transmit_window_size
Receive_ window_size
各种协商内容与参数的详细定义请参照相关协议标准文档中的定义,此处不赘述。
关于通讯参数协商部分的具体实现会在本文的第三部分AARE/AARQ中给出。
最后,摘抄下自己记事本中当初实现链路层时备注的一些心得体会和总结。
The following LLC parameters are defined:
Destination_LSAP: 0xE6;
Source_LSAP: 0xE6 for command frames and 0xE7 for response frames;
LLC_Quality: it is reserbed for future use and its value must always be 0x00.
Client端发送DISC帧,Server端响应UA帧或DM帧。
UA 表示接收到DISC帧后断开链接。
DM 表示在接收到DISC帧之前就已经处于链路断开状态。
HDLC是透明数据传输的链路协议,用户数据信息与链路层没有任何直接关系。