3

我正在高频采样,需要通过 UART 从我的 Arduino 中传输 10 位 ADC 值。

默认情况下,它使用每个字符一个字节。因此,如果执行模拟读取会产生“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 的二进制表示的每一位都使用一个字节,这很愚蠢。

4

2 回答 2

11

我可能会遗漏一些东西,但你为什么不使用Serial.write(byte)

您可以使用这样的方法:

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

您打算如何处理计算机上的数据?

于 2013-10-10T11:56:21.580 回答
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。

于 2013-10-10T11:00:11.487 回答