1. 程式人生 > >串列埠termios結構體的詳細設定

串列埠termios結構體的詳細設定

termios結構體內容:

<span style="font-size:18px;">成員 描述
-------------------------------------------
c_cflag 控制模式標誌
c_lflag 本地模式標誌
c_iflag 輸入模式標誌
c_oflag 輸出模式標誌
c_line line discipline
c_cc[NCCS] 控制字元
c_ispeed 輸入波特率
c_ospeed 輸出波特率
 </span>

在termios結構中的四個標誌控制了輸入輸出的四個不同部份。輸入模式標誌c_iflag決定如何解釋和處理接收的字元。輸出模式標誌 c_oflag決定如何解釋和處理髮送到tty裝置的字元。控制模式標誌決定裝置的一系列協議特徵,這一標誌只對物理裝置有效。本地模式標誌 c_lflag決定字元在輸出前如何收集和處理。

在串列埠傳輸中,用波特率來表示傳輸的速度,1波特表示在1秒鐘內可以傳輸1個碼元。波特率設定可以使用 cfsetispeed(&new_termios,B19200)和 cfsetospeed(&new_termios,B19200)這兩個函式來完成,預設的波特率為9600baud。 cfsetispeed()函式用來設定輸入的波特率,cfsetospeed()函式用來設定輸出的波特率。B19200是termios.h標頭檔案裡 定義的一個巨集,表示19200的波特率。

CLOCAL和CREAD是c_cflag成員中與速率相關的標誌,在串列埠程式設計中,這兩個標誌一定要有效,以確保程式在突發的作業控制或掛起時,不 會成為埠的佔有都,同時串列埠的接收驅動會自動讀入資料。設定方法如下:

<span style="font-size:18px;">termios_new.c_cflag |= CLOCAL; //保證程式不會成為端的佔有者
termios_new.c_cflag |= CREAD; //使埠能讀取輸入的資料
 </span>

設定串列埠屬性不能直接賦值,要通過對termios不同成員進行"與"和"或"操作來實現。在termios.h檔案,定義了各種常量,如上面介紹 的CLOCAL,CREAD。這些常量的值是掩碼,通過把這些常量與termios結構成員進行邏輯操作就可實現串列埠屬性的設定。在程式設計時用"|="來啟 用屬性,用"&=~"來取消屬性。

9.3. c_iflag 輸入標誌說明

  • BRKINT和IGNBRK

    如果設定了IGNBRK,中斷條件被忽略。如果沒有設定IGNBRK而設定了BRKINT,中斷條件清空輸入輸出佇列中所有的資料並且向tty的前 臺程序組中所有程序傳送一個SIGINT訊號。如果這兩個都沒有設定,中斷條件會被看作一個0字元。這時,如果設定了PARMRK,當檢測到一個幀誤差時 將會嚮應用程式傳送三個位元組'/377''/0''/0',而不是隻傳送一個'/0'。

  • PARMRK和IGNPAR

    如果設定了IGNPAR,則忽略接收到的資料的奇偶檢驗錯誤或幀錯誤(除了前面提到的中斷條件)。如果沒有設定IGNPAR而設定了PARMRK, 當接收到的位元組存在奇偶檢驗錯誤或幀錯誤的時候。將嚮應用程式傳送一個三位元組的'/377''/0''/n'錯誤報告。其中n表示所接收到的位元組。如果兩 者都沒有設定,除了接收到的位元組存在奇偶檢驗錯誤或幀誤差之外的中止條件都會嚮應用程式傳送一個單位元組('/0')的報告。

  • INPCK

    如果設定,則進行奇偶校驗。如果不進行奇偶檢驗,PARMRK和IGNPAR將對存在的奇偶校驗錯誤不產生任何的影響。

  • ISTRIP

    如果設定,所接收到的所有位元組的高位將會被去除,保證它們是一個7位的字元。

  • INLCR

    如果設定,所接收到的換行字元('/n')將會被轉換成回車符('/r')。

  • IGNCR

    如果設定,則會忽略所有接收的回車符('/r')。

  • ICRNL

    如果設定,但IGNCR沒有設定,接收到的回車符嚮應用程式傳送時會變換成換行符。

  • IUCLC

    如果IUCLC和IEXTEN都設定,接收到的所有大寫字母傳送給應程式時都被轉換成小寫字母。POSIX中沒有定義該標記。

  • IXOFF

    如果設定,為避免tty裝置的輸入緩衝區溢位,tty裝置可以向終端傳送停止符^S和開始符^Q,要求終端停止或重新開始向計算機發送資料。通過停 止符和開始符來控制資料流的方式叫軟體流控制,軟體流控制方式較少用,我們主要還是用硬體流控制方式。硬體流控制在c_cflag標誌中設定。

  • IXON

    如果設定,接收到^S後會停止向這個tty裝置輸出,接收到^Q後會恢復輸出。

  • IXANY

    如果設定,則接到任何字元都會重新開始輸出,而不僅僅是^Q字元。

  • IMAXBEL

    如果設定,當輸入緩衝區空間滿時,再接收到的任何字元就會發出警報符'/a'。POSIX中沒有定義該標記。

9.4. c_oflag 輸出標誌說明

OPOST是POSIX定義的唯一一個標誌,只有設定了該標誌後,其它非POSIX的輸出標記才會生效。

  • OPOST

    開啟該標記,後面的輸出標記才會生效。否則,不會對輸出資料進行處理。

  • OLCUC

    如果設定,大寫字母被轉換成小寫字母輸出。

  • ONLCR

    如果設定,在傳送換行符('/n')前先發送回車符('/r')。

  • ONOCR

    如果設定,當current column為0時,回車符不會被髮送也不會被處理。

  • OCRNL

    如果設定,回車符會被轉換成換行符。另外,如果設定了ONLRET,則current column會被設為0.

  • ONLRET

    如果設定,當一個換行符或回車符被髮送的時候,current column會被設定為0。

  • OXTABS

    如果設定,製表符會被轉換成空格符。

9.5. c_cflag 控制模式標誌說明

  • CLOCAL

    如果設定,modem的控制線將會被忽略。如果沒有設定,則open()函式會阻塞直到載波檢測線宣告modem處於摘機狀態為止。

  • CREAD

    只有設定了才能接收字元,該標記是一定要設定的。

  • CSIZE

    設定傳輸字元的位數。CS5表示每個字元5位,CS6表示每個字元6位,CS7表示每個字元7位,CS8表示每個字元8位。

  • CSTOPB

    設定停止位的位數,如果設定,則會在每幀後產生兩個停止位,如果沒有設定,則產生一個停止位。一般都是使用一位停止位。需要兩位停止位的裝置已過時 了。

  • HUPCL

    如果設定,當裝置最後開啟的檔案描述符關閉時,串列埠上的DTR和RTS線會減弱訊號,通知Modem結束通話。也就是說,當一個使用者通過Modem拔號 登入系統,然後登出,這時Modem會自動結束通話。

  • PARENB和PARODD

    如果設定PARENB,會產生一個奇偶檢驗位。如果沒有設定PARODD,則產生偶校驗位,如果設定了PARODD,則產生奇校驗位。如果沒有設定 PARENB,則PARODD的設定會被忽略。

  • CRTSCTS

    使用硬體流控制。在高速(19200bps或更高)傳輸時,使用軟體流控制會使效率降低,這個時候必須使用硬體流控制。

9.6. c_cc[] 控制字元說明

只有在本地模式標誌c_lflag中設定了IEXITEN時,POSIX沒有定義的控制字元才能在Linux中使用。每個控制字元都對應一個按鍵組 合(^C、^H等),但VMIN和VTIME這兩個控制字元除外,它們不對應控制符。這兩個控制字元只在原始模式下才有效。

  • c_cc[VINTR]

    預設對應的控制符是^C,作用是清空輸入和輸出佇列的資料並且向tty裝置的前臺程序組中的每一個程式傳送一個SIGINT訊號,對SIGINT信 號沒有定義處理程式的程序會馬上退出。

  • c_cc[VQUIT]

    預設對應的控制符是^/,作用是清空輸入和輸出佇列的資料並向tty裝置的前臺程序組中的每一個程式傳送一個SIGQUIT訊號,對SIGQUIT 訊號沒有定義處理程式的程序會馬上退出。

  • c_cc[verase]

    預設對應的控制符是^H或^?,作用是在標準模式下,刪除本行前一個字元,該字元在原始模式下沒有作用。

  • c_cc[VKILL]

    預設對應的控制符是^U,在標準模式下,刪除整行字元,該字元在原始模式下沒有作用。

  • c_cc[VEOF]

    預設對應的控制符是^D,在標準模式下,使用read()返回0,標誌一個檔案結束。

  • c_cc[VSTOP]

    預設對應的控制字元是^S,作用是使用tty裝置暫停輸出直到接收到VSTART控制字元。或者,如果裝置了IXANY,則等收到任何字元就開始輸 出。

  • c_cc[VSTART]

    預設對應的控制字元是^Q,作用是重新開始被暫停的tty裝置的輸出。

  • c_cc[VSUSP]

    預設對應的控制字元是^Z,使當前的前臺程序接收到一個SIGTSTP訊號。

  • c_cc[VEOL]和c_cc[VEOL2]

    在標準模式下,這兩個下標在行的末尾加上一個換行符('/n'),標誌一個行的結束,從而使用緩衝區中的資料被髮送,並開始新的一行。POSIX中 沒有定義VEOL2。

  • c_cc[VREPRINT]

    預設對應的控制符是^R,在標準模式下,如果設定了本地模式標誌ECHO,使用VERPRINT對應的控制符和換行符在本地顯示,並且重新列印當前 緩衝區中的字元。POSIX中沒有定義VERPRINT。

  • c_cc[VWERASE]

    預設對應的控制字元是^W,在標準模式下,刪除緩衝區末端的所有空格符,然後刪除與之相鄰的非空格符,從而起到在一行中刪除前一個單詞的效果。 POSIX中沒有定義VWERASE。

  • c_cc[VLNEXT]

    預設對應的控制符是^V,作用是讓下一個字元原封不動地進入緩衝區。如果要讓^V字元進入緩衝區,需要按兩下^V。POSIX中沒有定義 VLNEXT。

要禁用某個控制字元,只需把它設定為_POSIX_VDISABLE即可。但該常量只在Linux中有效,所以如果程式要考慮移植性的問題,請不要 使用該常量。

9.7. c_lflag 本地模式標誌說明

  • ICANON

    如果設定,則啟動標準模式,如果沒有設定,則啟動原始模式。

  • ECHO

    如果設定,則啟動本地回顯。如果沒有設定,則除了ECHONL之外,其他以ECHO開頭的標記都會失效。

  • ECHOCTL

    如果設定,則以^C的形式列印控制字元,如:按Ctrl+C顯示^C,按Ctrl+?顯示^?。

  • ECHOE

    如果在標準模式下設定了ECHOE標誌,則當收到一個ERASE控制符時將刪除前一個顯示字元。

  • ECHOK和ECHOKE

    在標準模式下,當接收到一個KILL控制符,則在緩衝區中刪除當前行。如果ECHOK、ECHOKE和ECHOE都沒有設定,則用ECHOCTL表 示的KILL字元(^U)將會在輸出終端上顯示,表示當前行已經被刪除。

    如果已經設定了ECHOE和ECHOK,但沒有設定ECHOKE,將會在輸出終端顯示ECHOCTL表示的KILL字元,緊接著是換行,如果設定了 OPOST,將會通過OPOST處理程式進行適當的處理。

    如果ECHOK、ECHOKE和ECHOE都有設定,則會刪除當前行。

    在POSIX中沒有定義ECHOKE標記,在沒有定義ECHOKE標記的系統中,設定ECHOK則表示同時設定了ECHOKE標誌。

  • ECHONL

    如果在標準模式下設定了該標誌,即使沒有設定ECHO標誌,換行符還是會被顯示出來。

  • ECHOPRT

    如果設定,則字元會被簡單地打印出來,包括各種控制字元。在POSIX中沒有定義該標誌。

  • ISIG

    如果設定,與INTR、QUIT和SUSP相對應的訊號SIGINT、SIGQUIT和SIGTSTP會發送到tty裝置的前臺程序組中的所有進 程。

  • NOFLSH

    一般情況下,當接收到INTR或QUIT控制符的時候會清空輸入輸出佇列,當接收到SUSP控制符時會清空輸入佇列。但是如果設定了NOFLUSH 標誌,則所有佇列都不會被清空。

  • TOSTOP

    如果設定,則當一個非前臺程序組的程序試圖向它的控制終端寫入資料時,訊號SIGTTOU會被被髮送到這個程序所在的程序組。預設情況下,這個訊號 會使程序停止,就像收到SUSP控制符一樣。

  • IEXIEN

    預設已設定,我們不應修改它。在Linux中IUCLC和幾個與刪除字元相關的標記都要求在設定了IEXIEN才能正常工作。

9.8. 下面介紹 一些常用串列埠屬性的設定方法。

  • 設定流控制

    <span style="font-size:18px;">termios_new.c_cflag &= ~CRTSCTS; //不使用流控制
    termios_new.c_cflag |= CRTSCTS; //使用硬體流控制
    termios_new.c_iflag |= IXON|IXOFF|IXANY; //使用軟體流控制
     </span>
  • 遮蔽字元大小位

    <span style="font-size:18px;">termios_new.c_cflag &= ~CSIZE; 
     </span>
  • 設定資料位大小

    <span style="font-size:18px;">termios_new.c_cflag |= CS8; //使用8位資料位
    termios_new.c_cflag |= CS7; //使用7位資料位
    termios_new.c_cflag |= CS6; //使用6位資料位
    termios_new.c_cflag |= CS5; //使用5位資料位
     </span>
  • 設定奇偶校驗方式

    <span style="font-size:18px;">termios_new.c_cflag &amp;= ~PARENB; //無奇偶校驗
     
    termios_new.c_cflag |= PARENB; //奇校驗
    termios_new.c_cflag &amp;= ~PARODD; 
     
    termios_new.c_cflag |= PARENB; //偶校驗
    termios_new.c_cflag &amp;= ~PARODD; 
     </span>
  • 停止位

    <span style="font-size:18px;">termios_new.c_cflag |= CSTOPB; //2位停止位
    termios_new.c_cflag &amp;= ~CSTOPB; //1位停止位 
     </span>
  • 輸出模式

    <span style="font-size:18px;">termios_new.c_cflag &amp;= ~OPOST; //原始資料(RAW)輸出
     </span>
  • 控制字元

    <span style="font-size:18px;">termios_new.c_cc[VMIN] = 1; //讀取字元的最小數量
    termios_new.c_cc[VTIME] = 1; //讀取第一個字元的等待時間
     </span>
  • 關閉終端回顯,鍵盤輸入的字元不會在終端視窗顯示。

    <span style="font-size:18px;">#include <stdio.h>
    #include <stdlib.h>
    #include <termios.h>
    #include <unistd.h>
     
    int main(void)
    {
    struct termios ts,ots;
    char passbuf[1024];
     
    tcgetattr(STDIN_FILENO,&ts); /* STDIN_FILENO的值是1,表示標準輸入的檔案描述符 */
    ots = ts;
     
    ts.c_lflag &= ~ECHO; /* 關閉回終端回顯功能*/
    ts.c_lflag |= ECHONL;
    tcsetattr(STDIN_FILENO,TCSAFLUSH,&ts); /* 應用新終端設定 */
     
    fgets(passbuf,1024,stdin); /* 輸入字元不會在終端顯示 */
    printf("you input character = %s/n",passbuf);
     
    tcsetattr(STDIN_FILENO,TCSANOW,&ots); /* 恢復舊的終端裝置 */
    }</span>