最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux下利用select實(shí)現(xiàn)串口數(shù)據(jù)讀取過程

 更新時間:2025年09月29日 11:31:02   作者:luoqice  
文章介紹Linux中使用select、poll或epoll實(shí)現(xiàn)串口數(shù)據(jù)讀取,通過I/O多路復(fù)用機(jī)制在數(shù)據(jù)到達(dá)時觸發(fā)讀取,避免持續(xù)輪詢,示例代碼展示設(shè)置串口參數(shù)及select檢測數(shù)據(jù)流程

在 Linux 系統(tǒng)里,我們可以借助 select、poll 或者 epoll 這些 I/O 多路復(fù)用機(jī)制達(dá)成串口數(shù)據(jù)讀取的觸發(fā)方式。

這些機(jī)制能夠讓程序在特定文件描述符(像串口設(shè)備文件描述符)有數(shù)據(jù)可讀時得到通知,進(jìn)而進(jìn)行數(shù)據(jù)讀取操作,而不是像輪詢方式那樣持續(xù)調(diào)用 read 函數(shù)。

示例代碼(使用select實(shí)現(xiàn))

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/select.h>

// 設(shè)置串口波特率
void SetSpeed(int fd, int speed) {
    struct termios options;
    tcgetattr(fd, &options);
    switch (speed) {
        case 115200:
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
        // 可以添加更多波特率設(shè)置
        default:
            cfsetispeed(&options, B115200);
            cfsetospeed(&options, B115200);
            break;
    }
    tcsetattr(fd, TCSANOW, &options);
}

// 設(shè)置串口參數(shù)
void SetParity(int fd, int databits, int stopbits, char parity) {
    struct termios options;
    tcgetattr(fd, &options);

    // 設(shè)置數(shù)據(jù)位
    options.c_cflag &= ~CSIZE;
    switch (databits) {
        case 7:
            options.c_cflag |= CS7;
            break;
        case 8:
            options.c_cflag |= CS8;
            break;
        default:
            options.c_cflag |= CS8;
            break;
    }

    // 設(shè)置奇偶校驗(yàn)位
    switch (parity) {
        case 'n':
        case 'N':
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~PARODD;
            break;
        case 'o':
        case 'O':
            options.c_cflag |= (PARODD | PARENB);
            break;
        case 'e':
        case 'E':
            options.c_cflag |= PARENB;
            options.c_cflag &= ~PARODD;
            break;
        default:
            options.c_cflag &= ~PARENB;
            options.c_cflag &= ~PARODD;
            break;
    }

    // 設(shè)置停止位
    switch (stopbits) {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            options.c_cflag &= ~CSTOPB;
            break;
    }

    tcsetattr(fd, TCSANOW, &options);
}

int main(void) {
    int fd;
    unsigned char buf[300];
    unsigned short len;
    fd = open("/dev/ttyS1", O_RDWR);
    if (fd == -1) {
        perror("can't open serial\n");
        return -1;
    }

    SetParity(fd, 8, 1, 'n');
    SetSpeed(fd, 115200);

    fd_set readfds;
    struct timeval timeout;

    while (1) {
        // 清空文件描述符集
        FD_ZERO(&readfds);
        // 將串口文件描述符加入讀文件描述符集
        FD_SET(fd, &readfds);

        // 設(shè)置超時時間
        timeout.tv_sec = 0;
        timeout.tv_usec = 20000;

        // 調(diào)用 select 函數(shù)等待事件發(fā)生
        int activity = select(fd + 1, &readfds, NULL, NULL, &timeout);

        if (activity < 0) {
            perror("select error");
            break;
        } else if (activity > 0) {
            // 檢查是否是串口文件描述符有數(shù)據(jù)可讀
            if (FD_ISSET(fd, &readfds)) {
                len = read(fd, buf, 100);
                if (len > 0) {
                    write(fd, buf, len);
                }
            }
        }
    }

    close(fd);
    return 0;
}

代碼解釋

SetSpeed 函數(shù)

  • 此函數(shù)用于設(shè)置串口的波特率,
  • 它借助 tcsetattr 函數(shù)來配置串口的輸入和輸出波特率

SetParity 函數(shù)

  • 該函數(shù)用于設(shè)置串口的數(shù)據(jù)位、停止位和奇偶校驗(yàn)位
  • 同樣是通過 tcsetattr 函數(shù)來完成串口參數(shù)的配置

main 函數(shù)

  • 打開串口設(shè)備文件 /dev/ttyS1,并且設(shè)置串口參數(shù)。
  • 構(gòu)建一個 fd_set 類型的文件描述符集 readfds,把串口文件描述符 fd 添加到該集合中。
  • 設(shè)定一個超時時間 timeout,防止 select 函數(shù)一直阻塞。
  • 調(diào)用 select 函數(shù)等待事件發(fā)生,若有數(shù)據(jù)可讀,select 函數(shù)會返回大于 0 的值。
  • 利用 FD_ISSET 宏檢查是否是串口文件描述符有數(shù)據(jù)可讀,若有則調(diào)用 read 函數(shù)讀取數(shù)據(jù),然后將數(shù)據(jù)回寫到串口。

通過這種方式,程序就無需持續(xù)輪詢 read 函數(shù),而是在有數(shù)據(jù)到達(dá)時才進(jìn)行讀取操作。

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Apache Prefork、Worker和Event三種MPM詳解

    Apache Prefork、Worker和Event三種MPM詳解

    這篇文章主要介紹了Apache Prefork、Worker和Event三種MPM詳解,著重介紹了配置參數(shù)部分,需要的朋友可以參考下
    2014-06-06
  • Ubuntu 系統(tǒng)中文顯示亂碼的問題解決

    Ubuntu 系統(tǒng)中文顯示亂碼的問題解決

    最近在工作中發(fā)現(xiàn)在Ubuntu 系統(tǒng)中出現(xiàn)中文亂碼,通過查找相關(guān)的資料發(fā)現(xiàn)可能是因?yàn)橄到y(tǒng)沒有配置中文字符編碼的原因,下面這篇文章就來詳細(xì)介紹了Ubuntu系統(tǒng)中文顯示亂碼的問題解決方法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • apache 80端口被iis或其他服務(wù)占用怎么辦

    apache 80端口被iis或其他服務(wù)占用怎么辦

    80端口被占用導(dǎo)致apache無法正常運(yùn)行,如果80端口不是iis占用,我們可以參考下面方法來查找80端口被哪個服務(wù)占用,具體操作如下
    2013-05-05
  • ubuntu中終端命令提示符太長的修改方法匯總

    ubuntu中終端命令提示符太長的修改方法匯總

    Linux(Ubuntu)終端 命令提示符太長 怎么辦?下面這篇文章主要給大家介紹了關(guān)于ubuntu中終端命令提示符太長的修改方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-04-04
  • Linux C++ 使用condition實(shí)現(xiàn)阻塞隊(duì)列的方法

    Linux C++ 使用condition實(shí)現(xiàn)阻塞隊(duì)列的方法

    下面小編就為大家?guī)硪黄狶inux C++ 使用condition實(shí)現(xiàn)阻塞隊(duì)列的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • Linux中的線程安全與線程同步詳解

    Linux中的線程安全與線程同步詳解

    這篇文章主要介紹了Linux中的線程安全與線程同步,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Ubuntu修改密碼及密碼復(fù)雜度策略設(shè)置方法

    Ubuntu修改密碼及密碼復(fù)雜度策略設(shè)置方法

    這篇文章主要介紹了Ubuntu修改密碼及密碼復(fù)雜度策略設(shè)置,方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • ubuntu下用dpkg命令行運(yùn)行deb安裝包的方法

    ubuntu下用dpkg命令行運(yùn)行deb安裝包的方法

    在Ubuntu系統(tǒng)中,除了通過桌面啟動deb安裝包外,還能通過命令行來運(yùn)行deb安裝包,需要使用到dpkg命令,下面這篇文中就給大家介紹下Ubuntu下使用dpkg命令運(yùn)行deb安裝包的方法,需要的朋友可以參考借鑒,一起來學(xué)習(xí)下吧。
    2017-01-01
  • linux下RPM包安裝基于xinetd的服務(wù)的管理

    linux下RPM包安裝基于xinetd的服務(wù)的管理

    大家好,本篇文章主要講的是linux下RPM包安裝基于xinetd的服務(wù)的管理,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • apache集成php5.6方法分享

    apache集成php5.6方法分享

    這篇文章主要介紹了apache集成php5.6方法分享,需要的朋友可以參考下
    2015-01-01

最新評論

崇文区| 孝感市| 城固县| 大港区| 盐边县| 三都| 全椒县| 桐梓县| 嘉峪关市| 呼图壁县| 中超| 开鲁县| 阜宁县| 马鞍山市| 开江县| 华亭县| 梁河县| 玛纳斯县| 博乐市| 景洪市| 长沙市| 天长市| 朝阳县| 台南市| 略阳县| 宁阳县| 定南县| 松阳县| 呼图壁县| 松潘县| 邹城市| 涞源县| 通海县| 佳木斯市| 天气| 华蓥市| 大同市| 沙洋县| 西昌市| 互助| 垦利县|