文章目录
- 问题
- 办法
- 将数据拆成 8 位,保存到 byte 数组
- 补充按位与运算
- 补充右移运算
- 举例说明
- 总结
问题
当数据在不同系统之间传输时,因为不同系统可能对字节的顺序有所不同。因此,需要将一个 16 位的值拆分为两个 8 位的字节,并将高位字节和低位字节需要分开存储。这样,能防止数据在传输过程中出现混乱的情况。
办法
将数据拆成 8 位,保存到 byte 数组
先上核心代码
analogReadResolution(14); // MAX_READING_14_bit = 16383 0-16383=16384 values = 2^14
int data = analogRead(A0); // 0-16383
byte msg[14];
msg[0] = data&255;
msg[1] = (data>>8)&255;
第一行表示设定 Arduino 开发板的模拟口精度为 14 位。
至于为什么精度能够设置成 14 位,因为我用的开发板是 Arduino Portenta H7,最大精度可到 16 位。更多资料可以看这篇文章:【Arduino】Portenta H7 板子介绍。
第二行表示从 Arduino 的 A0
口读取一个模拟数值,其范围为 0-16383。
注意 ADC 的精度已经提前规定成了 14 位精度,所以最大值才是 2^14 = 16384-1。
第三行表示创建一个 byte
字节类型的数组 msg
,数组的长度位 14 位,刚好对应了我们设定的模拟口读取精度。
第四行和第五行是将数据通过 按位与
和 右移
操作将 data
的低 8 位和高 8 位分别存储到 msg
数组的第 1 位和第 2 位。
补充按位与运算
按位与运算 (Bitewise AND) 是一种针对二进制数的逐位运算操作符。它对两个二进制数的对应位进行逻辑与操作,生成一个新的二进制数。
规则为:
- 如果两个对应位都为1,则结果的对应位为1。
- 如果两个对应位中有任何一个位为0,则结果的对应位为0。
例如,考虑以下两个二进制数的按位与运算:
1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | (171) |
---|---|---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | (204) |
& | ||||||||
1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | (136) |
补充右移运算
在C++中,右移操作使用右移位运算符 >>
表示。对于一个二进制数,右移操作将其所有位向右移动,移出的位将被丢弃,并在左侧补上 0。
例如,考虑以下二进制数的右移操作:
1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | (204) |
---|---|---|---|---|---|---|---|---|
>>3 | ||||||||
0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | (25) |
举例说明
比如当 data = 16234
时,在计算机中 data
的二进制表示为 00111111 10101010
。
按位与运算符 &
将 data
与 255 进行按位与运算,相当于将 data
的高 8 位全部置为 0,保留了低 8 位,并存储到数组 msg
的第一个元素 msg[0]
中。
也就是程序:
msg[0] = data&255;
具体运算如下所示:
0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | (16234) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
& | |||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | (255) | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | (106) |
右移运算 >>
先将 data
右移 8 位,即将原值的高 8 位移动到低 8 位的位置上。结果为 00000000 00111111
。然后再使用按位与运算符 &
将 00000000 00111111
与 255 进行按位与运算,同样是将 data
右移后的高 8 位全部置为 0,保留了低 8 位(相当于保留了原始值的高 8 位),并存储到数组 msg
的第二个元素 msg[1]
中。
也就是程序:
msg[1] = (data>>8)&255;
具体运算如下所示:
0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | (16234) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
>>8 | |||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | (63) |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | (63) | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
& | |||||||||||||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | (255) | |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | (63) |
总结
通过上述操作,我们成功将一个 16 位的值拆分为了两个 8 位的字节时,这样就可以传输到接收端了。这样做可以方便地在不同系统之间传输和处理数据。至于接收端怎么分析,那就要根据不同的接收端采用不同的方法了。