Android与单片机---开发板---智能硬件---智能设备---数据协议--开发总结

40 阅读6分钟
  • 小结:1 byte = 8 bit

3.1 什么是bit呢?什么又是高低位呢?在Java中又怎么写代码呢?

  • bit就是 也就是二进制数据,取值只有 0,1 - 高位在左,低位在右
  • 这里以byte 123为例:
  • byte b =123 转为bit
  • 高位在0,低位在1 0111 1011
  • 在Java中获取byte的8个bit

/**

  • byte转8 bit

  • @param b byte

  • @return 高位到低位顺序, 以byte123 为例: 0111 1011 */ public static byte[] byte2Bit(byte b) { byte[] arr = new byte[8]; for (int i = 7; i >= 0; i--) { arr[i] = (byte) (b & 1); b = (byte) (b >> 1); } return arr; }

  • 既然把byte转为了8个bit位,那我们又怎么再把bit转回为byte呢?

/**

  • 8个bit位转为byte */ public static byte bit2Byte(byte[] bytes) { if (bytes.length != 8) return 0; String binary = ""; byte result; for (byte b : bytes) { binary += b; } if (bytes[0] == 0) { // 正数 result = (byte) Integer.parseInt(binary, 2); } else { // 负数 result = (byte) (Integer.parseInt(binary, 2) - 256); } return result; }

3.2 上面已经说了byte与bit的相互转化,现在就轮到int

  • 上面已经说了一个int4个字节32bit
  • Integer类已经为我们封装好了转bit的方法,如下:

String s = Integer.toBinaryString(35235); //输出结果 1000100110100011

  • 可以看到没有32位,这是为什么呢?这是因为高位都是为0所以就直接省略了,当然我们也可以主动补齐32位只需要在高位补0即可。
  • bit再转回为int

int result = Integer.parseInt("1000100110100011", 2); //输出结果 35235

  • 这里需要注意的是Integer.toBinaryString()可以将负数转化为二进制,但是Integer.parseInt("", 2)不能直接将负数的二进制转为int,如下:

String radix = Integer.toBinaryString(-35235); System.out.println(radix); int result = Integer.parseInt(radix, 2); System.out.println(result);

程序执行会报一个java.lang.NumberFormatException: For input string:"11111111111111110111011001011101"异常,那我们怎么将负数的转回为int呢?当然是有方法的啦,如下:

//需要借助 BigInteger类 String radix = Integer.toBinaryString(-3535); BigInteger integer = new BigInteger(radix, 2); System.out.println(integer.intValue()); //输出结果 -3535

3.3当然我们可以通过电脑的计算器来计算二进制

3.4 上面我们说了一个int32个字节也就是4byte,那理所当然一个int可以转成2个byte或者4byte,如下:

/**

  • 一个int转2个字节的byte数组
  • 由低位到高位的转换
  • @param value
  • @return */ public static byte[] intTo2Bytes(int value) { byte[] src = new byte[2]; src[0] = (byte) (value & 0xFF); src[1] = (byte) ((value >> 8) & 0xFF); return src; }

/**

  • 一个int转4个字节的byte数组
  • 由低位到高位的转换
  • @param value
  • @return */ public static byte[] intTo4Bytes(int value) { byte[] src = new byte[4]; src[0] = (byte) (value & 0xFF); src[1] = (byte) ((value >> 8) & 0xFF); src[2] = (byte) ((value >> 16) & 0xFF); src[3] = (byte) ((value >> 24) & 0xFF); return src; }

这里需要注意的是int转byte[]的时候是高位数组的0下标 还是低位数组的0下标,上面的两个方法都是低位在数组的0下标

四、上面bb了一大堆,现在我们通过一个具体的协议来深入了解这些内容

4.1 协议如下:

这里需要解释下ucharuint是什么意思?uchar = unsigned char 、uint = unsigned int,也就是无符号的数据,也就是表示了这个数据是正数

  • 1、对协议进行分析可以得知:整个数据包是由两部分组成的包头+扩展数据包,其中包头占固定的32个字节
  • 2、首先我们得分析包头里面的每一个字段所占了多少个字节
  • uchar 占1个字节
  • uint 占4个字节
  • 2、那我们重点就是得来分析包头的数据需要怎么封装,通过协议我们可以看出包头内一共包含6个字段,分别表示如下:
  • 第一个为固定的"DH",总共占2个字节
  • 第二个为版本1.0 ,总共占2个字节
  • 第三个为扩展数据长度"extlen" ,总共占4个字节
  • 第四个为扩展数据类型取值0或1 ,总共占1个字节
  • 第五个为保留字段不使用就0补齐,总共占3个字节
  • 第六个为保留字段不使用就0补齐,总共占20个字节
  • 3、通过上面一顿分析,我们就轻松的理清了每个字段所占的字节了

4.2 Talk is cheap. Show me the code.

//magic byte[] magicB = {'D', 'H'}; //协议版本1.0转成int也就是1 byte[] versionB = {0, 1}; //扩展数据长度,这里假定扩展数据的长度为67 byte[] extLenB = intTo4Bytes(67); //扩展数据类型 0:JSON、1:二进制数据;这里使用JSON byte[] extType = {0}; //两个保留字段,直接0补齐,上面已经分析了两个字段一共占23个字节 byte[] reserved = new byte[23]; //这里将上面的多个数据合并至一个byte[] byte[] data = byteMergerAll(magicB, versionB, extLenB, extType, reserved);

到这里包头的数据就已经处理好了,还可以进一步对它进行封装

  • 这里提供一个多个数据数组合并的工具方法

/**

  • 多个数组合并一个
  • @return */ public static byte[] byteMergerAll(byte[]... bytes) { int allLength = 0; for (byte[] b : bytes) { allLength += b.length; } byte[] allByte = new byte[allLength]; int countLength = 0; for (byte[] b : bytes) { System.arraycopy(b, 0, allByte, countLength, b.length); countLength += b.length; } return allByte; }

4.3 封装包头数据

/**

  • 封装包头数据
  • 固定32个字节,其余的0补齐
  • @param extLen 扩展数据长度 */ public static byte[] getPkgHead(int extLen) { //magic byte[] magicB = {'D', 'H'}; //协议版本1.0转成int也就是1 byte[] versionB = {0, 1}; //扩展数据长度,这里假定扩展数据的长度为67 byte[] extLenB = intTo4Bytes(extLen); //扩展数据类型 0:JSON、1:二进制数据;这里使用JSON byte[] extType = {0}; //两个保留字段,直接0补齐,上面已经分析了两个字段一共占23个字节 byte[] reserved = new byte[23]; //这里将上面的多个数据合并至一个byte[] return byteMergerAll(magicB, versionB, extLenB, extType, reserved); }

4.4上面已经把包头处理好了那现在就可以发送命令了

//扩展数据:这里就需要根据实际的文档来生成了,我这里就随便写一个了

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。 img img

如果你需要这些资料,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!