使用 0xA 数据将原始数据发送到串行

使用 0xA 数据将原始数据发送到串行

我尝试向串口发送某人字符串echo -ne '\x55\x90\x17\x01\x00' > /dev/ttyACM0,USB监控向我显示以下数据:

ffff8c957536f540 2932377867 S Bo:2:005:3 -115 5 = 55901701 00

这工作正常,所有数据都以一个字符串形式发送,设备接受命令。但如果数据包含 0xA,它总是将数据分成 2 行。例如:

echo -ne '\x55\x90\xa\x01\xde' > /dev/ttyACM0

USB 监控显示给我这个:

ffff8c957536f540 3046024649 S Bo:2:005:3 -115 3 = 55900a
ffff8c957b719000 3046024661 S Bo:2:005:3 -115 2 = 01de

string 被分割成 2 行,当然设备已经忽略了这个命令。

我的问题是,如何发送包含 0xA 的任何数据。这与stty有问题,我花了很多时间但仍然没有成功。或者请确认,这不可能将字符串中间的 0xA 从 Linux 控制台发送到串行端口。

答案1

这看起来很像Bash 邮件列表中讨论的问题在过去的几天里。 Bash 使用行缓冲进行输出,因此中间包含换行符的printfor会为每个“行”调用系统调用。echowrite()

$ strace -ewrite bash -c 'echo -ne "foobar"' >/dev/null 
write(1, "foobar", 6)                   = 6
+++ exited with 0 +++

$ strace -ewrite bash -c 'echo -ne "foo\nbar\n"' >/dev/null 
write(1, "foo\n", 4)                    = 4
write(1, "bar\n", 4)                    = 4
+++ exited with 0 +++

如果您要写入的设备对此很敏感,则可能会导致后续线路出现多个不同的数据包。串行连接或 TCP 流(*)不应该关心这个问题,但更像 UDP 数据包的东西会关心这个问题。

看来您无法在 Bash 中解决此问题,但您可以使用其他一些实用程序,这些实用程序不会将输出拆分为单个输出命令中间的行。我测试的所有其他 shell 在一次调用中打印上述内容, GNU coreutils 的write()外部实用程序也是如此。printf它应该在/usr/bin/printfLinux 上,所以/usr/bin/printf '\x55\x90\xa\x01\xde'应该可以工作:

$ strace -f -ewrite /usr/bin/printf '\x55\x90\xa\x01\xde' >/dev/null 
write(1, "U\220\n\1\336", 5)            = 5
+++ exited with 0 +++

或者,您可以通过管道输出dd,默认情况下,它会将输出缓冲到 512 块(除了最后一个块),这对于您的情况来说应该足够了。 (dd obs=512要明确这一点。)

(* TCP 连接不应该关心,但邮件列表上的问题正是关于printf ... > /dev/tcp/...。不同的写入可能会影响 TCP 流的分段,显然一些有缺陷的主机关心这一点。)

答案2

这并不意味着数据被“分成”两行。

简而言之,您正在正确地写入数据,这就是您显示数据的方式,看起来您有“两行”。

0xA 是 ascii“换行”字符,即 Unix/Linux“换行”字符('\n')。

当您查看来自 USB 监视器的数据时,终端(或 Unix/Linux 中的几乎所有其他文本显示软件)会将显示移动到下一个“行”。在大多数终端上,这意味着显示驱动程序将插入回车符和换行符。

验证数据的更好方法是从 USB 监视器捕获数据并将其传送到命令od,并可以选择查看十六进制字符( od -t x1)。然后您应该看到您写入的实际数据。

答案3

某些 tty 设备保持 LF 到 CRLF 转换输出打开。您可以使用以下方法禁用它:

stty -onlcr -F /dev/ttyACM0

或者,对于严格的 POSIX 停留

stty -onlcr < -F /dev/ttyACM0

或者纯RAW模式尝试:

stty raw -echo -F /dev/ttyACM0

然后尝试

echo -ne '\x55\x90\xa\x01\xde' > /dev/ttyACM0

相关内容