在嵌入式开发、工业控制以及通信调试等领域,Linux 系统下的串口通信是一项基础且重要的技能,当需要传输或调试二进制数据时,16 进制格式的处理显得尤为关键,本文将详细介绍在 Linux 环境下进行串口 16 进制通信的相关知识,包括串口配置、16 进制数据的收发方法以及常见问题的解决方案。

Linux 串口通信基础
Linux 系统将串口设备抽象为字符设备文件,通常位于 /dev/ 目录下,如 /dev/ttyS0(COM1)、/dev/ttyUSB0(USB 转串口)等,在进行串口通信前,需要确保当前用户对设备文件具有读写权限,可通过 chmod 命令或加入 dialout 用户组解决。
串口通信的核心参数包括波特率、数据位、停止位、校验位和流控,这些参数需要收发双方保持一致,否则会导致数据解析错误,在 Linux 中,可通过 stty 命令快速配置串口参数,例如设置 /dev/ttyUSB0 的波特率为 115200、8 位数据位、1 位停止位、无校验位:
stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb
还可使用 minicom、screen 等终端工具进行简单的串口调试,这些工具支持基本的字符收发,但在处理 16 进制数据时功能有限,因此需要更专业的工具或编程方法。
16 进制数据的表示与转换
16 进制(Hexadecimal)是计算机中常用的数据表示方法,基数为 16,使用 0-9 和 A-F(或 a-f)共 16 个字符,在串口通信中,16 进制数据常用于表示二进制文件、传感器数据或协议帧,字节 0x41 对应 ASCII 字符 ‘A’,而 0x00 表示空字节。
在 Linux 下进行 16 进制数据处理时,常使用 xxd、hexdump 等命令行工具。xxd 可将二进制文件转换为 16 进制格式,也可反向转换:
# 将文件转换为 16 进制显示 xxd -g 1 file.bin # 将 16 进制文件转换回二进制 xxd -r -p file.hex > file.bin
hexdump 则以更灵活的格式显示数据,支持自定义偏移量和显示格式:

hexdump -C file.bin # 显示 ASCII 字符和偏移量
这些工具在调试串口数据时非常有用,可将接收到的原始字节流转换为可读的 16 进制格式,便于分析数据结构。
使用 C 语言进行串口 16 进制收发
在应用程序中处理串口 16 进制数据,通常需要结合系统调用和字符串解析,以下是使用 C 语言实现串口 16 进制发送与接收的基本步骤:
打开串口设备
使用 open() 函数打开串口设备文件,需设置 O_RDWR(读写模式)和 O_NOCTTY(不将终端作为控制终端)等标志:
int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd < 0) {
perror("Failed to open serial port");
exit(1);
}
配置串口参数
通过 termios 结构体配置串口参数,包括波特率、数据位、停止位等:
struct termios options; tcgetattr(fd, &options); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag |= (CLOCAL | CREAD); tcsetattr(fd, TCSANOW, &options);
16 进制字符串转换为二进制数据
发送 16 进制字符串(如 “A1 02 3F”)时,需先将其转换为二进制字节流,可通过逐字符解析实现:
void hex_to_bin(const char *hex, unsigned char *bin, int *len) {
*len = 0;
char *p = (char *)hex;
while (*p) {
if (isspace(*p)) {
p++;
continue;
}
unsigned char high = (*p >= 'A' && *p <= 'F') ? (*p - 'A' + 10) : (*p - '0');
p++;
if (!*p) break;
unsigned char low = (*p >= 'A' && *p <= 'F') ? (*p - 'A' + 10) : (*p - '0');
bin[(*len)++] = (high << 4) | low;
p++;
}
}
发送与接收数据
使用 write() 和 read() 函数进行数据收发,发送时直接写入转换后的二进制数据,接收时需处理原始字节流并转换为 16 进制格式显示:

// 发送 16 进制数据
const char *hex_data = "A1 02 3F";
unsigned char bin_data[256];
int bin_len;
hex_to_bin(hex_data, bin_data, &bin_len);
write(fd, bin_data, bin_len);
// 接收数据并显示为 16 进制
unsigned char recv_buf[256];
int recv_len = read(fd, recv_buf, sizeof(recv_buf));
for (int i = 0; i < recv_len; i++) {
printf("%02X ", recv_buf[i]);
}
使用 Python 进行串口 16 进制处理
Python 提供了 pyserial 库,简化了串口操作,安装后可通过以下代码实现 16 进制收发:
import serial
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
# 发送 16 进制数据
hex_data = "A1 02 3F"
ser.write(bytes.fromhex(hex_data))
# 接收数据并显示为 16 进制
recv_data = ser.read(ser.in_waiting or 1)
print('Received:', ' '.join(f'{b:02X}' for b in recv_data))
ser.close()
bytes.fromhex() 方法可直接将 16 进制字符串转换为字节对象,接收到的数据可通过 hex() 方法或格式化输出为 16 进制格式。
常见问题与注意事项
- 数据对齐问题:16 进制字符串需确保每两位对应一个字节,避免奇数长度导致解析错误。
- 波特率匹配:收发双方的波特率、数据位等参数必须严格一致,否则会出现乱码或数据丢失。
- 超时设置:合理设置串口超时时间,避免程序因等待数据而阻塞。
- 权限问题:确保用户对串口设备具有访问权限,可通过
ls -l /dev/ttyUSB*检查权限。 - 流控处理:在高速或远距离通信时,可能需要启用硬件流控(RTS/CTS)或软件流控(XON/XOFF)。
Linux 系统下的串口 16 进制通信是嵌入式开发中的重要环节,通过 stty、xxd 等工具可快速进行调试,而 C 语言和 Python 则提供了灵活的编程接口,掌握串口配置、16 进制数据转换及收发方法,能够有效解决实际开发中的数据传输问题,在实际应用中,还需结合具体协议需求,确保数据传输的准确性和可靠性。



















