ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Linux应用 -串口操作库

2026/8/9 19:51:53 拓冰建站 浏览量
Linux应用 -串口操作库

背景

这段代码是一个简单的串口通信库的示例,用于在类Unix操作系统(如Linux)上进行基本的串口通信。它包含了串口的打开、配置、读写操作以及关闭。为了便于理解和后续扩展,代码中的所有函数和结构体都采用了统一的前缀 cm(意为“Customized Module”或“Communication Module”)。该库支持异步读取,即当串口有数据到达时,将通过回调函数处理这些数据。此外,代码中也包括了写操作,用于向串口发送数据。

代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>typedef void (*CM_SERIAL_CALLBACK)(const char *data, int len);typedef struct {int fd;bool active;CM_SERIAL_CALLBACK callback;pthread_t thread_id;
} CM_SERIAL_ARGS_ST;void *cm_serial_listener(void *args) {CM_SERIAL_ARGS_ST *port = (CM_SERIAL_ARGS_ST *)args;char buf[1024];int n;while (port->active) {n = read(port->fd, buf, sizeof(buf));if (n > 0) {port->callback(buf, n);}}return NULL;
}CM_SERIAL_ARGS_ST* cm_serial_open(const char *device, int baudrate, CM_SERIAL_CALLBACK callback) {int fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);if (fd < 0) {perror("Unable to open serial device");return NULL;}struct termios tty;memset(&tty, 0, sizeof tty);if (tcgetattr(fd, &tty) != 0) {perror("Error from tcgetattr");return -1;}cfsetospeed(&tty, baudrate);cfsetispeed(&tty, baudrate);tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit charstty.c_iflag &= ~IGNBRK;                         // disable break processingtty.c_lflag = 0;                                // no signaling chars, no echo, no canonical processingtty.c_oflag = 0;                                // no remapping, no delaystty.c_cc[VMIN]  = 0;                            // read doesn't blocktty.c_cc[VTIME] = 5;                            // 0.5 seconds read timeouttty.c_iflag &= ~(IXON | IXOFF | IXANY);         // shut off xon/xoff ctrltty.c_cflag |= (CLOCAL | CREAD);                // ignore modem controls, enable readingtty.c_cflag &= ~(PARENB | PARODD);              // shut off paritytty.c_cflag |= 0;tty.c_cflag &= ~CSTOPB;tty.c_cflag &= ~CRTSCTS;if (tcsetattr(fd, TCSANOW, &tty) != 0) {perror("Error from tcsetattr");return -1;}CM_SERIAL_ARGS_ST *port = malloc(sizeof(CM_SERIAL_ARGS_ST));port->fd = fd;port->active = true;port->callback = callback;if(pthread_create(&port->thread_id, NULL, &cm_serial_listener, port)) {perror("Failed to create the serial listener thread");close(fd);free(port);return NULL;}return port;
}int cm_serial_write(CM_SERIAL_ARGS_ST *port, const char *data, int len) {return write(port->fd, data, len);
}void cm_serial_close(CM_SERIAL_ARGS_ST *port) {if (port) {port->active = false;pthread_join(port->thread_id, NULL);close(port->fd);free(port);}
}void cm_callback(const char *data, int len) {printf("Received data: ");fwrite(data, 1, len, stdout);printf("\n");
}int main() {CM_SERIAL_ARGS_ST *port = cm_serial_open("/dev/ttyS0", B9600, cm_callback);if (port == NULL) exit(1);// 示例写操作const char *message = "Hello, Serial Port!";int bytes_written = cm_serial_write(port, message, strlen(message));if (bytes_written >= 0) {printf("Sent: %s\n", message);} else {perror("Failed to write to serial port");}// 当需要关闭串口时cm_serial_close(port);return 0;
}