<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    Linux下串口編程入門

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    簡介:

      Linux操作系統從一開始就對串行口提供了很好的支持,本文就Linux下的串行口通訊編程進行簡單的介紹。

     

    串口簡介

      串行口是計算機一種常用的接口,具有連接線少,通訊簡單,得到廣泛的使用。常用的串口是RS-232-C接口(又稱EIA RS-232-C)它是在1970年由美國電子工業協會(EIA)聯合貝爾系統、調制解調器廠家及計算機終端生產廠家共同制定的用于串行通訊的標準。它的全名是"數據終端設備(DTE)和數據通訊設備(DCE)之間串行二進制數據交換接口技術標準"該標準規定采用一個25個腳的DB25連接器,對連接器的每個引腳的信號內容加以規定,還對各種信號的電平加以規定。傳輸距離在碼元畸變小于4%的情況下,傳輸電纜長度應為50英尺。

      Linux操作系統從一開始就對串行口提供了很好的支持,本文就Linux下的串行口通訊編程進行簡單的介紹,如果要非常深入了解,建議看看本文所參考的《Serial Programming Guide for POSIX Operating Systems》

     

    串口操作

      串口操作需要的頭文件

    #include <stdio.h> /*標準輸入輸出定義*/

    #include <stdlib.h> /*標準函數庫定義*/

    #include <unistd.h> /*Unix 標準函數定義*/

    #include <sys/types.h>

    #include <sys/stat.h>

    #include <fcntl.h> /*文件控制定義*/

    #include <termios.h> /*PPSIX 終端控制定義*/

    #include <errno.h> /*錯誤號定義*/



    打開串口

    在 Linux 下串口文件是位于 /dev 下的。串口一 為 /dev/ttyS0,串口二 為 /dev/ttyS1。打開串口是通過使用標準的文件打開函數操作:

    int fd; /*以讀寫方式打開串口*/

    fd = open( "/dev/ttyS0", O_RDWR);

    if (-1 == fd)

    { /* 不能打開串口一*/

        perror(" 提示錯誤!");

    }



    設置串口

    最基本的設置串口包括波特率設置,效驗位和停止位設置。串口的設置主要是設置 struct termios結構體的各成員值。

    struct termio

    {

        unsigned short c_iflag; /* 輸入模式標志 */

        unsigned short c_oflag; /* 輸出模式標志 */

        unsigned short c_cflag; /* 控制模式標志*/

        unsigned short c_lflag; /* local mode flags */

        unsigned char c_line; /* line discipline */

        unsigned char c_cc[NCC]; /* control characters */

    };



    設置這個結構體很復雜,我這里就只說說常見的一些設置:

    波特率設置 下面是修改波特率的代碼:

    struct termios Opt;

    tcgetattr(fd, &Opt);

    cfsetispeed(&Opt,B19200); /*設置為19200Bps*/ cfsetospeed(&Opt,B19200);

    tcsetattr(fd,TCANOW,&Opt);



    設置波特率的例子函數:

    int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };

    int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };

     

    void set_speed(int fd, int speed)

    {

        int i;

        int status;

        struct termios Opt;

        tcgetattr(fd, &Opt);

        for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)

        {

            if (speed == name_arr[i])

            {

                tcflush(fd, TCIOFLUSH);

                cfsetispeed(&Opt, speed_arr[i]);

                cfsetospeed(&Opt, speed_arr[i]);

                status = tcsetattr(fd1, TCSANOW, &Opt);

                if (status != 0)

                { perror("tcsetattr fd1"); return; }

                tcflush(fd,TCIOFLUSH);

            }

        }

    }



    設置效驗的函數:


    int set_Parity(int fd,int databits,int stopbits,int parity)

    {

        struct termios options;

        if ( tcgetattr( fd,&options) != 0)

        { perror("SetupSerial 1"); return(FALSE); }

     

        options.c_cflag &= ~CSIZE;

        switch (databits) /*設置數據位數*/

        {

        case 7:

            options.c_cflag |= CS7;

            break;

        case 8:

            options.c_cflag |= CS8;

            break;

        default:

            fprintf(stderr,"Unsupported data size/n");

            return (FALSE);

        }

     

        switch (parity)

        {

        case 'n':

        case 'N':

            options.c_cflag &= ~PARENB; /* Clear parity enable */

            options.c_iflag &= ~INPCK; /* Enable parity checking */

            break;

        case 'o':

        case 'O':

            options.c_cflag |= (PARODD | PARENB); /* 設置為奇效驗*/

            options.c_iflag |= INPCK; /* Disnable parity checking */

            break;

        case 'e':

        case 'E':

            options.c_cflag |= PARENB; /* Enable parity */

            options.c_cflag &= ~PARODD; /* 轉換為偶效驗*/

            options.c_iflag |= INPCK; /* Disnable parity checking */

            break;

        case 'S':

        case 's': /*as no parity*/

            options.c_cflag &= ~PARENB;

            options.c_cflag &= ~CSTOPB;

            break;

        default:

            fprintf(stderr,"Unsupported parity/n");

            return (FALSE);

        } /* 設置停止位*/

     

        switch (stopbits)

        {

        case 1:

            options.c_cflag &= ~CSTOPB;

            break;

        case 2:

            options.c_cflag |= CSTOPB;

            break;

        default:

            fprintf(stderr,"Unsupported stop bits/n");

            return (FALSE);

        } /* Set input parity option */

     

        if (parity != 'n')

            options.c_iflag |= INPCK;

     

        tcflush(fd,TCIFLUSH);

        options.c_cc[VTIME] = 150; /* 設置超時15 seconds*/

        options.c_cc[VMIN] = 0; /* Update the options and do it NOW */

        if (tcsetattr(fd,TCSANOW,&options) != 0)

        {

            perror("SetupSerial 3");

            return (FALSE);

        }

     

        return (TRUE);

    }



    需要注意的是: 如果不是開發終端之類的,只是串口傳輸數據,而不需要串口來處理,那么使用原始模式(Raw Mode)方式來通訊,設置方式如下:

    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/

    options.c_oflag &= ~OPOST; /*Output*/



    讀寫串口

    設置好串口之后,讀寫串口就很容易了,把串口當作文件讀寫就是。

    char buffer[1024];

    int Length;

    int nByte;

    nByte = write(fd, buffer ,Length)



    ·讀取串口數據

    使用文件操作read函數讀取,如果設置為原始模式(Raw Mode)傳輸數據,那么read函數返回的字符數是實際串口收到的字符數。可以使用操作文件的函數來實現異步讀取,如fcntl,或者select等來操作。

    char buff[1024];

    int Len;

    int readByte = read(fd,buff,Len);



    關閉串口

    關閉串口就是關閉文件。

    close(fd);



    例子

    下面是一個簡單的讀取串口數據的例子,使用了上面定義的一些函數和頭文件

    #define FALSE  -1
    #define TRUE   0

    int OpenDev(char *Dev)
    {
        int fd = open( Dev, O_RDWR ); 
        if (-1 == fd) 
        { 
            perror("Can't Open Serial Port");
            return -1; 
        }
        else 
            return fd;
    }

     

    int main(int argc, char **argv)

    {
        int fd;
        int nread;
        char buff[512];
        char *dev  = "/dev/ttyS1"; //串口二
        fd = OpenDev(dev);
        set_speed(fd,19200);
        if (set_Parity(fd,8,1,'N') == FALSE)  {
            printf("Set Parity Error/n");
            exit (0);
        }

        while (1)
        {
             while((nread = read(fd, buff, 512))>0)
             {
                  printf("/nLen %d/n",nread);
                  buff[nread+1] = '/0';
                  printf( "/n%s", buff);
             }
        }

        close(fd);
    }



    參考資料

    Serial Programming Guide for POSIX Operating Systems
    http://www.gjwtech.com/

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全