当时写这个的初衷是因为在调试Linux系统 , 串口测试费劲 通过echo/cat 有些功能受限制。
所以就搞了个测试程序 , Android可以不用这个 , 大把的测试工具。
程序功能介绍
这个程序是用来实现串口通信的。它接受三个参数,分别是通信模式(232或485)、串口设备名和波特率。它会根据参数的设置,打开指定的串口,并设置相应的属性。然后,它会创建一个子进程,用于从串口读取数据,并在标准输出上显示。父进程则用于从标准输入读取用户输入的内容,并发送到串口。用户可以输入文本或十六进制字符串,程序会自动识别并转换成字节序列。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <termios.h> #include <unistd.h> #define MODE_232 1 #define MODE_485 2 int open_serial_port(const char *port, int baud_rate, int mode) { struct termios tty; memset(&tty, 0, sizeof(tty)); int fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) { perror("open"); return -1; } if (tcgetattr(fd, &tty) != 0) { perror("tcgetattr"); close(fd); return -1; } cfsetospeed(&tty, baud_rate); cfsetispeed(&tty, baud_rate); // 设置控制模式(本地连接,接受使能) tty.c_cflag |= (CLOCAL | CREAD); // 设置数据位 tty.c_cflag &= ~CSIZE; tty.c_cflag |= CS8; // 设置奇偶校验位 tty.c_cflag &= ~PARENB; tty.c_iflag &= ~INPCK; // 设置停止位数 tty.c_cflag &= ~CSTOPB; // 设置等待时间和最小字符数(对应VTIME和VMIN两个参数),这里设为 10 秒和 0 个字符 tty.c_cc[VTIME] = 100; tty.c_cc[VMIN] = 0; if (mode == MODE_485) { // 设置为RS485模式 tty.c_cflag |= CRTSCTS | CLOCAL; tty.c_iflag &= ~(IXON | IXOFF | IXANY); } else if (mode == MODE_232) { // 设置为RS232模式 tty.c_cflag &= ~CRTSCTS; tty.c_iflag |= (IXON | IXOFF | IXANY); } // 清空输入输出缓冲区 tcflush(fd, TCIOFLUSH); if (tcsetattr(fd, TCSANOW, &tty) != 0) { perror("tcsetattr"); close(fd); return -1; } return fd; } void read_serial_port(int fd) { char buf[256]; int n; while (1) { memset(buf, 0, sizeof(buf)); n = read(fd, buf, sizeof(buf)); if (n > 0) { printf("读到: %s", buf); } } } void write_serial_port(int fd) { char buf[256]; int n; while (1) { printf("请输入发送内容:"); fgets(buf, sizeof(buf), stdin); n = strlen(buf); if (n > 0) { // 去掉最后的换行符 if (buf[n-1] == '\n') { buf[n-1] = '\0'; n--; } // 判断输入的字符串是否是十六进制格式 int is_hex = 1; int i; for (i = 0; i < n; i++) { if ((buf[i] >= '0' && buf[i] <= '9') || (buf[i] >= 'a' && buf[i] <= 'f') || (buf[i] >= 'A' && buf[i] <= 'F')) { continue; } else if (buf[i] == ' ') { continue; } else { is_hex = 0; break; } } if (is_hex) { // 将输入的十六进制字符串转换成字节序列 unsigned char data[128]; int j = 0; for (i = 0; i < n; i++) { if (buf[i] == ' ') { continue; } sscanf(&buf[i], "%02X", &data[j]); j++; i++; } n = j; if (n > 0) { n = write(fd, data, n); if (n < 0) { perror("write"); } else { printf("hex发送成功\n"); } } } else { // 直接将输入的文本发送到串口 n = write(fd, buf, n); if (n < 0) { perror("write"); } else { printf("txt发送成功\n"); } } } } } int main(int argc, char *argv[]) { if (argc != 4) { printf("Usage: %s [mode] [serial port] [baud rate]\n", argv[0]); return 1; } int mode; if (strcmp(argv[1], "232") == 0) { mode = MODE_232; } else if (strcmp(argv[1], "485") == 0) { mode = MODE_485; } else { printf("Invalid mode: %s\n", argv[1]); return 1; } const char *port = argv[2]; int baud_rate = atoi(argv[3]); int fd = open_serial_port(port, baud_rate, mode); if (fd < 0) { fprintf(stderr, "Failed to open serial port %s with baud rate %d\n", port, baud_rate); return 1; } printf("Serial port %s opened successfully with baud rate %d and mode %d\n", port, baud_rate, mode); pid_t pid = fork(); if (pid == 0) { // 子进程用于读取数据 read_serial_port(fd); } else if (pid > 0) { // 父进程用于写数据 write_serial_port(fd); } else { perror("fork"); return 1; } close(fd); return 0; }
使用示例
要编译这个程序,需要在终端中输入:
./gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc -o serial serial.c
要运行这个程序,需要在终端中输入:
./serial [mode] [serial port] [baud rate]
例如:
./serial 232 /dev/ttyUSB0 115200 # 使用RS232模式打开/dev/ttyUSB0串口,并设置波特率为115200 ./serial 485 /dev/ttyS0 9600 # 使用RS485模式打开/dev/ttyS0串口,并设置波特率为9600
然后就可以看到类似下面的输出:
Serial port /dev/ttyUSB0 opened successfully with baud rate 115200 and mode 232 请输入发送内容:Hello world! txt发送成功 读到: Hello world! 请输入发送内容:01 02 03 04 05 hex发送成功 读到: 01 02 03 04 05