答案1
如果您希望字节按原样通过串行连接双向传输,则需要告诉系统它不要用作终端设备,方法是从系统中分离 tty 线路规则或发出:
stty raw -echo < /dev/ttyS2
在您的情况下,正是onlcr
tty 设备上默认启用的属性导致输出上的 LF 到 CRLF 转换。您可以禁用全部输出处理包括ocrnl
with stty -opost
,但这留下了在另一个方向传输的数据的所有输入处理。
您没有指示您正在使用哪个 shellecho
或printf
实现,但请注意 ,-n
选项-e
不是标准的,并且参数包含的行为printf
或何时的行为未指定。echo
\x
printf
其格式参数的几种实现扩展\xHH
为值 0xHH 的字节。
在那些
printf "\xAA\xEE\x0A\x%02x" $i
将扩展\xAA
为字节 0xAA,而 for\x
会将其扩展为字节 0 或按\x
字面意思或抱怨十六进制数字丢失。例如,你最终会得到<0xaa><0xee><LF>\x01
in 。$a
有些echo
实现也解释\xHH
序列(有些仅在传递-e
选项时)。
在这里,如果你想便携,你会这样做:
a=$(printf '\\252\\356\\012\\%03o' "$i")
printf "$a" > /dev/ttyS2
或者:
a=$(printf '\\0252\\0356\\0012\\0%03o' "$i")
printf %b "$a" > /dev/ttyS2
(标准printf
支持\ooo
格式中的八进制序列,以及一种%b
旨在模拟某些echo
实现使用或不使用 进行的扩展类型的格式-e
,并且八进制序列表示为\0ooo
)。
您还想确保第一个printf
不输出 NUL 字节,因为除了 之外,shell 不能在其变量中存储 NUL 字节(例如zsh
不要这样做)。a=$(printf '\0 or \x00 or \u0000')
和zsh
:
bytes=(0xaa 0xee 0x0a $i)
set +o multibyte
printf %s ${(#)bytes} > /dev/ttyS2
该数据可以通过以下任一方式存储在变量中:
printf -v data %s ${(#)bytes}
或者
data=${(#j[])bytes}
但更一般地说,如果您想使用任意字节值操作数据,您可能需要使用适当的编程语言,即使它是像perl
或 之 类的解释型语言python
。
另一种方法是使用类似的工具xxd
可以在二进制形式和文本十六进制转储之间来回转换。
printf aaee0a%02d "$i" | xxd -p -r > /dev/ttyS1