国产无码免费,人妻口爆,国产V在线,99中文精品7,国产成人无码AA精品一,制度丝袜诱惑av,久久99免费麻辣视频,蜜臀久久99精品久久久久久酒店
        訂閱
        糾錯
        加入自媒體

        技術文章:基于Linux的tty架構及UART驅動詳解

        2021-02-05 17:06
        一口Linux
        關注

        三. 模塊詳細設計

        3.1. 關鍵函數接口3.1.1. uart_register_driver功能:  uart_register_driver用于串口驅動uart_driver注冊到內核(串口核心層)中,通常在模塊初始化函數調用該函數。
        *參數:drv:要注冊的uart_driver
        *返回值:成功,返回0;否則返回錯誤碼

        int uart_register_driver(struct uart_driver *drv)
        3.1.2. uart_unregister_driver功能:uart_unregister 用于注銷我們已注冊的uart_driver,通常在模塊卸載函數調用該函數,
        *參數 : drv:要注銷的uart_driver
        *返回值:成功返回0,否則返回錯誤碼

        void uart_unregister_driver(struct uart_driver *drv)
        3.1.3. uart_add_one_port功能:uart_add_one_port用于為串口驅動添加一個串口端口,通常在探測到設備后(驅動的設備probe方法)調用該函數
        *參數:
        *     drv:串口驅動
        *     port:要添加的串口端口
        *返回值:成功,返回0;否則返回錯誤碼

        int uart_add_one_port(struct uart_driver *drv,struct uart_port *port)
        3.1.4. uart_remove_one_port功能:uart_remove_one_port用于刪除一個已經添加到串口驅動中的串口端口,通常在驅動卸載時調用該函數
        *參數:
        *     drv:串口驅動
        *     port:要刪除的串口端口
        *返回值:成功,返回0;否則返回錯誤碼

        int uart_remove_one_port(struct uart_driver *drv,struct uart_port *port)
        3.1.5. uart_write_wakeup功能:uart_write_wakeup喚醒上層因串口端口寫數據而堵塞的進程,通常在串口發送中斷處理函數中調用該函數
        *參數:
        *     port: 需要喚醒寫堵塞進程的串口端口

        void uart_write_wakeup(struct uart_port *port)
        3.1.6. uart_suspend_port功能:uart_suspend_port用于掛起特定的串口端口
        *參數:
        *     drv:要掛起的串口端口鎖所屬的串口驅動
        *     port:要掛起的串口端口
        *返回值:成功返回0;否則返回錯誤碼

        int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
        3.1.7. uart_resume_port功能:uart_resume_port用于恢復某一已掛起的串口
        *參數:
        *     drv:要恢復的串口端口所屬的串口驅動
        *     port:要恢復的串口端口
        *返回值:成功返回0;否則返回錯誤碼

        int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
        3.1.8. uart_get_baud_rate功能:uart_get_baud_rate通過解碼termios結構體來獲取指定串口的波特率
        *參數:
        *     port:要獲取波特率的串口端口
        *     termios:當前期望的termios配置(包括串口波特率)
        *     old:以前的termios配置,可以為NULL
        *     min:可以接受的最小波特率
        *     max:可以接受的最大波特率
        *     返回值:串口波特率

        unsigned int uart_get_baund_rate(struct uart_port *port, struct ktermios *termios, struct ktermios *old,unsigned int min, unsigned int max)
        3.1.9. uart_get_divisor功能:uart_get_divisor 用于計算某一波特率的串口時鐘分頻數(串口波特率除數)
        *參數:
        *     port:要計算分頻數的串口端口
        *     baud:期望的波特率
        *返回值:串口時鐘分頻數

        unsigned int uart_get_divisor(struct uart_port *port, unsigned int baund)
        3.1.10. uart_update_timeout功能:uart_update_timeout用于更新(設置)串口FIFO超出時間
        *參數:
        *     port:要更新超時間的串口端口
        *     cfalg:termios結構體的cflag值
        *     baud:串口的波特率

        void uart_update_timeout(struct uart_port *port,unsigned int cflag, unsigned int baud)
        3.1.11. uart_insert_char功能:uart_insert_char用于向uart層插入一個字符
        *參數:
        *     port:要寫信息的串口端口
        *     status:RX buffer狀態
        *     overrun:在status中的overrun bit掩碼
        *     ch:需要插入的字符
        *     flag:插入字符的flag:TTY_BREAK,TTY_PSRIYY, TTY_FRAME

        void uart_insert_char(struct uart_port *port, unsigned int status, unsigned int overrun,unsigned int ch, unsigned int flag)
        3.1.12. uart_console_write功能:uart_console_write用于向串口端口寫一控制臺信息
        *參數:
        *     port:要寫信息的串口端口
        *     s:要寫的信息
        *     count:信息的大小
        *     putchar:用于向串口端口寫字符的函數,該函數有兩個參數:串口端口和要寫的字符

        Void uart_console_write(struct uart_port *port,const char *s, unsigned int count,viod(*putchar)(struct uart_port*, int))
        4. 模塊使用說明4.1. 串口編程4.1.1. 串口控制函數屬性說明tcgetatrr取屬性(termios結構)tcsetarr設置屬性(termios結構)cfgetispeed得到輸入速度cfsetispeed得到輸出速度cfstospeed設置輸出速度tcdrain等待所有輸出都被傳輸tcflow掛起傳輸或接收tcflush刷請未決輸出和/或輸入tcsendbreak送BREAK字符tcgetpgrp得到前臺進程組IDTcsetpgrp設置前臺進程組ID4.1.2. 串口配置流程(1) 保持原先串口配置,使用tegetatrr(fd, &oldtio);struct termious newtio, oldtio;
        tegetattr(fd, &oldtio);
        (2) 激活選項有CLOCAL和CREAD,用于本地連接和接收使用newtio.cflag |= CLOCAL|CREAD;
        (3) 設置波特率newtio.c_cflag = B115200;
        (4) 設置數據位,需使用掩碼設置newtio.c_cflag &= ~CSIZE;
        Newtio.c_cflag |= CS8;
        (5) 設置停止位,通過激活c_cflag中的CSTOP實現。若停止位為1,則清除CSTOPB,若停止位為2,則激活CSTOPnewtio.c_cflag &= ~CSTOPB; 停止位設置為1
        Newtio.c_cflag |= CSTOPB; 停止位設置為2
        (6) 設置流控newtio.c_cfag |= CRTSCTS 開啟硬件流控
        newtio.c_cfag |= (IXON | IXOFF | IXANY); 開啟軟件流控
        (7) 奇偶檢驗位設置,使用c_cflag和c_ifag.設置奇校驗newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);

        設置偶校驗

        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= ~PARODD;
        (8) 設置最少字符和等待時間,對于接收字符和等待時間沒有什么特別的要求,可設置為0:newtio.c_cc[VTIME] = 0;
        newtio.c_cc[VMIN]  = 0;
        (9) 處理要寫入的引用對象tcflush函數刷清(拋棄)輸入緩沖(終端程序已經接收到,但用戶程序尚未讀)或輸出緩沖(用戶程序已經寫,但未發送)。int tcflash(int filedes, int quene)
        quene數應當是下列三個常數之一:
         *TCIFLUSH 刷清輸入隊列
         *TCOFLUSH 刷清輸出隊列
         *TCIOFLUSH 刷清輸入、輸出隊列
        例如:
        tcflush(fd, TCIFLUSH);
        (10) 激活配置,在完成配置后,需要激活配置使其生效。使用tcsetattr()函數:int tcsetarr(int filedes, const struct termios *termptr);
        opt 指定在什么時候新的終端屬性才起作用,
          *TCSANOW:更改立即發生
          *TCSADRAIN:發送了所有輸出后更改才發生。若更改輸出參數則應使用此選項
          *TCSAFLUSH:發送了所有輸出后更改才發生。更進一步,在更改發生時未讀的
                        所有輸入數據都被刪除(刷清)
        例如:tcsetatrr(fd, TCSANOW, &newtio);
        4.1.3. 使用流程(1)打開串口,例如"/dev/ttySLB0"fd = open("/dev/ttySLB0",O_RDWR | O_NOCTTY | O_NDELAY);
        O_NOCTTY:是為了告訴Linux這個程序不會成為這個端口上的“控制終端”。如果不這樣做的話,所有的輸入,比如鍵盤上過來的Ctrl+C中止信號等等,會影響到你的進程。
        O_NDELAY:這個標志則是告訴Linux這個程序并不關心DCD信號線的狀態,也就是不管串口是否有數據到來,都是非阻塞的,程序繼續執行。
        (2)恢復串口狀態為阻塞狀態,用于等待串口數據的讀入,用fcntl函數:fcntl(fd,F_SETFL,0);  //F_SETFL:設置文件flag為0,即默認,即阻塞狀態
        (3)接著測試打開的文件描述符是否應用一個終端設備,以進一步確認串口是否正確打開。isatty(STDIN_FILENO);
        (4)讀寫串口串口的讀寫與普通文件一樣,使用read,write函數
        read(fd, buf ,8);
        write(fd,buff,8);
        4.1.4. Demo

        以下給出一個測溫模塊收取數據的例子

        #include <sys/types.h>
        #include <sys/stat.h>
        #include <fcntl.h>
        #include <termios.h>
        #include <stdio.h>
        #include <string.h>
        #include <unistd.h>
        #include <log/log.h>
        #include <stdlib.h>
        #define UART_DEVICE     "/dev/ttySLB1"
        struct temp {
        float temp_max1;
        float temp_max2;
        float temp_max3;
        float temp_min;
        float temp_mean;
        float temp_enviromem;
        char temp_col[1536];
        };
        int main(void)

        int count, i, fd;
        struct termios oldtio, newtio;
        struct temp *temp;
        temp = (struct temp *)malloc(sizeof(struct temp));
        if (!temp) {
         printf("malloc failed");
         return -1;

        char cmd_buf1[] = { 0xAA, 0x01, 0x04, 0x00, 0x06, 0x10, 0x05, 0x00, 0xBB};
        char cmd_buf2[] = { 0xAA, 0x01, 0x04, 0x00, 0x00, 0xA0, 0x00, 0x03, 0xBB};
        char cmd_buf3[] = { 0xAA, 0x01, 0x04, 0x00, 0x03, 0x10, 0x01, 0x00, 0xBB};
        char read_buf[2000];
        //-----------打開uart設備文件------------------
        fd = open(UART_DEVICE, O_RDWR | O_NOCTTY);
        if (fd < 0) {
         printf("Open %s failed", UART_DEVICE);
         return -1;
        } else {
         printf("Open %s successfully", UART_DEVICE);

        //-----------設置操作參數-----------------------
        tcgetattr(fd, &oldtio);//獲取當前操作模式參數
        memset(&newtio, 0, sizeof(newtio));
        //波特率=230400 數據位=8 使能數據接收
        newtio.c_cflag = B230400 | CS8 | CLOCAL | CREAD | CSTOPB;
        newtio.c_iflag = IGNPAR;
        tcflush(fd, TCIFLUSH);//清空輸入緩沖區和輸出緩沖區
        tcsetattr(fd, TCSANOW, &newtio);//設置新的操作參數
        //printf("input: %s, len = %d", cmd_buf, strlen(cmd_buf));
        //------------向urat發送數據-------------------
        for (i = 0; i < 9; i++)
         printf("%#X ", cmd_buf1[i]);
        count = write(fd, cmd_buf1, 9);
        if (count 。 9) {
         printf("send failed");
         return -1;

        usleep(500000);
        memset(read_buf, 0, sizeof(read_buf));
        count = read(fd, read_buf, sizeof(read_buf));
        if (count > 0) {
         for (i = 0; i < count; i++);
         temp->temp_max1 = read_buf[7] << 8 | read_buf[6];
         temp->temp_max2 = read_buf[9] << 8 | read_buf[8];
         temp->temp_max3 = read_buf[11] << 8 | read_buf[10];
         temp->temp_min  = read_buf[13] << 8 | read_buf[12];
         temp->temp_mean = read_buf[15] << 8 | read_buf[14];
         printf("temp->temp_max1 = %f", temp->temp_max1 * 0.01);
         printf("temp->temp_max2 = %f", temp->temp_max2 * 0.01);
         printf("temp->temp_max3 = %f", temp->temp_max3 * 0.01);
         printf("temp->temp_min  = %f", temp->temp_min  * 0.01);
         printf("temp->temp_mean = %f", temp->temp_mean * 0.01);
         
        } else {
         printf("read temp failed");
         return -1;

        count = write(fd, cmd_buf3, 9);
        if (count 。 9) {
         printf("send failed");
         return -1;

        usleep(365);
        memset(read_buf, 0, sizeof(read_buf));
        count = read(fd, read_buf, sizeof(read_buf));
        if (count > 0) {
         for (i = 0; i < count; i++);
         temp->temp_enviromem = read_buf[7] << 8 | read_buf[6];
         printf("temp->temp_enviromem = %f", temp->temp_enviromem * 0.01);
        } else {
         printf("read enviromem failed");
         return -1;

         
        count = write(fd, cmd_buf2, 9);
        if (count != 9) {
         printf("send failed");
         return -1;

        usleep(70000);
        memset(read_buf, 0, sizeof(read_buf));
        memset(temp->temp_col, 0, sizeof(temp->temp_col));
        count = read(fd, read_buf, sizeof(read_buf));
        printf("count = %d", count);
        if (count > 0) {
         for (i = 0; i < count - 7; i++)
         temp->temp_col[i] = read_buf[i+6];
         for (i = 0; i < 1536; i++)
         {
          if (。╥%10))
           printf("");
          printf("%#X ", temp->temp_col[i]);
         }
        } else {
         printf("read temp colour failed");
         return -1;

        free(temp);
        close(fd);
        tcsetattr(fd, TCSANOW, &oldtio); //恢復原先的設置
        return 0;


        <上一頁  1  2  3  4  
        聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯系舉報。

        發表評論

        0條評論,0人參與

        請輸入評論內容...

        請輸入評論/評論長度6~500個字

        您提交的評論過于頻繁,請輸入驗證碼繼續

        暫無評論

        暫無評論

          人工智能 獵頭職位 更多
          掃碼關注公眾號
          OFweek人工智能網
          獲取更多精彩內容
          文章糾錯
          x
          *文字標題:
          *糾錯內容:
          聯系郵箱:
          *驗 證 碼:

          粵公網安備 44030502002758號

          主站蜘蛛池模板: 国产免费制服丝袜调教视频| 2025无码| 激情图区| 久草精品视频在线观看| 精品无码产区一区二| 亚洲成人黄色网| 临汾市| 日本大色情www成人亚洲| 2025AV在线| 五月天成人社区| 千阳县| 国产19p| AV一本| 九九热色| 国产V片免费A片视频| 菏泽市| 91国在线观看| 91在线资源| 衡南县| 中文字幕丰满人妻熟女| 久久久久久亚洲AV无码专区| 国产精品国产三级国产专区53| 常熟市| 亚洲午夜av| 影音先锋久久| 亚洲国内自拍| 久久内射| 瑞丽市| 国产精品18| 宜兴市| 谁有老熟女网站| 闸北区| 在线免费看av| 国产精品xxxxx| 99热视屏| 999久久久| 日本无码中文| 同江市| 亚洲成人网在线| 国产一区二区波多野结衣| 久久黄色片|