Ubuntu下stty配置串口输出的正确方式及数据偏移问题排查
Ubuntu下向Silicon Labs BMG220p发送二进制串口数据的问题解决
问题背景
- 设备:Silicon Labs BMG220p微控制器,USB连接Ubuntu后识别为
/dev/ttyACM0 - 需求:通过bash脚本发送固定32字节的二进制数据
- 异常:首次运行脚本时设备能收到正确的32字节数据,后续每次执行都会出现数据偏移3字节的情况,推测是串口驱动对二进制数据添加了控制字符处理
- 当前使用的脚本:
#! /usr/bin/bash while getopts p: flag do echo -n "$flag: " case ${flag} in p) ttyPort=${OPTARG} echo "Use tty $ttyPort";;; esac done printf "%b" "\x02\x11\x22\x33\x44\x0Akaefer\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x07\x03\x04" > $ttyPort
- 当前
stty -F /dev/ttyACM0输出:
speed 9600 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0; -parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
解决方案
一、修正串口配置(stty)
问题根源在于当前串口处于规范模式(icanon)并启用了软件流控(ixon),驱动会对二进制数据做特殊字符解析和缓存处理。需要将串口切换为原始模式,禁用所有不必要的处理逻辑:
在脚本发送数据前添加以下配置命令:
stty -F $ttyPort raw -echo -ixoff -ixon -icanon isig min 0 time 0
各参数作用:
raw:禁用所有输入输出的转义、翻译处理,直接传递原始二进制数据-echo:禁止回显发送的数据,避免干扰设备接收-ixoff -ixon:禁用XON/XOFF软件流控,防止驱动将\x11、\x13这类二进制字符当成流控命令-icanon:关闭规范模式,禁用行缓存和特殊字符(如回车、EOF)的解析min 0 time 0:设置无最小字符数要求和超时,确保数据立即发送
修改后的完整脚本:
#! /usr/bin/bash while getopts p: flag do echo -n "$flag: " case ${flag} in p) ttyPort=${OPTARG} echo "Use tty $ttyPort";;; esac done # 配置串口为原始模式,禁用所有不必要的处理 stty -F $ttyPort raw -echo -ixoff -ixon -icanon isig min 0 time 0 # 发送二进制数据 printf "%b" "\x02\x11\x22\x33\x44\x0Akaefer\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x07\x03\x04" > $ttyPort
二、使用screen发送二进制数据的方法
如果需要用screen工具在脚本中发送二进制数据,可按以下步骤操作:
- 提前生成包含目标二进制数据的文件:
printf "%b" "\x02\x11\x22\x33\x44\x0Akaefer\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x07\x03\x04" > binary_data.bin
- 在脚本中通过screen后台发送数据:
# 后台启动screen串口会话,配置为原始模式 screen -S serial_send -d -m $ttyPort 9600,raw,-echo,-ixoff,-ixon sleep 0.5 # 等待会话连接稳定 # 向会话发送命令,发送二进制文件内容 screen -S serial_send -X exec !! cat binary_data.bin sleep 0.1 # 等待数据发送完成 # 关闭screen会话 screen -S serial_send -X quit
内容的提问来源于stack exchange,提问作者T.Krastev
相关产品推荐
相关产品推荐

