阿硬:协议定好了,你按协议上的解析就可以了。
小卡拉米:高八位,中八位低八位什么意思。
阿硬:
在我们和硬件通讯的协议当中,可能要一个字节一个字节的解析。但是我们有时候需要传输的数据有时候用一个字节是不够的。 比如一个CAN协议,要接收一个数据
我们接收到数据段有三个字节,第一个字节代表数据的高八位,第二个字节代表数据的中八位,第三个字节代表数据的低八位。我们怎么解析这个数据呢?
1、复习byte ,short,int 和 long
在Kotlin中
类型 | 位数 | 字节数 | 取值范围 |
---|---|---|---|
Byte |
8 | 1 | -128 到 127 |
Short |
16 | 2 | -32768 到 32767 |
Int |
32 | 4 | -2³¹ 到 2³¹-1 |
Long |
64 | 8 | -2⁶³ 到 2⁶³-1 |
2、传输数据时,byte个数的选择
当传输状态信息(例如设备启动状态、水温、空调温度设定值)时,一个 Byte
(8位)通常足以表示,因为其取值范围(-128 至 127)能够涵盖这类离散或有限范围的状态值。
若传输的数据值超出 Byte
的表示范围,则需要使用两个 Byte
组合表示一个数值 :其中一个 Byte
表示高八位 ,另一个 Byte
表示低八位。
对于小数类型的数据传输 ,需在通信协议中明确规定小数精度 (例如保留三位小数)。实际传输时,一般做法是将原始数值乘以缩放因子(如 1000)转换为整数 ,然后发送该整数值。接收方解析后,再除以相同的缩放因子(如 1000) ,即可还原原始数值。
3、两个byte 转成一个数
核心原理:二进制位拼接与数值重构
当使用两个字节表示一个数值时(Byte1 为高八位,Byte2 为低八位),本质是通过二进制位的拼接重构原始数值。其数学原理是:
最终数值 = (高八位值 × 256) + 低八位值
具体的操作步骤:
3.1、字节到整数的无符号转换
Kotlin/Java中,Byte 是有符号类型,需要转为无符号整数
kotlin
val highBits = byte1.toInt() and 0xFF // 高八位无符号值 (0~255)
val lowBits = byte2.toInt() and 0xFF // 低八位无符号值 (0~255)
and 0xFF 确保只保留后八位
3.2、高八位左移
通过位左移(<<) 将高八位移动到正确位置:
kotlin
val shiftedHigh = highBits shl 8 // 等价于 highBits × 2⁸
00001011
(十进制11)左移8位 → 00001011_00000000
(十进制2816)
3.3、位或(OR)运算合并
将移位后的高八位与低八位进行按位或运算:
kotlin
val finalValue = shiftedHigh or lowBits // 位拼接
00001011_00000000
(高八位)
OR 00101100
(低八位)
= 00001011_00101100
原理解析图
kotlin
高八位字节 (byte1) 低八位字节 (byte2)
┌───────┐ ┌───────┐
│ 00001011 │ │ 00101100 │
└───────┘ └───────┘
│ │
▼ 左移8位 ▼
┌───────────────┐ ┌───────┐
│ 0000101100000000 │ OR │ 00101100 │
└───────────────┘ └───────┘
│ │
└─────┬─────┘
▼
┌───────────────────┐
│ 0000101100101100 │ → 十进制2860
└───────────────────┘
高中低 同理,三个的时候,高八位要左移十六, 中八位左移八位
4、一个数转成两个byte
4.1. 提取低八位(byte2) :
kotlin
val byte2 = (value and 0xFF).toByte() // 直接取最后8位
and 0xFF
操作:屏蔽高24位,保留最低8位- 示例:2860(0x0B2C)→ 0x2C → 44
4.2. 提取高八位(byte1) :
kotlin
val byte1 = (value shr 8).toByte() // 右移8位后取低8位
shr 8
操作:将原始值右移8位(相当于除以256)- 示例:2860(0x0B2C)→ 右移8位 → 0x0B → 11
4.3 如果需要提取中八位,需要注意一下
详细步骤(以 0x12345678 为例)
-
屏蔽低八位(清除0-7位) :
kotlinval withoutLow = value and 0xFFFFFF00 // 清除低8位
- 位掩码
0xFFFFFF00
=11111111_11111111_11111111_00000000
- 示例:
0x12345678 and 0xFFFFFF00 = 0x12345600
- 效果:保留24-8位,清除0-7位
- 位掩码
-
屏蔽高八位(清除24-31位) :
kotlinval middle8 = (value shr 8) and 0xFF // 右移后取低8位
-
步骤分解:
a.
value shr 8
:将值右移8位0x12345678 shr 8 = 0x00123456
b.and 0xFF
:取结果的最低8位0x00123456 and 0xFF = 0x56
-
完整代码实现
kotlin
fun extractMiddle8Bits(value: Int): Int {
:直接右移+掩码(推荐)
return (value shr 8) and 0xFF
// 方法2:分步屏蔽
// val withoutLow = value and 0xFFFFFF00
// return (withoutLow ushr 8) and 0xFF
}
OK,这样就可以和阿硬愉快的沟通啦