“DL/T645-1997通訊規約”解析


      該通信規約適用於本地系統中多功能表的費率裝置與手持單元(HHU)或其它數據終端設備進行點對點的或一主多從的數據交換方式,規定了它們之間的物理連接、通信鏈路及應用技術規范。該協議在做“電力監控”、“水監控”等“工控領域”,具有廣泛的應用。協議具體內容可以從網上Google,下面主要介紹下協議的解析方法。

      

     DL645協議需要先發送“前導字節”,用來喚醒從站,當然有些設備是不需要這樣喚醒的。在發送幀信息之前,先發送1-4個字節FEH,以喚醒接收方("FEH",H表示16進制,是一個字節),  “前導字節”  +  “取數據報文”=“整體報文”。

首先我們先整體了解一個發送報文“68 12 34 56 78 90 12 68 01 02 43 C3 cs 16” 

在這之前呢,先看一下BCD碼。

BCD碼:二進制編碼的十進制代碼。

比如:

0=0000
1=0001
2=0010
3=0011
4=0100
5=0101
6=0110
7=0111
8=1000
9=1001
 
BCD碼:ASCII表示(都是字符)
BCD碼都是由0~9,10個字符構成。
也就是說,BCD碼一個字節是兩位,一位是0~9,一個字節能夠表示00~99。
 
BCD碼1位是2進制的4位。按16進制表示,沒有ABCDEF。
 

幀格式(DL/T645-1997通訊規約標准文檔中

幀是傳送信息的基本單元。幀格式如圖所示。

說  明

代碼

幀起始符

68H

 

 

地址域

A0

A1

A2

A3

A4

A5

幀起始符

68H

控制碼

C

數據長度域

L

 

數據域

 

DATA

校驗碼

CS

結束符

16H

4.2.1 幀起始符68H:標識一幀信息的開始,其值為68H=01101000B。

4.2.2地址域A0∽A5:地址域由6個字節構成,每字節2位BCD碼。地址長度為12位十進制數,可以為表號、資產號、用戶號、設備號等。具體使用可由用戶自行決定。當使用的地址碼長度不足6字節時,用十六進制AAH補足6字節。低地址位在先,高地址位在后。當地址為999999999999H時,為廣播地址。

4.2.3 控制碼C:控制碼的格式如下所示。

D7

D6

D5

D4

D3

D2

D1

D0

 

                                                                  

                                                  功能碼

                                   后續幀標志

                         從站異常標志

                 傳送方向

       D7=0:由主站發出的命令幀

       D7=1:由從站發出的應答幀

       D6=0:從站正確應答

       D6=1:從站對異常信息的應答

       D5=0:無后續數據幀

       D5=1:有后續數據幀

       D4∽D0:請求及應答功能碼

               00000:保留

               00001:讀數據

               00010:讀后續數據

               00011:重讀數據

               00100:寫數據

               01000:廣播校時

               01010:寫設備地址

               01100:更改通信速率

               01111:修改密碼

               10000:最大需量清零

4.2.4 數據長度L:L為數據域的字節數。讀數據時L≤200,寫數據時L≤50,L=0 表示無數據域。

4.2.5 數據域DATA:數據域包括數據標識和數據、密碼等,其結構隨控制碼的功能而改變。傳輸時發送方按字節進行加33H處理,接收方按字節進行減33H處理。

4.2.6 校驗碼CS:從幀起始符開始到校驗碼之前的所有各字節的模256的和, 即各字節二進制算術和,不計超過256的溢出值。

4.2.7結束符號16H:標識一幀信息的結束,其值為16H=00010110B。
 
 
 發送報文

68 12 34 56 78 90 12 68 01 02 43 C3 cs 16

說明如下:

68(幀起始符)

12   34  56  78  90   12 (6字節,沒字節兩位,共12位地址,BCD碼表示。)  

 

68(幀起始符)

01(控制碼“包含功能碼”= 01 = 讀取數據)

02 (數據域長度,指 “43,C3”一共是兩字節。) 

“43 c3” (“43 C3”是數據域,表示讀取數據類型 = “10 90”, 發送報文中 數據域需要做“+0x33處理”)

cs(加校驗和,一個字節,根據前面的計算)

16(幀結束符)

 

下面詳細的解釋下:

幀起始符(645協議規定由68H開始,16進制。)

 

0x12(BCD數值碼) --- 12(string)      轉為字符串0x12.ToString("X2")
0x45(BCD數值碼) --- 45(string)

 

如果表地址為:000021010203(電表上看到的地址串),里面就是12位(字符串來看)
通訊時,使用 0x00, 0x00 , 0x21 ,0x01 , 0x02 , 0x03, 6個字節表示地址,但發送的時候要先發低字節,再發高字節。發送時也是“0x03,0x02,0x01, 0x21,0x00,0x00”

 

控制碼:
從電腦到表具:0(主從站方向)+0(設備沒問題)+0(有無后續幀)+00001(讀)=1=0x1

數據域長度:表示數據域有多長

串口傳輸方式:所有數據項均先傳送低位字節,后傳送高位字節

數據域內容,也就是“數據類型+數據項”(比如電表): 1001(電能量)+00(當前)+00(有功)+0001(正向電能)+0000(總點能)


02(數據域長度)

10

90(數據域內容,兩個字節) 拼接后的報文,要先發低字節(90) ,再發10. 發送報文要加上"33",最后數據域就是"10 + 33"和"90 + 33"最終就是“ 43     c3”。

02 10 90 == 02   (10 + 33)     (90 + 33) = 02   43    c3

 

返回報文:

68   12   34 56 78 90 12 68 81 06 43 c3 33 44 55 66 cs 16

68(幀起始符)
12 34 56 78 90 12(地址域)
68(幀起始符)
81(控制碼,返回有功總電能“10000001”,讀取數據)
06(數據域長度)
43 C3(數據域)
33  44  55  66 (數據項,四字節)

數據項要減去“33H”,根據數據類型(附錄)點小數點。

33   44   55   66 (數據域數據計算) = (33 - 33) (44 - 33) (55 - 33) (66 - 33) = 00112233 = 1122.33   kWh

 

最后我們來看一個電表實例,取地址為“694561”的電表的“反相有功電能(發電量)”。

實例如下:

一、發送報文

1、電表地址:694561(地址,6位BCD碼,BCD碼1位是2進制的4位。按16進制表示,沒有ABCDEF。不足12位,需要在高位“補0”。)。

2、完善地址:000000694561(12位BCD碼)

3、前導符字節:0xFE

4、幀起始符:0x68

5、地址域:0x614569000000(第字節在前,高字節在后。DL645協議,先發低字節再發高字節。)

6、幀起始符:0x68

7、控制碼:0x01(讀數據1,讀后續數據2,其中還包含功能碼等。)

8、數據域長度:0x02(2字節)

9、待發送數據類型(數據類型放在數據域中):9(1001,電能量)+0(0000,00當前,00有功)+ 2(0010,反向電能)+0(0000,總電能)

10、數據域+33H:0x90+0x33=0xC3 0x20+0x33=0x53

11、發送數據域:0x53 0xC3

12、校驗碼:CS(1個字節,比如計算出來的是“0x01”)

13、結束符:0x16

14、發送字符串:0xFE 0x68 0x61 45 69 00 00 00 0x68 0x01 0x02 0x53 0xC3 0x01 0x16

15、Byte[] bufferlist=new Byte[] {0xFE,0x68,0x61,0x45,0x69,0x00,0x00,0x00,0x68,0x01,0x02,0x53,0xC3,0x01,0x16 }

DL645編碼過程:
增加“前導符字節”(可以沒有)
增加幀起始符
增加地址域
增加幀起始符
增加控制碼
增加數據域長度
增加數據域
計算CS校驗碼,並增加
增加結束符


二、返回報文

1、幀起始符:0x68

2、地址域:0x614569000000

3、幀起始符:0x68

4、控制碼:傳送方向(0—電腦到表具,1—表具到電腦),從站異常標志(0—表具無異常,1—表具有異常),后續幀標識(0—無后續數據,1—有后續數據)

功能碼(讀數據):00001

最后是10000001(讀反相有功電能。從站向主站發送,第一位是“1”。主站向從站,第一位是“0”。),也就是“0x81”

5、數據域長度:
返回數據長度,根據請求的數據類型來定的。比如,電能量是“6個字節”,包含“2的數據類型”和“4字節的數據項”。

0x06

6、數據域
數據類型:0x53(低字節先返回) 0xC3(高字節后返回)
數據:0x33 0x78 0x34 0x66(先返回低字節,再返回高字節。電表是發送方。)

7、數據減去“33H”
0x33-0x33=0x00
0x78-0x33=0x45
0x34-0x33-0x01
0x66-0x33=0x33

8、按BCD碼解析16進制數
single datas = single.parse(0x33.ToString("X2");+0x01.ToString("X2");+0x45.ToString("X2");+"."+0x00.ToString("X2");)

9、最后結果

datas=datas+" kWh";

結果就是:330145.00 kWh  (電表總反相有功電能量,也就是“發電量”。耗電量是“正相有功電能量”)


DL645解碼過程:
--幀起始符
if 字節長度 = 1
{
if(字節!=0x68)
{
清除字節
程序等待
}
}


--地址
if 字節長度 = 7
{
循環判斷地址字段
{
if(地址不相等)
{
清除字節
程序等待
}
}
}

--幀起始符
if 字節長度 = 8
{

if(字節!=0x68)
{
清除字節
程序等待
}

}


--控制碼
if 字節長度 = 9
{

if(不等於0x81)
{
清除字節
程序等待
}
}


--計算報文總長度
if 字節長度 >= 10
{

報文總長度=1 幀起始符 + 6 地址+ 1 幀起始符+ 1 控制碼 + 1 數據域長度+ 1 校驗碼 + 1 結束符 + “數據域長度”

}


--校驗
if 報文總長度大於 >= 計算報文長度
{
計算校驗碼
if(校驗碼 != 被校驗報文 && 結束符 != 0x16)
{
清除字節
程序等待
}
}


處理數據域數據

寫入處理數據域數據

如果有什么不當的地方,還請大師們多多指正,請不要拍磚。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM