串口編程2:編程基礎

閱讀目錄

操作串口需要包含的頭文件

#include <stdio.h>   /*標準輸入輸出的定義*/
#include <errno.h>  /*錯誤號定義*/
#include <sys/stat.h>
#include <fcntl.h>  /*文件控制定義*/
#include <termios.h>    /*PPSIX 終端控制定義*/
#include <stdlib.h> /*標準函數庫定義*/
#include <sys/types.h>
#include <unistd.h> /*UNIX 標準函數定義*/

串口相關操作 

打開串口

我們都知道,在Linux下,除了網絡設備,其餘的都是文件的形式。串口設備也一樣在/dev下。

所以我們可以通過open系統調用/函數來訪問它。 示例: 

fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY|O_NDELAY); 

O_NOCTTY:可以告訴Linux這個程序不會成爲這個端口上的“控制終端”.如果不這樣做的話,所有的輸入,比如鍵盤上過來的Ctrl+C中止信號等等,會影響到你的進程。 
O_NDELAY:標誌則是告訴Linux,這個程序並不關心DCD信號線的狀態——也就是不關心端口另一端是否已經連接。

讀寫串口

與普通文件一樣,使用read,write函數。 示例:

read(fd,buff,8); 
write(fd,buff,8);

串口屬性設置 

最基本的設置串口包括波特率設置,效驗位和停止位設置。這由通信雙方協定。

很多系統都支持POSIX終端(串口)接口.程序可以利用這個接口來改變終端的參數,比如,波特率,字符大小等等.要使用這個端口的話,你必須將<termios.h>頭文件包含到你的程序中。這個頭文件中定義了終端控制結構體和POSIX控制函數。

最重要的就是這個結構體:

struct termios
{
    tcflag_t  c_iflag;  //輸入選項
    tcflag_t  c_oflag;  //輸出選項
    tcflag_t  c_cflag;  //控制選項
    tcflag_t  c_lflag;  //行選項
    cc_t      c_cc[NCCS]; //控制字符
};

其中我們更關注的是c_cflag控制選項。其中包含了波特率、數據位、校驗位、停止位的設置。 
它可以支持很多常量名稱其中設置數據傳輸率爲相應的數據傳輸率前要加上“B”。 
c_cflag成員不能直接對其初始化,而要將其通過與、或操作使用其中的某些選項。 
設置串口屬性主要是配置termios結構體中的各個變量,大致流程如下:

使用函數tcgetattr保存原串口屬性 

struct termios newtio,oldtio; 
tcgetattr(fd,&oldtio);

通過位掩碼的方式激活本地連接和接受使能選項:CLOCAL和CREAD 

newtio.c_cflag | = CLOCAL | CREAD;

使用函數cfsetispeed和cfsetospeed設置數據傳輸率 

cfsetispeed(&newtio,B115200); 
cfsetospeed(&newtio,B115200);

取值必須是以下常量之一:

B0    B50    B75    B110    B134    B150    B200    B300    B600    B1200    B1800
B2400    B4800    B9600    B19200    B38400    B57600    B115200    B230400

通過位掩碼設置字符大小

newtio.c_cflag &= ~CSIZE; 
newtio.c_cflag |= CS8;

設置奇偶效驗位

設置奇偶效驗位需要用到兩個termios中的成員:c_cflag和c_iflag。首先要激活c_cflag中的校驗位使能標誌PARENB和是否進行奇偶效驗,同時還要激活c_iflag中的奇偶效驗使能。 

//設置奇校驗: 
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;

設置停止位

激活c_cflag中的CSTOPB設置停止位。若停止位爲1,則清除CSTOPB;若停止位爲0,則激活CSTOPB。

newtio.c_cflag &= ~CSTOPB;

設置最少字符和等待時間

在對接收字符和等待時間沒有特別要求的情況下,可以將其設置爲0。

newtio.c_cc[VTIME] = 0; 
newtio.c_cc[VMIN] = 0;

處理要寫入引用的對象

調用函數”tcflush(fd,queue_selector)”來處理要寫入引用的對象,queue_selector可能的取值有以下幾種:

TCIFLUSH:刷新收到的數據但是不讀 
TCOFLUSH:刷新寫入的數據但是不傳送 
TCIOFLUSH:同時刷新收到的數據但是不讀,並且刷新寫入的數據但是不傳送。

激活配置

在完成配置後,需要激活配置使其生效。使用tcsetattr()函數。

int tcsetattr(int filedes,int opt,const struct termios *termptr);

串口配置的完整代碼

#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>


int set_serial(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
    struct termios newttys1,oldttys1;

     /*保存原有串口配置*/
     if(tcgetattr(fd,&oldttys1)!=0) 
     {
          perror("Setupserial 1");
          return -1;
     }
     bzero(&newttys1,sizeof(newttys1));
     newttys1.c_cflag|=(CLOCAL|CREAD ); /*CREAD 開啓串行數據接收,CLOCAL並打開本地連接模式*/

     newttys1.c_cflag &=~CSIZE;/*設置數據位*/
     /*數據位選擇*/   
     switch(nBits)
     {
         case 7:
             newttys1.c_cflag |=CS7;
             break;
         case 8:
             newttys1.c_cflag |=CS8;
             break;
     }
     /*設置奇偶校驗位*/
     switch( nEvent )
     {
         case '0':  /*奇校驗*/
             newttys1.c_cflag |= PARENB;/*開啓奇偶校驗*/
             newttys1.c_iflag |= (INPCK | ISTRIP);/*INPCK打開輸入奇偶校驗;ISTRIP去除字符的第八個比特  */
             newttys1.c_cflag |= PARODD;/*啓用奇校驗(默認爲偶校驗)*/
             break;
         case 'E':/*偶校驗*/
             newttys1.c_cflag |= PARENB; /*開啓奇偶校驗  */
             newttys1.c_iflag |= ( INPCK | ISTRIP);/*打開輸入奇偶校驗並去除字符第八個比特*/
             newttys1.c_cflag &= ~PARODD;/*啓用偶校驗*/
             break;
         case 'N': /*無奇偶校驗*/
             newttys1.c_cflag &= ~PARENB;
             break;
     }
     /*設置波特率*/
    switch( nSpeed )  
    {
        case 2400:
            cfsetispeed(&newttys1, B2400);
            cfsetospeed(&newttys1, B2400);
            break;
        case 4800:
            cfsetispeed(&newttys1, B4800);
            cfsetospeed(&newttys1, B4800);
            break;
        case 9600:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
        case 115200:
            cfsetispeed(&newttys1, B115200);
            cfsetospeed(&newttys1, B115200);
            break;
        default:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
    }
     /*設置停止位*/
    if( nStop == 1)/*設置停止位;若停止位爲1,則清除CSTOPB,若停止位爲2,則激活CSTOPB*/
    {
        newttys1.c_cflag &= ~CSTOPB;/*默認爲一位停止位; */
    }
    else if( nStop == 2)
    {
        newttys1.c_cflag |= CSTOPB;/*CSTOPB表示送兩位停止位*/
    }

    /*設置最少字符和等待時間,對於接收字符和等待時間沒有特別的要求時*/
    newttys1.c_cc[VTIME] = 0;/*非規範模式讀取時的超時時間;*/
    newttys1.c_cc[VMIN]  = 0; /*非規範模式讀取時的最小字符數*/
    tcflush(fd ,TCIFLUSH);/*tcflush清空終端未完成的輸入/輸出請求及數據;TCIFLUSH表示清空正收到的數據,且不讀取出來 */

     /*激活配置使其生效*/
    if((tcsetattr( fd, TCSANOW,&newttys1))!=0)
    {
        perror("com set error");
        return -1;
    }

    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章