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串口参数,可以根据具体需求进行组合和调整。

相关推荐
wdfk_prog2 小时前
[Linux]学习笔记系列 -- [fs]file_table
linux·笔记·学习
乾元2 小时前
LLM 自动生成安全基线与等保合规初稿——把“网络工程事实”转译为“可审计的制度语言”
运维·网络·人工智能·python·安全·架构
大连好光景2 小时前
WSL下创建的Ubuntu系统与Windows实现显卡直通
linux·运维·ubuntu
huangjiazhi_2 小时前
Ubuntu 添加服务自启动
linux·运维·ubuntu
wqfhenanxc2 小时前
vscode/cursor 远程Linux基础命令
linux·ide·vscode
吴爃2 小时前
N8N调用系统接口进行AI分析
运维·人工智能·ai
Zeku2 小时前
20251130 - 详细解析Framebuffer应用编程中涉及到的API函数
linux·驱动开发·嵌入式软件·linux应用开发
保卫大狮兄2 小时前
TPM 到底用在设备管理的哪个阶段?
大数据·运维
Xの哲學2 小时前
Linux AQM 深度剖析: 拥塞控制
linux·服务器·算法·架构·边缘计算