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

信息结构:

传输说明:

  信息结构中的各个字节书写时都是以十六进制标识,两位数组成。传输时,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两个字节。

因此,实际传输的字节数应是表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段的解释:

  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,,));
local LO = Parse2btye(string.sub(tmp,,));
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),);--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)+; local rh = bits.bor(bits.lshift(cs, ),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的计算是除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[],buffer[],buffer[]);
print("lengthchk:",string.format("%x",x))
print("lengthchk:",string.format("%x",y))
buffer[]=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 = ,strlen- do
sum = sum + buffer[i];
end
print("checksum==>",string.format("%x",sum));
--取得sum的高位和低位
local hh = bits.rshift(bits.band(sum, 0xff00), );
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+ <= 0xFF then
chkh = nhh;
chkl = nll+;
elseif nhh+ <= 0xFF then
chkh = nhh+;
chkl = ;
else
chkh = ;
chkl = ;
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-]=h1
buffer[strlen-]=h2
buffer[strlen-]=l1
buffer[strlen-]=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,);
ret=ret..string.char(tonumber(tmp,));
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) <= then
return nil;
end;
strlen,str = utils.str2chr(str);
for i = , strlen do
RetTable[i] = string.byte(string.sub(str, i, i + ));--将ascii字符串每一个字符变为表的每一项,一个字符对应一个ascii数字编码
end;
return strlen,RetTable;
end;
function Parse2btye(szStr)
if string.byte(szStr,) == 0x20 and string.byte(szStr,) == 0x20 then
return VALUE_INVALID;
end
local buf = ''; buf = commutils.Hex2Dec(string.sub(szStr, ));
return string.byte(buf,);
end
function Hex2Ascii(hex)--把两位十六进制表示的一个数据的高位和低位分别转为adcii码表示,高位对应一个adcii,低位对应一个ascii,该ascii又由一个两位十六进制数表示()
local chartable = {'', '', '', '', '', '', '', '', '', '', 'A', 'B', 'C', 'D', 'E', 'F'};
local low = bits.band(hex, 0x0f);
local high = bits.rshift(bits.band(hex, 0xf0), );--z:与oxfo与运算并且右移四位去除低四位 local lowAsc = string.byte(chartable[low+]);
local highAsc = string.byte(chartable[high+]);
--print(string.format("%x: %x", lowAsc, highAsc));
return highAsc,lowAsc
end
local function Byte2Hex(szByte)
if szByte >= string.byte('') and szByte <= string.byte('') then
return szByte - string.byte('');
elseif szByte >= string.byte('a') and szByte <= string.byte('f') then
return szByte - string.byte('a')+;
elseif szByte >= string.byte('A') and szByte <= string.byte('F') then
return szByte - string.byte('A')+;
else
print("ParseData error,szByte = ",string.format("%02x",string.byte(szByte)));
return ;
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,))
tmp1 = Byte2Hex(string.byte(szStr,));
print("tmp1==>",tmp1)
tmp2 = Byte2Hex(string.byte(szStr,));
print("tmp2udo==>",string.byte(szStr,))
print("tmp2==>",tmp2)
print("dec==>",tmp1* + tmp2);
return string.char(tmp1* + tmp2);
--end
--return string.char(tmp1*16 + tmp2);
end

将硬件规定的通信协议用Lua实现(涉及到很多Lua通信的数据转换)的更多相关文章

  1. 用VC编译lua源码,生成lua语言的解释器和编译器

    用VC编译lua源码,生成lua语言的解释器和编译器 1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编 ...

  2. [Lua]Mac系统上安装Lua环境

    1.下载 Lua语言的官方网站 http://www.lua.org/ 下载最新版本的Lua环境 2.安装 解压下载包lua-5.3.1.tar.gz 打开终端Terminal 使用cd命令进入该目录 ...

  3. 【cocos2d-x + Lua(1) 绑定Lua并使用tolua++】

    为什么要使用Lua进行游戏开发?转载请注明出处http://www.cnblogs.com/zisou/p/cocos2dx-lua1.html 上面一个问题我觉得在我们使用Lua之前需要深入思考的, ...

  4. lua调用java java调用lua[转载]

    转载:http://dualface.github.io/blog/2013/01/01/call-java-from-lua/LuaJavaBridge - Lua 与 Java 互操作的简单解决方 ...

  5. Lua学习 2) —— Android与Lua互调

    2014-07-09 一.Android类调用lua并回调 Android调用Lua函数,同一时候把类作为參数传递过去.然后再Lua中回调类的函数 调用lua mLuaState = LuaState ...

  6. ESP8266 LUA脚本语言开发: 准备工作-LUA文件加载与变量调用

    前言 这节说一下多个文件调用 多个文件之间变量调用 准备两个文件 init.lua other.lua 开始 模块默认一开始调用的是init.lua 咱让init.lua调用 other.lua 很简 ...

  7. ESP8266 LUA脚本语言开发: 准备工作-LUA开发是怎么来的

    前言 当前8266有各种开发 1.在官方已经封装好的C库上开发(SDK开发) 2.官方在SDK的基础上封装的AT指令程序(AT指令开发) 3.在SDK的基础上嵌入脚本语言(Lua,Python等开发方 ...

  8. [lua]紫猫lua教程-命令宝典-L1-01-11. lua的个人补充

    1.关于三目运算符的一些补充和纠正 前面没看仔细  a>b ? a: b 这个形式 似乎lua下并不存在...要了命 一般都是使用  a and b or c 的形式 但是这种形式存在一些问题 ...

  9. [lua]紫猫lua教程-命令宝典-L1-01-01. Lua环境与IDE

    网上大把的lua教程  不过紫猫老师的教程向来都是讲的非常仔细 所以最近天气已经36+了 魔兽世界还需要冲飞行声望  懒得写单子根本没有单子,正好认认真真的看下紫猫老师的lua教程 紫猫老师的lua教 ...

随机推荐

  1. Ubuntu增加一个用户并给普通用户赋予root权限的方法

    1.添加用户,首先用adduser命令添加一个普通用户,命令如下: #adduser tommy //添加一个名为tommy的用户#passwd tommy   //修改密码Changing pass ...

  2. linux_day3

    1.grep与find的区别? grep是查找文件内的字符而find则是查找文件 2.显示/etc/passwd中以nologin结尾的行 3. 输入ip addr命令后,过滤出包含ip的行 ip a ...

  3. 读<css世界>笔记之img标签

    Web开发时,为了节约带宽以及提高加载性能,首屏以下的图片就会通过滚屏加载的方式异步加载,然后这个即将被异步加载的图片为了布局稳健,体验良好,往往会使用一张透明的图片占位,如: <img src ...

  4. C# 五大修饰符

    修饰符 访问权限 public 关键字是类型和类型成员的访问修饰符. 公共访问是允许的最高访问级别. 对访问公共成员没有限制 private 私有访问是允许的最低访问级别. 私有成员只有在声明它们的类 ...

  5. Python学习---基于JQuery的Ajax实现[快捷+底层$.ajax]

    快捷API <1>$.get(url, [data], [callback], [type]) <2>$.post(url, [data], [callback], [type ...

  6. codeforces 420D Cup Trick

    codeforces 420D Cup Trick 题意 题解 官方做法需要用到线段树+平衡树(? 如果数据小的话似乎可以用莫队).然后代码好长好长.我补了一个只要用到树状数组的做法. 代码 #inc ...

  7. Entity Framework 指定架构无效 错误:1052

    IIS发布网站:如果不发布放到IIS没有问题,发布后IIS部署 打开网站却提示指定架构无效 1052 找到很多解决的问题 1添加wenconfig 2.更改entity名的 其实我认为最简单的就是先找 ...

  8. cheerio数据抓取

    很多语言都能写个爬虫抓取数据,js自然也可以,使用cheerio可以支持css检索,较快捷的获取需要的数据.首先,先把node.js给安装了.可到官网下载.安装好node.js后,使用npm安装che ...

  9. 纯css3跑马灯demo

    我们写跑马灯一般都是用js控制定时器不断循环产生,但是定时器消耗比较大,特别是程序中很多用到定时器的时候,感觉有的时候比较卡.但是css3样式一般不会.这里主要的思路就是用css3代替js定时器实现一 ...

  10. UVa 1640 - The Counting Problem(数论)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...