IT培训机构|91免费精品视频|专注编程培训|91免费精品|软件开发培训_91免费国产视频_华清远见教育


嵌入式Linux串口應用編程之串口配置

分享到:
           

    串口的設置主要是設置struct termios結構體的各成員值,如下所示:

    #include<termios.h>
    struct termios
    {
        unsigned short c_iflag; /* 輸入模式標志 */
        unsigned short c_oflag; /* 輸出模式標志 */
        unsigned short c_cflag; /* 控制模式標志 */
        unsigned short c_lflag; /* 本地模式標志 */
        unsigned char c_line; /* 線路規程 */
        unsigned char c_cc[NCC]; /* 控制特性 */
        speed_t c_ispeed; /* 輸入速度 */
        speed_t c_ospeed; /* 輸出速度 */
    };

    termios是在Posix規范中定義的標準接口,表示終端設備(包括虛擬終端、串口等)。因為串口是一種終端設備,所以通過終端編程接口對其進行配置和控制。因此在具體討論串口相關編程之前,需要先了解一下終端的相關知識。

    終端是指用戶與計算機進行對話的接口,如鍵盤、顯示器和串口設備等物理設備,X Window上的虛擬終端。類UNIX操作系統都有文本式虛擬終端,使用【Ctrl+Alt】+F1~F6鍵可以進入文本式虛擬終端,在X Window上可以打開幾十個以上的圖形式虛擬終端。類UNIX操作系統的虛擬終端有xterm、rxvt、zterm、eterm等,而Windows上有crt、putty等虛擬終端。

    終端有三種工作模式,分別為規范模式(canonical mode)、非規范模式(non-canonical mode)和原始模式(raw mode)。

    通過在termios結構的c_lflag中設置ICANNON標志來定義終端是以規范模式(設置ICANNON標志)還是以非規范模式(清除ICANNON標志)工作,默認情況為規范模式。

    在規范模式下,所有的輸入是基于行進行處理的。在用戶輸入一個行結束符(回車符、EOF等)之前,系統調用read()函數是讀不到用戶輸入的任何字符的。除了EOF之外的行結束符(回車符等)與普通字符一樣會被read()函數讀取到緩沖區中。在規范模式中,行編輯是可行的,而且一次調用read()函數多只能讀取一行數據。如果在read()函數中被請求讀取的數據字節數小于當前行可讀取的字節數,則read()函數只會讀取被請求的字節數,剩下的字節下次再被讀取。

    在非規范模式下,所有的輸入是即時有效的,不需要用戶另外輸入行結束符,而且不可進行行編輯。在非規范模式下,對參數MIN(c_cc[VMIN])和TIME(c_cc[VTIME])的設置決定read()函數的調用方式。設置可以有4種不同的情況。

    ● MIN = 0和TIME = 0:read()函數立即返回。若有可讀數據,則讀取數據并返回被讀取的字節數,否則讀取失敗并返回0。
    ● MIN > 0和TIME = 0:read()函數會被阻塞,直到MIN個字節數據可被讀取。
    ● MIN = 0和TIME > 0:只要有數據可讀或者經過TIME個十分之一秒的時間,read()函數則立即返回,返回值為被讀取的字節數。如果超時并且未讀到數據,則read()函數返回0。
    ● MIN > 0和TIME > 0:當有MIN個字節可讀或者兩個輸入字符之間的時間間隔超過TIME個十分之一秒時,read()函數才返回。因為在輸入第一個字符后系統才會啟動定時器,所以,在這種情況下,read()函數至少讀取一個字節后才返回。

    按照嚴格意義來講,原始模式是一種特殊的非規范模式。在原始模式下,所有的輸入數據以字節為單位被處理。在這個模式下,終端是不可回顯的,而且所有特定的終端輸入/輸出控制處理不可用。通過調用cfmakeraw()函數可以將終端設置為原始模式,而且該函數通過以下代碼可以得到實現:

    termios_p->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
    | INLCR | IGNCR | ICRNL | IXON);
    termios_p->c_oflag &= ~OPOST;
    termios_p->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    termios_p->c_cflag &= ~(CSIZE | PARENB);
    termios_p->c_cflag |= CS8;

    現在講解設置串口的基本方法。如上所述,串口設置基本的操作包括波特率設置,校驗位和停止位設置。在這個結構中為重要的是c_cflag,通過對它的賦值,用戶可以設置波特率、字符大小、數據位、停止位、奇偶校驗位和硬軟流控等。另外,c_iflag和c_cc也是比較常用的標志。在此主要對這3個成員進行詳細說明。c_cflag支持的常量名稱如表2.11所示。其中設置波特率宏名為相應的波特率數值前加上B,由于數值較多,本表沒有全部列出。

表2.11 c_cflag支持的常量名稱

CBAUD 波特率的位掩碼
B0 0波特率(放棄DTR)

續表

CBAUD 波特率的位掩碼
B1800 1800波特率
B2400 2400波特率
B4800 4800波特率
B9600 9600波特率
B19200 19200波特率
B38400 38400波特率
B57600 57600波特率
B115200 115200波特率
EXTA 外部時鐘率
EXTB 外部時鐘率
CSIZE 數據位的位掩碼
CS5 5個數據位
CS6 6個數據位
CS7 7個數據位
CS8 8個數據位
CSTOPB 2個停止位(不設則是1個停止位)
CREAD 接收使能
PARENB
PARODD
校驗位使能
使用奇校驗而不使用偶校驗
HUPCL 后關閉時掛線(放棄DTR)
CLOCAL 本地連接(不改變端口所有者)
CRTSCTS 硬件流控

    在這里,對于c_cflag成員不能直接對其初始化,而要將其通過“與”、“或”操作使用其中的某些選項。

    輸入模式標志c_iflag用于控制端口接收端的字符輸入處理。c_iflag支持的常量名稱,如表2.12所示。

表2.12 c_iflag支持的常量名稱

INPCK 奇偶校驗使能
IGNPAR 忽略奇偶校驗錯誤
PARMRK 奇偶校驗錯誤掩碼
ISTRIP 裁減掉第8位比特
IXON 啟動輸出軟件流控
IXOFF 啟動輸入軟件流控

續表

INPCK 奇偶校驗使能
IXANY 允許輸入任意字符可以重新啟動輸出(默認為輸入起始字符才重啟輸出)
IGNBRK 忽略輸入終止條件
BRKINT 當檢測到輸入終止條件時發送SIGINT信號
INLCR 將接收到的NL(換行符)轉換為CR(回車符)
IGNCR 忽略接收到的CR(回車符)
ICRNL 將接收到的CR(回車符)轉換為NL(換行符)
IUCLC 將接收到的大寫字符映射為小寫字符
IMAXBEL 當輸入隊列滿時響鈴

    c_oflag用于控制終端端口發送出去的字符處理,c_oflag支持的常量名稱如表2.13所示。因為現在終端的速度比以前快得多,所以大部分延時掩碼幾乎沒什么用途。

表2.13 c_oflag支持的常量名稱

OPOST 啟用輸出處理功能,如果不設置該標志則其他標志都被忽略
OLCUC 將輸出中的大寫字符轉換成小寫字符
ONLCR 將輸出中的換行符('\n')轉換成回車符('\r')
ONOCR 如果當前列號為0,則不輸出回車符
OCRNL 將輸出中的回車符('\r')轉換成換行符('\n')
ONLRET 不輸出回車符
OFILL 發送填充字符以提供延時
OFDEL 如果設置該標志,則表示填充字符為DEL字符,否則為NUL字符
NLDLY 換行符延時掩碼
CRDLY 回車符延時掩碼
TABDLY 制表符延時掩碼
BSDLY 水平退格符延時掩碼
VTDLY 垂直退格符延時掩碼
FFLDY 換頁符延時掩碼

    c_lflag用于控制終端的本地數據處理和工作模式,c_lflag所支持的常量名稱如表2.14所示。

表2.14 c_lflag支持的常量名稱

ISIG 若收到信號字符(INTR、QUIT等),則會產生相應的信號
ICANON 啟用規范模式
ECHO 啟用本地回顯功能
ECHOE 若設置ICANON,則允許退格操作

續表

ECHOK 若設置ICANON,則KILL字符會刪除當前行
ECHONL 若設置ICANON,則允許回顯換行符
ECHOCTL 若設置ECHO,則控制字符(制表符、換行符等)會顯示成“^X”,其中X的ASCII碼等于給相應控制字符的ASCII碼加上0x40。例如,退格字符(0x08)會顯示為“^H”('H'的ASCII碼為0x48)
ECHOPRT 若設置ICANON和IECHO,則刪除字符(退格符等)和被刪除的字符都會被顯示
ECHOKE 若設置ICANON,則允許回顯在ECHOE和ECHOPRT中設定的KILL字符
NOFLSH 在通常情況下,當接收到INTR、QUIT和SUSP控制字符時,會清空輸入和輸出隊列。如果設置該標志,則所有的隊列不會被清空
TOSTOP 若一個后臺進程試圖向它的控制終端進行寫操作,則系統向該后臺進程的進程組發送SIGTTOU信號。該信號通常終止進程的執行
IEXTEN 啟用輸入處理功能

    c_cc定義特殊控制特性,c_cc所支持的常量名稱如表2.15所示。

表2.15 c_cc支持的常量名稱

VINTR 中斷控制字符,對應鍵為Ctrl+C
VQUIT 退出操作符,對應鍵為Ctrl+Z
VERASE 刪除操作符,對應鍵為Backspace(BS)
VKILL 刪除行符,對應鍵為Ctrl+U
VEOF 文件結尾符,對應鍵為Ctrl+D
VEOL 附加行結尾符,對應鍵為Carriage return(CR)
VEOL2 第二行結尾符,對應鍵為Line feed(LF)
VMIN 指定少讀取的字符數
VTIME 指定讀取的每個字符之間的超時時間

    下面就詳細講解設置串口屬性的基本流程。

    1.保存原先串口配置

    首先,為了安全起見和以后調試程序方便,可以先保存原先串口的配置,在這里可以使用函數tcgetattr(fd, &old_cfg)。該函數得到由fd指向的終端的配置參數,并將它們保存于termios結構變量old_cfg中。該函數還可以測試配置是否正確、該串口是否可用等。若調用成功,函數返回值為0,若調用失敗,函數返回值為-1,其使用如下所示:

    if (tcgetattr(fd, &old_cfg) != 0)
    {
        perror("tcgetattr");
        return -1;
    }

    2.激活選項

    CLOCAL和CREAD分別用于本地連接和接收使能,因此,首先要通過位掩碼的方式激活這兩個選項。

    newtio.c_cflag |= CLOCAL | CREAD;

    調用cfmakeraw()函數可以將終端設置為原始模式,在后面的實例中,采用原始模式進行串口數據通信。

    cfmakeraw(&new_cfg);

    3.設置波特率

    設置波特率有專門的函數,用戶不能直接通過位掩碼來操作。設置波特率的主要函數有cfsetispeed()和cfsetospeed()。這兩個函數的使用很簡單,如下所示:

    cfsetispeed(&\&new_cfg, B115200);
    cfsetospeed(&new_cfg, B115200);

    cfsetispeed()函數在termios結構中設置數據輸入波特率,而cfsetospeed()函數在termios結構中設置數據輸入波特率。一般來說,用戶需將終端的輸入和輸出波特率設置成一樣的。這幾個函數在成功時返回0,失敗時返回-1。

    4.設置字符大小

    與設置波特率不同,設置字符大小并沒有現成可用的函數,需要用位掩碼。一般首先去除數據位中的位掩碼,再重新按要求設置,如下所示:

    new_cfg.c_cflag &= ~CSIZE; /* 用數據位掩碼清空數據位設置 */
    new_cfg.c_cflag |= CS8;

    5.設置奇偶校驗位

    設置奇偶校驗位需要用到termios中的兩個成員:c_cflag和c_iflag。首先要激活c_cflag中的校驗位使能標志PARENB和確認是否要進行校驗,這樣會對輸出數據產生校驗位,而對輸入數據進行校驗檢查。同時還要激活c_iflag中的對于輸入數據的奇偶校驗使能(INPCK)。如使能奇校驗時,代碼如下所示:

    new_cfg.c_cflag |= (PARODD | PARENB);
    new_cfg.c_iflag |= INPCK;

    而使能偶校驗時,代碼如下所示:

    new_cfg.c_cflag |= PARENB;
    new_cfg.c_cflag &= ~PARODD; /* 清除偶奇校驗標志,則配置為偶校驗 */
    new_cfg.c_iflag |= INPCK;

    6.設置停止位

    設置停止位是通過激活c_cflag中的CSTOPB而實現的。若停止位為一個比特,則清除CSTOPB;若停止位為兩個,則激活CSTOPB。以下分別是停止位為一個和兩個比特時的代碼:

    new_cfg.c_cflag &= ~CSTOPB; /* 將停止位設置為一個比特 */
    new_cfg.c_cflag |= CSTOPB; /* 將停止位設置為兩個比特 */

    7.設置少字符和等待時間

    在對接收字符和等待時間沒有特別要求的情況下,可以將其設置為0,則在任何情況下read()函數立即返回,此時串口操作會設置為非阻塞方式,如下所示:

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

    8.清除串口緩沖

    由于串口在重新設置后,需要對當前的串口設備進行適當的處理,這時就可調用在<termios.h>中聲明的tcdrain()、tcflow()、tcflush()等函數來處理目前串口緩沖中的數據,它們的格式如下所示:

    int tcdrain(int fd); /* 使程序阻塞,直到輸出緩沖區的數據全部發送完畢 */
    int tcflow(int fd, int action); /* 用于暫停或重新開始輸出 */
    int tcflush(int fd, int queue_selector); /* 用于清空輸入/輸出緩沖區 */

    在本實例中使用tcflush()函數,對于在緩沖區中尚未傳輸的數據,或者收到的但是尚未讀取的數據,其處理方法取決于queue_selector的值,它可能的取值有以下幾種。

    ● TCIFLUSH:對接收到而未被讀取的數據進行清空處理。
    ● TCOFLUSH:對尚未傳送成功的輸出數據進行清空處理。
    ● TCIOFLUSH:包括前兩種功能,即對尚未處理的輸入/輸出數據進行清空處理。

    如在本例中所采用的是第一種方法,當然可以使用TCIOFLUSH參數:

    tcflush(fd, TCIFLUSH);

    9.激活配置

    在完成全部串口配置后,要激活剛才的配置并使配置生效。這里用到的函數是tcsetattr(),它的函數原型是:

    tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

    其中,參數termios_p是termios類型的新配置變量。

    參數optional_actions可能的取值有以下3種。

    ● TCSANOW:配置的修改立即生效。
    ● TCSADRAIN:配置的修改在所有寫入fd的輸出都傳輸完畢之后生效。
    ● TCSAFLUSH:所有已接收但未讀入的輸入都將在修改生效之前被丟棄。

    該函數若調用成功則返回0,若失敗則返回-1,代碼如下所示:

    if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0)
    {
        perror("tcsetattr");
        return -1;
    }

    下面給出了串口配置的完整函數。為了函數的通用性,通常將常用的選項都在函數中列出,這樣可以大大方便以后用戶的調試使用。該設置函數如下所示:

    int set_com_config(int fd,int baud_rate,
    int data_bits, char parity, int stop_bits)
    {
        struct termios new_cfg,old_cfg;
        int speed;

        /* 保存并測試現有串口參數設置,在這里如果串口號等出錯,會有相關的出錯信息 */
        if (tcgetattr(fd, &old_cfg) != 0)
        {
            perror("tcgetattr");
            return -1;
        }
        new_cfg = old_cfg;
        cfmakeraw(&new_cfg); /* 配置為原始模式 */
        new_cfg.c_cflag &= ~CSIZE;
        /* 設置波特率 */
        switch (baud_rate)
        {
            case 2400:
            {
                speed = B2400;
            }
            break;
            case 4800:
            {
                speed = B4800;
            }
            break;
            case 9600:
            {
                speed = B9600;
            }
            break;
            case 19200:
            {
                speed = B19200;
            }
            break;
            case 38400:
            {
                speed = B38400;
            }
            break;

            default:
            case 115200:
            {
                speed = B115200;
            }
            break;
        }
        cfsetispeed(&new_cfg, speed);
        cfsetospeed(&new_cfg, speed);

        switch (data_bits) /* 設置數據位 */
        {
            case 7:
            {
                new_cfg.c_cflag |= CS7;
            }
            break;

            default:
            case 8:
            {
                new_cfg.c_cflag |= CS8
;             }
            break;
        }

        switch (parity) /* 設置奇偶校驗位 */
        {
            default:
            case 'n':
            case 'N':
            {
                new_cfg.c_cflag &= ~PARENB;
                new_cfg.c_iflag &= ~INPCK;
            }
            break;

            case 'o':
            case 'O':
            {
                new_cfg.c_cflag |= (PARODD | PARENB);
                new_cfg.c_iflag |= INPCK;
            }
            break;

            case 'e':
            case 'E':
            {
                new_cfg.c_cflag |= PARENB;
                new_cfg.c_cflag &= ~PARODD;
                new_cfg.c_iflag |= INPCK;
            }
            break;

            case 's': /* as no parity */
            case 'S':
            {
                new_cfg.c_cflag &= ~PARENB;
                new_cfg.c_cflag &= ~CSTOPB;
            }
            break;
        }

        switch (stop_bits) /* 設置停止位 */
        {
            default:
            case 1:
            {
                new_cfg.c_cflag &= ~CSTOPB;
            }
            break;

            case 2:
            {
                new_cfg.c_cflag |= CSTOPB;
            }
        }

        /* 設置等待時間和小接收字符 */
        new_cfg.c_cc[VTIME] = 0;
        new_cfg.c_cc[VMIN] = 1;
        tcflush(fd, TCIFLUSH); /* 處理未接收字符 */
        if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0) /* 激活新配置 */
        {
            perror("tcsetattr");
            return -1;
        }
        return 0;
    }

    本文選自華清遠見嵌入式培訓教材《從實踐中學嵌入式Linux應用程序開發》

   熱點鏈接:

   1、嵌入式Linux串口應用編程基礎知識
   2、Linux下多路復用I/O接口
   3、linux 文件鎖的實現及其應用
   4、底層文件I/O操作的系統調用
   5、Linux中的文件及文件描述符

更多新聞>> 

主站蜘蛛池模板: 离子交换树脂_阴离子交换树脂_阳离子交换树脂-中国树脂网 | 液晶拼接屏_三星46寸/55寸/LG液晶拼接屏_深圳拼接墙厂家_电视大屏幕液晶拼接_高清工业级液晶监视器 | 植绒布工厂,植绒布现货批发-深圳市金峰盛植绒制品有限公司 | 山东淄博海杰化工有限公司-淄博海杰化工_NP-10、OP-10、吐温80、司盘80、磺酸、油酸等乳化剂 | 水暖毯厂家-水暖毯配件-河北鑫政扬家用电器有限公司 | 武汉东湖高新集团股份有限公司官网 | 重庆消杀公司-重庆斗哥环保科技-灭鼠公司-重庆灭蟑螂-除四害-灭老鼠-灭虫-重庆灭白蚁公司 | 苏州交通设施_道路划线_停车场划线_厂区划线_环氧地坪厂家-推荐【飞扬市政交通设施公司】专注交通设施8年! | 压力试验机,万能试验机-北京大地华宇仪器设备有限公司 官网 | 三坐标测量机_海克斯康三坐标_蔡司三坐标_常州三坐标测量服务中心_苏州长南精密技术有限公司 | 压痕机_自动拆标机_瑞安市晨力机械有限公司 | 汇讯WiseUC--连接人与业务,以即时通讯为基础的应用集成平台 | 塑木地板-木塑地板厂家「云南昆明楚雄曲靖玉溪塑木地板」云南云冶中信塑木新型材料有限公司 | 江西省力速数控机械有限公司丨火花机丨龙门加工中心丨镜面火花机丨卧式加工中心 | 上饶环亚电脑会计培训学校--电脑学校|上饶电脑学校|上饶电脑培训|会计培训|上饶会计培训|上饶县会计培训|广丰会计培训|玉山会计培训|横峰会计培训|上饶网店培训 上进电缆(嘉兴)股份有限公司官网 - 光伏电缆|防火电缆|电力电缆|铝合金电缆专业生产厂家 | 陕西|青海|兰州|新疆|西宁|净化工程|西安甘肃|PCR实验室|无尘车间|净化车间-西安环亚净化工程 | 浙江创洁卫生消杀有限公司-浙江杀虫公司,温州消杀公司,温州灭鼠公司,灭蟑螂,灭蚊蝇,灭跳蚤,灭书虱,灭臭虫,灭螨虫,白蚁防治,房间消毒除味等专业服务 | 山东正奇塑料机械有限公司,山东塑料机械,水带机组,塑料管材机,山东吹膜机组厂家,山东农膜机厂家 山东长青石油液压机械有限公司-致力于石油机械设备的研发制造,提供定制服务 | 仪器校准-计量检测-计量校准-中健计量检测(广东)有限公司 | 湖北大洋塑胶有限公司|AGR|PPR|RTP|HDPE|e-PSP钢塑复合压力管道生产厂家 | 中华收藏网-中藏网-藏品拍卖|字画拍卖|艺术品拍卖|古玩城|收藏资讯|古玩交易|书画定制 | 深圳社区邦家政公司-保姆_月嫂_育儿嫂 _早教育婴师_家政钟点工_家政培训_家政加盟- 社区邦优质生活服务 专业、标准化、便捷、安心,一站式家庭服务平台,服务专业有保障 ! | 纸袋胶-糊盒胶-礼盒胶-裱纸胶-水性喷胶-东莞市美好化工有限公司 纸袋机|多层纸袋机|高速纸袋机|无锡市天天友情机械有限公司 | 破碎机锤头_知名破碎机锤头厂家-巩义东辰 | 湖州搬家公司_档案搬迁_货物运输_钟点搬运价格「湖州蓝天家政综合服务有限公司」 | 转炉挡渣机构,转炉滑板挡渣,滑动水口生产厂家-河北瑞华冶金科技有限公司 | 直流电源|Chroma直流电源|可程控直流电源-卓定电子Chroma代理 | 燃气锅炉-供暖锅炉-热水锅炉-电锅炉-北京锅炉安装公司-北京亦辰科技有限公司 | 郑州空调维修_郑州中央空调维修_空调清洗维保-郑州大晟机电设备安装工程有限公司 | 无机纤维抗菌板-A级不燃纤维板-石英纤维板厂家-医疗抗菌板-浙江德耐姆 | 河南郑州纯净水设备_厂家_价格_河南江宇环保科技有限公司水处理设备工厂 | 三叶罗茨鼓风机_三叶罗茨风机厂家_山东九洲四海机械有限公司 | 济宁卡尔迪机械制造有限公司_铁路换枕机_升降驾驶室_挖机加高底盘_加长臂 | 合肥年会策划-合肥开业庆典公司-合肥会务活动礼仪公司-合肥展台搭建/音响租赁公司 [七色海] | 长沙变频器维修,变频器维修,ABB变频器维修,西门子变频器维修,施耐德变频器维修,伺服驱动器维修,工业机器人维修,20年专业工控电气维修,长沙文铖电气设备有限公司_长沙文铖电气设备有限公司 | 无铅锡膏,无铅锡膏厂家,有铅锡膏厂家,高温锡膏厂家,环保锡丝,贴片红胶-东莞市科舜电子科技有限公司 | 卧螺离心机-固液分离机-台州春鼎机械制造有限公司 | 无锡市恒威工业气体有限公司-工业高纯气体_高纯度特种气体 | 首页 -北京博智建达软件开发有限公司| 企业头条—优府网企业自媒体| 泊头压滤机-隔膜-洗沙-厢式-板框压滤机-河北巨盛压滤机制造有限公司 |