Android 与单片机 --- 开发板 --- 智能硬件 --- 智能设备 --- 数据协议 -- 开发总结
| --- | --- | --- | --- || byte | 1 | 8 | -128 ~ 127 || char | 2 | 16 | '\u0000' ~ '\uFFFF' || short | 2 | 16 | -2^15 ~ 2^15 - 1 || int | 4 | 32 | -2^31 ~ 2^31 - 1 || float | 4 | 32 | 2^-149 ~ 2^128 -1 || long | 8 | 64 | -2^63 ~ 2^63 - 1 || double | 8 | 64 | 2^-1074 ~ 2^1024 - 1 || boolean | / | 1 | true or false |
String 在 Java 中不属于基本数据类型,一个汉字占 2 个字节,一个英文字母占 1 个字节
小结: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
了
上面已经说了一个
int
占4
个字节`32
个
bit`
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 上面我们说了一个int
占32
个字节也就是4
个byte
,那理所当然一个int
可以转成 2 个 byte 或者4
个byte
,如下:
/**
一个 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 协议如下:
这里需要解释下
uchar
、uint
是什么意思?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.
//magicbyte[] magicB = {'D', 'H'};//协议版本 1.0 转成 int 也就是 1byte[] versionB = {0, 1};//扩展数据长度,这里假定扩展数据的长度为 67byte[] extLenB = intTo4Bytes(67);//扩展数据类型 0:JSON、1:二进制数据;这里使用 JSONbyte[] 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) {//magicbyte[] magicB = {'D', 'H'};//协议版本 1.0 转成 int 也就是 1byte[] versionB = {0, 1};//扩展数据长度,这里假定扩展数据的长度为 67
评论