在Arduino上将一个整数转换为两个字节进行传输

3
我正在高频采样,并需要通过UART从我的Arduino传输10位ADC值。默认情况下,它使用一个字节来表示一个字符。因此,如果进行analogRead会得到值"612",则会通过UART发送"6"作为一个字节,"1"作为一个字节,"2"作为一个字节,最后一个字节为行终止符。由于这种通信方式截断了我的采样率,因此让它尽可能地高效和统一非常重要,因此我试图强制它使用两个字节来传输数据,无论数据实际是什么(默认情况下,传输"23"需要三个字节,传输"883"需要四个字节,传输"1001"需要五个字节)。目前,我正在尝试以下方法,这是我找到的最佳方法:
int a = 600; //Just an example
char high = (char)highByte(a);
char low = (char)lowByte(a);
Serial.print(high);
Serial.println(low);

目前无论值是什么,都会使用三个字节(包括 \n)。是否有更高效的方法?

可以尝试像这样直接打印:

Serial.print(foo, BIN);

完全不起作用。实际上,它为foo的二进制表示中的每个位使用一个字节,这相当愚蠢。


1
不发送换行符?如果您知道数据始终是一对字节,并且不担心丢失一个字节(可以更少地在流中分散同步字节),那么没有理由使用换行符。此外,如果您将数据作为二进制发送,如果其中一个字节恰好是10(与ASCII换行符相同),会发生什么? - Some programmer dude
1
Serial.write() 是处理二进制数据的方法。Serial.print() 函数旨在将值转换为可读的文本。 - Craig
2个回答

11

我可能错过了什么,但为什么你不使用Serial.write(byte)

你可以使用像这样的方法:

void writeIntAsBinary(int value){
    Serial.write(lowByte(value));
    Serial.write(highByte(value));
}

你打算如何处理电脑上的数据?


8
如果你正在通过串行线发送二进制数据,你真的不应该使用类似文本风格的换行符来混淆一切。
另一方面,如果没有某种同步帮助,就很难知道哪个字节是哪个。
但是,由于你只有10位有效负载,却要发送16位数据,所以你可以“做一个UTF-8”,使用一个自由比特来表示“值的起始”。这将需要仅使用每个8位字节的7位负载,但这没问题,因为7 + 7 = 14,远远超过了10。我们可以让第8位意味着“这是一个新的一对字节的高位”:
const int a = 600;
const unsigned char high = ((a >> 7) & 0x7f) | 0x80;
const unsigned char low  = (a & 0x7f);

Serial.print(high);
Serial.print(low);

在上面的例子中,传输的两个字节将是:
high == ((600 >> 7) & 0x7f) | 0x80 == 4 | 0x80 == 0x84
low  == (600 & 0x7f)               == 88       == 0x58

接收方需要反向执行上述步骤:
const int value = ((high & 0x7f) << 7) | low;

这应该是有效的,它使用高字节的最高位先发送,表示这确实是高字节。低字节永远不会设置最高位。


除非低字节也设置了MSB,否则这将无法工作。您只能在低字节上传输7位。 - user694733
我认为应该是 high = ((a >> 7) & 0xff) | 0x80; low = (a & 0x7f); - user694733
@user694733 谢谢!我没有完全考虑清楚,我进行了编辑。 - unwind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接