zoukankan      html  css  js  c++  java
  • 将硬件规定的通信协议用Lua实现(涉及到很多Lua通信的数据转换)

    1:这次处理的是大唐的gps通信协议,先简单介绍一下他规定的通信规则:

    信息结构:

    传输说明:

      信息结构中的各个字节书写时都是以十六进制标识,两位数组成。传输时,SOIEOISOI=7EHEOI=0DH)各按一个字节传输,但其余各项每个字节都是拆成两个字节,每个字节用两个ASCII码标识,即高4位用一个ASCII码表示,低4位用一个ASCII码标识,传输时先发送高4位的ASCII码,后发送低4位的ASCII码。

    示例:CID2=4BH4ASCII码是34HBASCII码是42H,传送时顺序发送34H42H两个字节。

    因此,实际传输的字节数应是1以及下面各表中字节数乘以2

    2:要达到的目的: 

    例如要处理一段这样的数据:(需要计算的LCHkSUM和CHKSUM由46代替)                        

    info="7E 32 31 30 31 44 30 30 30 

                46 30 31 45 ( length段(1个LCHKSUM+3个LENTGTHID)

                 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

                 0D" 

      我们不知道LCHKSUM是多少,也不知道后面的CHKSUM是多少但是知道其他,总不能手动去算吧,于是写了如下程序用来自动计算这两个CHKSUM

    3:关于LENGTH段的解释:

      LENGTH2个字节,由LENIDLCHKSUM组成,LENID表示INFO项的ASCII码字节数,当LENID=0时,INFO为空,即无该项。LENGTH拆分4ASCII码传送,先高字节,后低字节。校验码的计算:D11D10D9D8+D7D6D5D4+D3D2D1D0,求和后模16余数取反加1

    示例:

    INFO项的ASCII码字节数为18,即LENID=0000 0001 0010B

    D11D10D9D8+D7D6D5D4+D3D2D1D0=0000B+0001B+0010B=0011B,模16余数为0011B0011B取反加1就是1101B,即LCHKSUM1101B

    可以得出:LENGTH1101 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" 

     

    4:关于CHKSUM的解释:

      CHKSUM的计算是除SOIEOICHKSUM外,其他字符按ASCII码值累加求和,所得结果模65536余数取反加1CHKSUM拆分4ASCII码传送,先高字节,后低字节。

    示例:

    收到或发送的字符序列为:“~20014043E00200FD3BR”(“~”为SOIREOI),则最后5个字符FD3BR中的FD3BCHKSUM,计算方法是:

    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"

    完了!哈哈

    5:上面的两个处理函数涉及到的自定义函数

     !(函数在这里没有分包,实际中是在不同的包中)

    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

     

  • 相关阅读:
    CNN comprehension
    Gradient Descent
    Various Optimization Algorithms For Training Neural Network
    gerrit workflow
    jenkins job配置脚本化
    Jenkins pipeline jobs隐式传参
    make words counter for image with the help of paddlehub model
    make words counter for image with the help of paddlehub model
    git push and gerrit code review
    image similarity
  • 原文地址:https://www.cnblogs.com/zzy-frisrtblog/p/5920034.html
Copyright © 2011-2022 走看看