Linux应用 -串口操作库

本文介绍了一个C语言编写的串口通信库,支持Linux等类Unix系统,包含串口的打开、配置、异步读取和写操作,以及线程安全的关闭功能。示例展示了如何使用该库进行串口通信和数据接收。
摘要由CSDN通过智能技术生成

背景

这段代码是一个简单的串口通信库的示例,用于在类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 chars
    tty.c_iflag &= ~IGNBRK;                         // disable break processing
    tty.c_lflag = 0;                                // no signaling chars, no echo, no canonical processing
    tty.c_oflag = 0;                                // no remapping, no delays
    tty.c_cc[VMIN]  = 0;                            // read doesn't block
    tty.c_cc[VTIME] = 5;                            // 0.5 seconds read timeout

    tty.c_iflag &= ~(IXON | IXOFF | IXANY);         // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);                // ignore modem controls, enable reading
    tty.c_cflag &= ~(PARENB | PARODD);              // shut off parity
    tty.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;
}

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值