Linux shell中设置串口参数

Linux shell中设置串口参数

在Linux shell中,可以使用多种工具和命令来配置串口参数,主要包括sttysetserialioctl系统调用。

1. 使用stty命令

stty是最常用的终端配置工具,可以设置串口参数。

基本语法

bash 复制代码
stty -F <设备文件> <参数>

常用参数设置

设置波特率
bash 复制代码
# 设置波特率为115200
stty -F /dev/ttyS0 115200

# 设置波特率为9600
stty -F /dev/ttyUSB0 9600
设置数据位、停止位、校验位
bash 复制代码
# 8位数据位,1位停止位,无校验
stty -F /dev/ttyS0 cs8 -cstopb -parenb

# 7位数据位,1位停止位,偶校验
stty -F /dev/ttyS0 cs7 -cstopb parenb -parodd

# 7位数据位,2位停止位,奇校验
stty -F /dev/ttyS0 cs7 cstopb parenb parodd
设置流控制
bash 复制代码
# 启用硬件流控制(RTS/CTS)
stty -F /dev/ttyS0 crtscts

# 禁用硬件流控制
stty -F /dev/ttyS0 -crtscts

# 启用软件流控制(XON/XOFF)
stty -F /dev/ttyS0 ixon ixoff

# 禁用软件流控制
stty -F /dev/ttyS0 -ixon -ixoff
其他重要设置
bash 复制代码
# 设置原始模式(禁用所有处理)
stty -F /dev/ttyS0 raw

# 设置规范模式(启用行编辑)
stty -F /dev/ttyS0 -raw

# 禁用回显
stty -F /dev/ttyS0 -echo

# 启用回显
stty -F /dev/ttyS0 echo

# 设置最小读取字符数和超时(非规范模式)
stty -F /dev/ttyS0 min 0 time 10  # 0个字符,1秒超时
stty -F /dev/ttyS0 min 1 time 0   # 至少1个字符,无超时
查看当前设置
bash 复制代码
# 查看所有设置
stty -F /dev/ttyS0 -a

# 查看特定设置
stty -F /dev/ttyS0

完整配置示例

bash 复制代码
#!/bin/bash
# 配置串口为115200波特率,8N1,无流控制,原始模式
SERIAL_PORT="/dev/ttyUSB0"
BAUDRATE="115200"

# 配置基本参数
stty -F $SERIAL_PORT $BAUDRATE cs8 -cstopb -parenb
stty -F $SERIAL_PORT -crtscts -ixon -ixoff

# 设置原始模式,禁用回显
stty -F $SERIAL_PORT raw -echo

# 设置非阻塞读取
stty -F $SERIAL_PORT -icanon min 0 time 0

echo "串口 $SERIAL_PORT 已配置为 $BAUDRATE 8N1"

2. 使用setserial命令

setserial用于设置串口硬件参数,通常需要root权限。

基本语法

bash 复制代码
setserial <设备文件> [参数]

常用参数

bash 复制代码
# 查看串口信息
setserial -g /dev/ttyS[0-3]

# 设置UART类型
setserial /dev/ttyS0 uart 16550A

# 设置I/O端口地址
setserial /dev/ttyS0 port 0x3f8

# 设置IRQ
setserial /dev/ttyS0 irq 4

# 设置自动配置
setserial /dev/ttyS0 autoconfig

# 保存设置
setserial /dev/ttyS0 -a

3. 使用ioctl系统调用(C程序)

通过C程序直接调用ioctl系统调用设置串口参数。

示例程序

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>

int set_serial_port(const char *port, speed_t baudrate) {
    int fd;
    struct termios options;
    
    // 打开串口
    fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd < 0) {
        perror("无法打开串口");
        return -1;
    }
    
    // 获取当前设置
    if (tcgetattr(fd, &options) < 0) {
        perror("获取串口设置失败");
        close(fd);
        return -1;
    }
    
    // 设置输入输出波特率
    cfsetispeed(&options, baudrate);
    cfsetospeed(&options, baudrate);
    
    // 8N1设置
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    
    // 无硬件流控制
    options.c_cflag &= ~CRTSCTS;
    
    // 启用接收器,忽略调制解调器状态
    options.c_cflag |= (CLOCAL | CREAD);
    
    // 原始输入
    options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
                        | INLCR | IGNCR | ICRNL | IXON);
    
    // 原始输出
    options.c_oflag = 0;
    
    // 无本地处理
    options.c_lflag = 0;
    
    // 非规范模式,立即返回
    options.c_cc[VTIME] = 0;
    options.c_cc[VMIN] = 0;
    
    // 应用设置
    if (tcsetattr(fd, TCSANOW, &options) < 0) {
        perror("设置串口参数失败");
        close(fd);
        return -1;
    }
    
    // 清空缓冲区
    tcflush(fd, TCIOFLUSH);
    
    return fd;
}

4. 使用Python(pyserial库)

python 复制代码
#!/usr/bin/env python3
import serial
import serial.tools.list_ports

# 配置串口参数
ser = serial.Serial(
    port='/dev/ttyUSB0',      # 串口设备
    baudrate=115200,          # 波特率
    bytesize=serial.EIGHTBITS, # 数据位:8
    parity=serial.PARITY_NONE, # 校验位:无
    stopbits=serial.STOPBITS_ONE, # 停止位:1
    timeout=1,                # 读取超时(秒)
    xonxoff=False,            # 软件流控制
    rtscts=False,             # 硬件流控制
    dsrdtr=False              # DSR/DTR流控制
)

# 或者逐个设置
ser = serial.Serial()
ser.port = '/dev/ttyS0'
ser.baudrate = 9600
ser.bytesize = serial.SEVENBITS
ser.parity = serial.PARITY_EVEN
ser.stopbits = serial.STOPBITS_TWO
ser.timeout = 0.5
ser.xonxoff = True
ser.rtscts = False
ser.open()

# 列出可用串口
ports = serial.tools.list_ports.comports()
for port in ports:
    print(f"{port.device}: {port.description}")

5. Shell脚本示例

完整的串口配置脚本

bash 复制代码
#!/bin/bash
# serial_config.sh

# 配置参数
PORT=${1:-"/dev/ttyUSB0"}
BAUD=${2:-115200}
DATABITS=${3:-8}
PARITY=${4:-"none"}
STOPBITS=${5:-1}
FLOW=${6:-"none"}

# 校验位映射
case $PARITY in
    "none") PARITY_FLAGS="-parenb" ;;
    "odd") PARITY_FLAGS="parenb parodd" ;;
    "even") PARITY_FLAGS="parenb -parodd" ;;
    *) echo "无效的校验位: $PARITY"; exit 1 ;;
esac

# 数据位映射
case $DATABITS in
    5) DATABIT_FLAGS="cs5" ;;
    6) DATABIT_FLAGS="cs6" ;;
    7) DATABIT_FLAGS="cs7" ;;
    8) DATABIT_FLAGS="cs8" ;;
    *) echo "无效的数据位: $DATABITS"; exit 1 ;;
esac

# 停止位映射
if [ "$STOPBITS" = "2" ]; then
    STOPBIT_FLAGS="cstopb"
else
    STOPBIT_FLAGS="-cstopb"
fi

# 流控制映射
case $FLOW in
    "none") FLOW_FLAGS="-crtscts -ixon -ixoff" ;;
    "hardware") FLOW_FLAGS="crtscts -ixon -ixoff" ;;
    "software") FLOW_FLAGS="-crtscts ixon ixoff" ;;
    *) echo "无效的流控制: $FLOW"; exit 1 ;;
esac

# 检查设备是否存在
if [ ! -c "$PORT" ]; then
    echo "错误: 设备 $PORT 不存在"
    exit 1
fi

# 应用设置
echo "配置串口 $PORT:"
echo "  波特率: $BAUD"
echo "  数据位: $DATABITS"
echo "  校验位: $PARITY"
echo "  停止位: $STOPBITS"
echo "  流控制: $FLOW"

stty -F $PORT $BAUD $DATABIT_FLAGS $STOPBIT_FLAGS $PARITY_FLAGS $FLOW_FLAGS raw -echo -icanon

# 验证设置
echo -e "\n当前设置:"
stty -F $PORT -a | grep -E "speed|cs[0-9]|parenb|parodd|cstopb|crtscts|ixon|ixoff"

# 设置权限(可选)
# sudo chmod 666 $PORT

交互式串口配置脚本

bash 复制代码
#!/bin/bash
# interactive_serial_config.sh

# 列出可用串口
echo "可用串口:"
ls /dev/ttyS* /dev/ttyUSB* /dev/ttyACM* 2>/dev/null

# 选择串口
read -p "输入串口设备: " PORT

# 选择波特率
echo "常用波特率:"
echo "1) 9600"
echo "2) 19200"
echo "3) 38400"
echo "4) 57600"
echo "5) 115200"
echo "6) 230400"
echo "7) 自定义"
read -p "选择波特率 [1-7]: " BAUD_CHOICE

case $BAUD_CHOICE in
    1) BAUD=9600 ;;
    2) BAUD=19200 ;;
    3) BAUD=38400 ;;
    4) BAUD=57600 ;;
    5) BAUD=115200 ;;
    6) BAUD=230400 ;;
    7) read -p "输入自定义波特率: " BAUD ;;
    *) BAUD=115200 ;;
esac

# 应用配置
stty -F $PORT $BAUD cs8 -cstopb -parenb -crtscts raw -echo

echo "串口 $PORT 已配置为 $BAUD 8N1"
echo "按Ctrl+C退出"

# 简单终端
cat $PORT &
CAT_PID=$!
trap "kill $CAT_PID 2>/dev/null" EXIT

while true; do
    read -p "> " INPUT
    echo -e "$INPUT" > $PORT
done

6. 其他实用命令

查看串口信息

bash 复制代码
# 查看所有串口设备
dmesg | grep tty

# 查看串口详细信息
udevadm info -a -n /dev/ttyS0

# 查看串口驱动信息
cat /proc/tty/driver/serial

设置权限

bash 复制代码
# 添加用户到dialout组
sudo usermod -a -G dialout $USER

# 临时更改权限
sudo chmod 666 /dev/ttyUSB0

# 永久设置udev规则
echo 'KERNEL=="ttyUSB*", MODE="0666"' | sudo tee /etc/udev/rules.d/50-usb-serial.rules
sudo udevadm control --reload-rules

测试串口

bash 复制代码
# 发送测试数据
echo "test" > /dev/ttyS0

# 接收数据(显示十六进制)
cat -v < /dev/ttyS0

# 十六进制转储
od -x < /dev/ttyS0

# 使用screen作为简单终端
screen /dev/ttyS0 115200

7. 常见问题解决

权限问题

bash 复制代码
# 检查当前用户组
groups

# 添加用户到dialout组
sudo gpasswd -a $USER dialout
# 需要重新登录生效

设备忙问题

bash 复制代码
# 查看占用进程
lsof /dev/ttyS0

# 强制释放设备
fuser -k /dev/ttyS0

保存和恢复设置

bash 复制代码
# 保存当前设置
stty -F /dev/ttyS0 -g > serial_settings.txt

# 恢复设置
stty -F /dev/ttyS0 $(cat serial_settings.txt)

这些shell命令和脚本提供了灵活的方式来配置Linux串口参数,可以根据具体需求进行组合和调整。

相关推荐
Sumlll_2 小时前
Ubuntu系统下QEMU的安装与RISC-V的测试
linux·ubuntu·risc-v
猫头虎2 小时前
2025最新OpenEuler系统安装MySQL的详细教程
linux·服务器·数据库·sql·mysql·macos·openeuler
木子.李3472 小时前
ssh连接远程服务器相关总结
运维·服务器·ssh
晚风吹人醒.4 小时前
SSH远程管理及访问控制
linux·运维·ssh·scp·xshell·访问控制·远程管理
Uncertainty!!5 小时前
Linux多用户情况下个别用户输入密码后黑屏
linux·远程连接
necessary6535 小时前
使用Clion查看linux环境中的PG源码
linux·运维·服务器
江湖有缘6 小时前
Jump个人仪表盘Docker化部署教程:从0到 搭建专属导航页
运维·docker·容器
小猪佩奇TONY6 小时前
Linux 内核学习(14) --- linux x86-32 虚拟地址空间
linux·学习
Lam㊣6 小时前
Centos 7 系统docker:更换镜像源
linux·docker·centos
FL16238631297 小时前
win11+WSL+Ubuntu-xrdp+远程桌面闪退+黑屏闪退解决
linux·运维·ubuntu