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得到第一个字节)

  1. function LengthID(ch1, ch2, ch3) local tmp = "";
  2. tmp = tmp .. string.char(0x30) .. string.char(ch1) .. string.char(ch2) .. string.char(ch3);
  3. print("tmp==>",tmp);
  4. local HI = Parse2btye(string.sub(tmp,,));
  5. local LO = Parse2btye(string.sub(tmp,,));
  6. print(LO)--两个十六进制数1e转化为十进制30
  7. print("lo==>",string.format("%x",LO));
  8. print("hi==>",string.format("%x",HI));
  9. local hh = bits.band(HI, 0x0F);
  10. local mid = bits.rshift(bits.band(LO, 0xF0),);--z:加法时一定别带十六进制权(比如01e:并非10+0e,而是01+0e
  11. local ll = bits.band(LO, 0x0F);
  12. print(string.format("%x",hh+mid+ll))
  13. local cs = bits.bnot(hh+mid+ll, 0xFF)+;
  14.  
  15. local rh = bits.bor(bits.lshift(cs, ),hh);
  16. return Hex2Ascii(rh);--返回rh的高位和低位,高位就是我们需要的LCHKSUM
  17. 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字符串

  1. function CheckSum(strlen,buffer)--z:特别注意传输时一个数据字节直接使用了两个ascii码表示,一个ascii码占一个字节,用两位十六进制数表示
  2.  
  3. --计算lengthchk并填充
  4. x,y=LengthID(buffer[],buffer[],buffer[]);
  5. print("lengthchk:",string.format("%x",x))
  6. print("lengthchk:",string.format("%x",y))
  7. buffer[]=x
  8.  
  9. print("uncheck table:")
  10. for key,value in pairs(buffer) do
  11. io.write(string.format("%x",value)," ")
  12. end
  13. print()
  14. local sum = 0.0;
  15.  
  16. for i = ,strlen- do
  17. sum = sum + buffer[i];
  18. end
  19. print("checksum==>",string.format("%x",sum));
  20. --取得sum的高位和低位
  21. local hh = bits.rshift(bits.band(sum, 0xff00), );
  22. local ll = bits.band(sum, 0x00ff);
  23. --高位低位分别取反
  24. local nhh = bit32.band(bit32.bnot(hh),0x000000ff);
  25. local nll = bit32.band(bit32.bnot(ll),0x000000ff);
  26. --低位+1不进位的话就直接加,要进位的话就加高位
  27. if nll+ <= 0xFF then
  28. chkh = nhh;
  29. chkl = nll+;
  30. elseif nhh+ <= 0xFF then
  31. chkh = nhh+;
  32. chkl = ;
  33. else
  34. chkh = ;
  35. chkl = ;
  36. end
  37. print("zzyh:",string.format("%x",chkh));
  38. h1,h2=Hex2Ascii(chkh)
  39. print(string.format("%x",h1))
  40. print(string.format("%x",h2))
  41. print("zzyl:",string.format("%x",chkl));
  42. l1,l2=Hex2Ascii(chkl);
  43. print(string.format("%x",l1))
  44. print(string.format("%x",l2))
  45. buffer[strlen-]=h1
  46. buffer[strlen-]=h2
  47. buffer[strlen-]=l1
  48. buffer[strlen-]=l2
  49. print("checked table:")
  50. for k,v in pairs(buffer) do
  51. io.write(string.format("%x",v)," ")
  52. end
  53. print()
  54. 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:上面的两个处理函数涉及到的自定义函数

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

  1. function utils.str2chr(str)--将由16进制字符组成的字符串转化为该十六进制相对应的ascii字符串
  2. local ret="";
  3. local tmp;
  4. print("undostring:",str);
  5. for w in string.gmatch(str,"%x+") do--循环的读取该串中的十六进制数据并且转化为字符,例如:0x32->2
  6. tmp=string.sub(w,);
  7. ret=ret..string.char(tonumber(tmp,));
  8. end
  9. print("done string:",ret);
  10. strlen=string.len(retStr);
  11. return strlen,retStr;
  12. end;
  13. function utils.str2table(str)--z:表格里面存的是每个字符对应的ascii数字编码
  14. local RetTable = {};
  15. if string.len(str) <= then
  16. return nil;
  17. end;
  18. strlen,str = utils.str2chr(str);
  19. for i = , strlen do
  20. RetTable[i] = string.byte(string.sub(str, i, i + ));--将ascii字符串每一个字符变为表的每一项,一个字符对应一个ascii数字编码
  21. end;
  22. return strlen,RetTable;
  23. end;
  24. function Parse2btye(szStr)
  25. if string.byte(szStr,) == 0x20 and string.byte(szStr,) == 0x20 then
  26. return VALUE_INVALID;
  27. end
  28. local buf = '';
  29.  
  30. buf = commutils.Hex2Dec(string.sub(szStr, ));
  31. return string.byte(buf,);
  32. end
  33. function Hex2Ascii(hex)--把两位十六进制表示的一个数据的高位和低位分别转为adcii码表示,高位对应一个adcii,低位对应一个ascii,该ascii又由一个两位十六进制数表示()
  34. local chartable = {'', '', '', '', '', '', '', '', '', '', 'A', 'B', 'C', 'D', 'E', 'F'};
  35. local low = bits.band(hex, 0x0f);
  36. local high = bits.rshift(bits.band(hex, 0xf0), );--z:与oxfo与运算并且右移四位去除低四位
  37.  
  38. local lowAsc = string.byte(chartable[low+]);
  39. local highAsc = string.byte(chartable[high+]);
  40. --print(string.format("%x: %x", lowAsc, highAsc));
  41. return highAsc,lowAsc
  42. end
  1. local function Byte2Hex(szByte)
  2. if szByte >= string.byte('') and szByte <= string.byte('') then
  3. return szByte - string.byte('');
  4. elseif szByte >= string.byte('a') and szByte <= string.byte('f') then
  5. return szByte - string.byte('a')+;
  6. elseif szByte >= string.byte('A') and szByte <= string.byte('F') then
  7. return szByte - string.byte('A')+;
  8. else
  9. print("ParseData error,szByte = ",string.format("%02x",string.byte(szByte)));
  10. return ;
  11. end
  12. end
  13.  
  14. local function Hex2Dec(szStr)--把两个十六进制数转化为一个long型数
  15. local tmp1,tmp2;
  16. --if string.byte(szStr,1)==nil or string.byte(szStr,2)==nil then
  17. -- return 0;
  18. --else
  19. print("tmp1udo==>",string.byte(szStr,))
  20. tmp1 = Byte2Hex(string.byte(szStr,));
  21. print("tmp1==>",tmp1)
  22. tmp2 = Byte2Hex(string.byte(szStr,));
  23. print("tmp2udo==>",string.byte(szStr,))
  24. print("tmp2==>",tmp2)
  25. print("dec==>",tmp1* + tmp2);
  26. return string.char(tmp1* + tmp2);
  27. --end
  28. --return string.char(tmp1*16 + tmp2);
  29. 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 ...