信息結構:數組
傳輸說明:函數
信息結構中的各個字節書寫時都是以十六進制標識,兩位數組成。傳輸時,SOI和EOI(SOI=7EH,EOI=0DH)各按一個字節傳輸,但其他各項每一個字節都是拆成兩個字節,每一個字節用兩個ASCII碼標識,即高4位用一個ASCII碼錶示,低4位用一個ASCII碼標識,傳輸時先發送高4位的ASCII碼,後發送低4位的ASCII碼。編碼
示例:CID2=4BH,4的ASCII碼是34H,B的ASCII碼是42H,傳送時順序發送34H和42H兩個字節。spa
所以,實際傳輸的字節數應是表1以及下面各表中字節數乘以2。code
例如要處理一段這樣的數據:(須要計算的LCHkSUM和CHKSUM由46代替) orm
info="7E 32 31 30 31 44 30 30 30 blog
46 30 31 45 ( length段(1個LCHKSUM+3個LENTGTHID))ci
30 30 30 36 33 32 36 31 42 37 30 31 44 34 42 42 42 39 30 31 45 41 30 30 30 30 30 30 30 30(數據段)字符串
46 46 46 46 (CHKSUM)string
0D"
咱們不知道LCHKSUM是多少,也不知道後面的CHKSUM是多少可是知道其餘,總不能手動去算吧,因而寫了以下程序用來自動計算這兩個CHKSUM
LENGTH共2個字節,由LENID和LCHKSUM組成,LENID表示INFO項的ASCII碼字節數,當LENID=0時,INFO爲空,即無該項。LENGTH拆分4個ASCII碼傳送,先高字節,後低字節。校驗碼的計算:D11D10D9D8+D7D6D5D4+D3D2D1D0,求和後模16餘數取反加1。
示例:
INFO項的ASCII碼字節數爲18,即LENID=0000 0001 0010B。
D11D10D9D8+D7D6D5D4+D3D2D1D0=0000B+0001B+0010B=0011B,模16餘數爲0011B,0011B取反加1就是1101B,即LCHKSUM爲1101B。
能夠得出:LENGTH爲1101 0000 0001 0010B,即D012H。
代碼實現:(利用length段的後面234字節算出chksum獲得第一個字節)
function LengthID(ch1, ch2, ch3) local tmp = ""; tmp = tmp .. string.char(0x30) .. string.char(ch1) .. string.char(ch2) .. string.char(ch3); print("tmp==>",tmp); local HI = Parse2btye(string.sub(tmp,1,2)); local LO = Parse2btye(string.sub(tmp,3,4)); print(LO)--兩個十六進制數1e轉化爲十進制30 print("lo==>",string.format("%x",LO)); print("hi==>",string.format("%x",HI)); local hh = bits.band(HI, 0x0F); local mid = bits.rshift(bits.band(LO, 0xF0),4);--z:加法時必定別帶十六進制權(好比01e:並不是10+0e,而是01+0e) local ll = bits.band(LO, 0x0F); print(string.format("%x",hh+mid+ll)) local cs = bits.bnot(hh+mid+ll, 0xFF)+1; local rh = bits.bor(bits.lshift(cs, 4),hh); return Hex2Ascii(rh);--返回rh的高位和低位,高位就是咱們須要的LCHKSUM end
通過這個計算:上面給出例子中的info變成了:
info="7E 32 31 30 31 44 30 30 30 31 30 31 45 30 30 30 36 33 32 36 31 42 37 30 31 44 34 42 42 42 39 30 31 45 41 30 30 30 30 30 30 30 3046 46 46 460D"
CHKSUM的計算是除SOI、EOI和CHKSUM外,其餘字符按ASCII碼值累加求和,所得結果模65536餘數取反加1。CHKSUM拆分4個ASCII碼傳送,先高字節,後低字節。
示例:
收到或發送的字符序列爲:「~20014043E00200FD3B\R」(「~」爲SOI,\R爲EOI),則最後5個字符FD3B\R中的FD3B爲CHKSUM,計算方法是:
‘2’+‘0’+‘0’+……+‘E’+‘0’+‘0’+‘2’+‘0’+‘0’
=32H+30H+30H+……+45H+30H+30H+32H+30H+30H
=02C5H
將由16進制字符組成的字符串轉化爲該十六進制相對應的ascii字符串
function CheckSum(strlen,buffer)--z:特別注意傳輸時一個數據字節直接使用了兩個ascii碼錶示,一個ascii碼佔一個字節,用兩位十六進制數表示 --計算lengthchk並填充 x,y=LengthID(buffer[11],buffer[12],buffer[13]); print("lengthchk:",string.format("%x",x)) print("lengthchk:",string.format("%x",y)) buffer[10]=x print("uncheck table:") for key,value in pairs(buffer) do io.write(string.format("%x",value)," ") end print() local sum = 0.0; for i = 2,strlen-5 do sum = sum + buffer[i]; end print("checksum==>",string.format("%x",sum)); --取得sum的高位和低位 local hh = bits.rshift(bits.band(sum, 0xff00), 8); local ll = bits.band(sum, 0x00ff); --高位低位分別取反 local nhh = bit32.band(bit32.bnot(hh),0x000000ff); local nll = bit32.band(bit32.bnot(ll),0x000000ff); --低位+1不進位的話就直接加,要進位的話就加高位 if nll+1 <= 0xFF then chkh = nhh; chkl = nll+1; elseif nhh+1 <= 0xFF then chkh = nhh+1; chkl = 0; else chkh = 0; chkl = 0; end print("zzyh:",string.format("%x",chkh)); h1,h2=Hex2Ascii(chkh) print(string.format("%x",h1)) print(string.format("%x",h2)) print("zzyl:",string.format("%x",chkl)); l1,l2=Hex2Ascii(chkl); print(string.format("%x",l1)) print(string.format("%x",l2)) buffer[strlen-4]=h1 buffer[strlen-3]=h2 buffer[strlen-2]=l1 buffer[strlen-1]=l2 print("checked table:") for k,v in pairs(buffer) do io.write(string.format("%x",v)," ") end print() end
通過這個計算:上面給出例子中的info變成了:
info="7E 32 31 30 31 44 30 30 30 31 30 31 45 30 30 30 36 33 32 36 31 42 37 30 31 44 34 42 42 42 39 30 31 45 41 30 30 30 30 30 30 30 30 46 37 34 37 0D"
完了!哈哈
!(函數在這裏沒有分包,實際中是在不一樣的包中)
function utils.str2chr(str)--將由16進制字符組成的字符串轉化爲該十六進制相對應的ascii字符串 local ret=""; local tmp; print("undostring:",str); for w in string.gmatch(str,"%x+") do--循環的讀取該串中的十六進制數據而且轉化爲字符,例如:0x32->2 tmp=string.sub(w,0); ret=ret..string.char(tonumber(tmp,16)); end print("done string:",ret); strlen=string.len(retStr); return strlen,retStr; end; function utils.str2table(str)--z:表格裏面存的是每一個字符對應的ascii數字編碼 local RetTable = {}; if string.len(str) <= 0 then return nil; end; strlen,str = utils.str2chr(str); for i = 1, strlen do RetTable[i] = string.byte(string.sub(str, i, i + 1));--將ascii字符串每個字符變爲表的每一項,一個字符對應一個ascii數字編碼 end; return strlen,RetTable; end; function Parse2btye(szStr) if string.byte(szStr,1) == 0x20 and string.byte(szStr,2) == 0x20 then return VALUE_INVALID; end local buf = ''; buf = commutils.Hex2Dec(string.sub(szStr, 1)); return string.byte(buf,1); end function Hex2Ascii(hex)--把兩位十六進制表示的一個數據的高位和低位分別轉爲adcii碼錶示,高位對應一個adcii,低位對應一個ascii,該ascii又由一個兩位十六進制數表示() local chartable = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; local low = bits.band(hex, 0x0f); local high = bits.rshift(bits.band(hex, 0xf0), 4);--z:與oxfo與運算而且右移四位去除低四位 local lowAsc = string.byte(chartable[low+1]); local highAsc = string.byte(chartable[high+1]); --print(string.format("%x: %x", lowAsc, highAsc)); return highAsc,lowAsc end
local function Byte2Hex(szByte) if szByte >= string.byte('0') and szByte <= string.byte('9') then return szByte - string.byte('0'); elseif szByte >= string.byte('a') and szByte <= string.byte('f') then return szByte - string.byte('a')+10; elseif szByte >= string.byte('A') and szByte <= string.byte('F') then return szByte - string.byte('A')+10; else print("ParseData error,szByte = ",string.format("%02x",string.byte(szByte))); return 0; end end local function Hex2Dec(szStr)--把兩個十六進制數轉化爲一個long型數 local tmp1,tmp2; --if string.byte(szStr,1)==nil or string.byte(szStr,2)==nil then -- return 0; --else print("tmp1udo==>",string.byte(szStr,1)) tmp1 = Byte2Hex(string.byte(szStr,1)); print("tmp1==>",tmp1) tmp2 = Byte2Hex(string.byte(szStr,2)); print("tmp2udo==>",string.byte(szStr,2)) print("tmp2==>",tmp2) print("dec==>",tmp1*16 + tmp2); return string.char(tmp1*16 + tmp2); --end --return string.char(tmp1*16 + tmp2); end