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. border实现三角形的原理

    前言:网上最普遍的实现三角形的方法,就是通过控制border来实现,那为什么可以呢? 原理 我们先来看看border的表现形式. #box{ width:100px; height:100px; ba ...

  2. mybatis三种传值方式

    第一种:按序列传参(dao层的函数方法)[sql] Public User selectUser(String name,String area); 对应的Mapper.xml [sql] <s ...

  3. 关于js的两个函数

    注:这两个函数结合其他主要实现异步的默认checkbox选中和其他选中,从php页面穿过来已经选中的值,用jQuery 回绑:关键点在于$.each(),遍历,再用$.attr() 回绑:第二步关键点 ...

  4. Vuex2.0边学边记+两个小例子

    最近在研究Vuex2.0,搞了好几天终于有点头绪了. 首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各 ...

  5. MySQL数据库(7)----数据库的选择、创建、删除和更改

    1.选择数据库 使用 USE 语句可以选择数据库,并把它指定为MySQL服务器连接的默认(当前)数据库: USE db_name; 要想选择数据库,用户必须要具备相应的访问权限:否则,会出现错误提示. ...

  6. 131.005 Unsupervised Learning - Cluster | 非监督学习 - 聚类

    @(131 - Machine Learning | 机器学习) 零. Goal How Unsupervised Learning fills in that model gap from the ...

  7. mac 下常用快捷键

    1.快速搜索某个类 双击thift 2.切换不同的类: ctrl+方向键 3.alt+command+B 进入到具体的子类 但是 ctrl+方向键一直切的是电脑上 桌面的切换.打开 系统偏好设置-快捷 ...

  8. CPU纯软件半虚拟化技术

    在2003年出现的Xen,使用了另外的一种半虚拟化的方案来解决x86架构下CPU的敏感指令问题.主要采用Hypercall技术.Guest OS的部分代码被改变,从而使Guest OS会将和特权指令相 ...

  9. 关于Unity3d的Quaternion.Slerp的学习

    首先在场景中创建三个cube的GameObject,from表示要转换之前的样子,to表示转换之后的样子,change表示转的效果.如下图所示: 其中from和change cube开始运行之前的tr ...

  10. Java实例---简单的宠物管理系统

    代码分析 Cat.java package com.ftl.petshop; class Cat implements Pet { private String name; private Strin ...