www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 嵌入式 > 嵌入式教程
[導(dǎo)讀]串口是計算機一種常用的接口,常用的串口有RS-232-C接口。它是于1970年由美國電子工業(yè)協(xié)會(EIA)聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計算機終端生產(chǎn)廠家共同制定的用于串行通信的標準,它的全稱是“數(shù)據(jù)終端設(shè)備(DTE)和數(shù)據(jù)通信設(shè)備(DCE)之間串行二進制數(shù)據(jù)交換接口技術(shù)標準”。

6.4嵌入式Linux串口應(yīng)用編程6.4.1串口概述

常見的數(shù)據(jù)通信的基本方式可分為并行通信與串行通信兩種。

n 并行通信是指利用多條數(shù)據(jù)傳輸線將一個字數(shù)據(jù)的各比特位同時傳送。它的特點是傳輸速度快,適用于傳輸距離短且傳輸速度較高的通信。

n 串行通信是指利用一條傳輸線將數(shù)據(jù)以比特位為單位順序傳送。特點是通信線路簡單,利用簡單的線纜就可實現(xiàn)通信,降低成本,適用于傳輸距離長且傳輸速度較慢的通信。

串口是計算機一種常用的接口,常用的串口有RS-232-C接口。它是于1970年由美國電子工業(yè)協(xié)會(EIA)聯(lián)合貝爾系統(tǒng)、調(diào)制解調(diào)器廠家及計算機終端生產(chǎn)廠家共同制定的用于串行通信的標準,它的全稱是“數(shù)據(jù)終端設(shè)備(DTE)和數(shù)據(jù)通信設(shè)備(DCE)之間串行二進制數(shù)據(jù)交換接口技術(shù)標準”。該標準規(guī)定采用一個DB25芯引腳的連接器或9芯引腳的連接器,其中25芯引腳的連接器如圖6.3所示。

圖6.325引腳串行接口圖

S3C2410X內(nèi)部具有兩個獨立的UART控制器,每個控制器都可以工作在Interrupt(中斷)模式或者DMA(直接存儲訪問)模式。同時,每個UART均具有16字節(jié)的FIFO(先入先出寄存器),支持的最高波特率可達到230.4Kbps。UART的操作主要可分為以下幾個部分:數(shù)據(jù)發(fā)送、數(shù)據(jù)接收、產(chǎn)生中斷、設(shè)置波特率、Loopback模式、紅外模式以及硬軟流控模式。

串口參數(shù)的配置讀者在配置超級終端和minicom時也已經(jīng)接觸過,一般包括波特率、起始位比特數(shù)、數(shù)據(jù)位比特數(shù)、停止位比特數(shù)和流控模式。在此,可以將其配置為波特率115200、起始位1b、數(shù)據(jù)位8b、停止位1b和無流控模式。

在Linux中,所有的設(shè)備文件一般都位于“/dev”下,其中串口1和串口2對應(yīng)的設(shè)備名依次為“/dev/ttyS0”和“/dev/ttyS1”,而且USB轉(zhuǎn)串口的設(shè)備名通常為“/dev/ttyUSB0”和“/dev/ttyUSB1”(因版本不同該設(shè)備名會有所不同),可以查看在“/dev”下的文件以確認。在本章中已經(jīng)提到過,在Linux下對設(shè)備的操作方法與對文件的操作方法是一樣的,因此,對串口的讀寫就可以使用簡單的read()、write()函數(shù)來完成,所不同的只是需要對串口的其他參數(shù)另做配置,下面就來詳細講解串口應(yīng)用開發(fā)的步驟。

6.4.2串口設(shè)置詳解

串口的設(shè)置主要是設(shè)置structtermios結(jié)構(gòu)體的各成員值,如下所示:

#include<termios.h>

structtermios

{

unsignedshortc_iflag;/*輸入模式標志*/

unsignedshortc_oflag;/*輸出模式標志*/

unsignedshortc_cflag;/*控制模式標志*/

unsignedshortc_lflag;/*本地模式標志*/

unsignedcharc_line;/*線路規(guī)程*/

unsignedcharc_cc[NCC];/*控制特性*/

speed_tc_ispeed;/*輸入速度*/

speed_tc_ospeed;/*輸出速度*/

};

termios是在POSIX規(guī)范中定義的標準接口,表示終端設(shè)備(包括虛擬終端、串口等)。口是一種終端設(shè)備,一般通過終端編程接口對其進行配置和控制。在具體講解串口相關(guān)編程之前,先了解一下終端相關(guān)知識。

終端有3種工作模式,分別為規(guī)范模式(canonicalmode)、非規(guī)范模式(non-canonicalmode)和原始模式(rawmode)。

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

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

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

n MIN=0和TIME=0:read()函數(shù)立即返回。若有可讀數(shù)據(jù),則讀取數(shù)據(jù)并返回被讀取的字節(jié)數(shù),否則讀取失敗并返回0。

n MIN>0和TIME=0:read()函數(shù)會被阻塞直到MIN個字節(jié)數(shù)據(jù)可被讀取。

n MIN=0和TIME>0:只要有數(shù)據(jù)可讀或者經(jīng)過TIME個十分之一秒的時間,read()函數(shù)則立即返回,返回值為被讀取的字節(jié)數(shù)。如果超時并且未讀到數(shù)據(jù),則read()函數(shù)返回0。

n MIN>0和TIME>0:當有MIN個字節(jié)可讀或者兩個輸入字符之間的時間間隔超過TIME個十分之一秒時,read()函數(shù)才返回。因為在輸入第一個字符之后系統(tǒng)才會啟動定時器,所以在這種情況下,read()函數(shù)至少讀取一個字節(jié)之后才返回。

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

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;

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

表6.11 c_cflag支持的常量名稱

CBAUD

波特率的位掩碼

B0

0波特率(放棄DTR)

B1800

1800波特率

B2400

2400波特率

續(xù)表

B4800

4800波特率

B9600

9600波特率

B19200

19200波特率

B38400

38400波特率

B57600

57600波特率

B115200

115200波特率

EXTA

外部時鐘率

EXTB

外部時鐘率

CSIZE

數(shù)據(jù)位的位掩碼

CS5

5個數(shù)據(jù)位

CS6

6個數(shù)據(jù)位

CS7

7個數(shù)據(jù)位

CS8

8個數(shù)據(jù)位

CSTOPB

2個停止位(不設(shè)則是1個停止位)

CREAD

接收使能

PARENB

PARODD

校驗位使能

使用奇校驗而不使用偶校驗

HUPCL

最后關(guān)閉時掛線(放棄DTR)

CLOCAL

本地連接(不改變端口所有者)

CRTSCTS

硬件流控

在這里,不能直接對c_cflag成員初始化,而要將其通過“與”、“或”操作使用其中的某些選項。輸入模式標志c_iflag用于控制端口接收端的字符輸入處理。c_iflag支持的常量名稱如表6.12所示。

表6.12 c_iflag支持的常量名稱

INPCK

奇偶校驗使能

IGNPAR

忽略奇偶校驗錯誤

PARMRK

奇偶校驗錯誤掩碼

ISTRIP

裁減掉第8位比特

IXON

啟動輸出軟件流控

IXOFF

啟動輸入軟件流控

IXANY

輸入任意字符可以重新啟動輸出(默認為輸入起始字符才重啟輸出)

IGNBRK

忽略輸入終止條件

BRKINT

當檢測到輸入終止條件時發(fā)送SIGINT信號

INLCR

將接收到的NL(換行符)轉(zhuǎn)換為CR(回車符)

IGNCR

忽略接收到的CR(回車符)

ICRNL

將接收到的CR(回車符)轉(zhuǎn)換為NL(換行符)

IUCLC

將接收到的大寫字符映射為小寫字符

IMAXBEL

當輸入隊列滿時響鈴

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

表6.13 c_oflag支持的常量名稱

OPOST

啟用輸出處理功能,如果不設(shè)置該標志,則其他標志都被忽略

OLCUC

將輸出中的大寫字符轉(zhuǎn)換成小寫字符

ONLCR

將輸出中的換行符(‘\n’)轉(zhuǎn)換成回車符(‘\r’)

ONOCR

如果當前列號為0,則不輸出回車符

OCRNL

將輸出中的回車符(‘\r’)轉(zhuǎn)換成換行符(‘\n’)

ONLRET

不輸出回車符

OFILL

發(fā)送填充字符以提供延時

OFDEL

如果設(shè)置該標志,則表示填充字符為DEL字符,否則為NUL字符

NLDLY

換行延時掩碼

CRDLY

回車延時掩碼

TABDLY

制表符延時掩碼

BSDLY

水平退格符延時掩碼

VTDLY

垂直退格符延時掩碼

FFLDY

換頁符延時掩碼

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

表6.14 c_lflag支持的常量名稱

ISIG

若收到信號字符(INTR、QUIT等),則會產(chǎn)生相應(yīng)的信號

ICANON

啟用規(guī)范模式

ECHO

啟用本地回顯功能

ECHOE

若設(shè)置ICANON,則允許退格操作

ECHOK

若設(shè)置ICANON,則KILL字符會刪除當前行

ECHONL

若設(shè)置ICANON,則允許回顯換行符

ECHOCTL

若設(shè)置ECHO,則控制字符(制表符、換行符等)會顯示成“^X”,其中X的ASCII碼等于給相應(yīng)控制字符的ASCII碼加上0x40。例如:退格字符(0x08)會顯示為“^H”(’H’的ASCII碼為0x48)

ECHOPRT

若設(shè)置ICANON和IECHO,則刪除字符(退格符等)和被刪除的字符都會被顯示

ECHOKE

若設(shè)置ICANON,則允許回顯在ECHOE和ECHOPRT中設(shè)定的KILL字符

NOFLSH

在通常情況下,當接收到INTR、QUIT和SUSP控制字符時,會清空輸入和輸出隊列。如果設(shè)置該標志,則所有的隊列不會被清空

TOSTOP

若一個后臺進程試圖向它的控制終端進行寫操作,則系統(tǒng)向該后臺進程的進程組發(fā)送SIGTTOU信號。該信號通常終止進程的執(zhí)行

IEXTEN

啟用輸入處理功能

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

表6.13 c_cc支持的常量名稱

VINTR

中斷控制字符,對應(yīng)鍵為CTRL+C

VQUIT

退出操作符,對應(yīng)鍵為CRTL+Z

VERASE

刪除操作符,對應(yīng)鍵為Backspace(BS)

VKILL

刪除行符,對應(yīng)鍵為CTRL+U

VEOF

文件結(jié)尾符,對應(yīng)鍵為CTRL+D

VEOL

附加行結(jié)尾符,對應(yīng)鍵為Carriagereturn(CR)

VEOL2

第二行結(jié)尾符,對應(yīng)鍵為Linefeed(LF)

VMIN

指定最少讀取的字符數(shù)

VTIME

指定讀取的每個字符之間的超時時間

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

1.保存原先串口配置

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

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

{

perror("tcgetattr");

return-1;

}

2.激活選項

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

newtio.c_cflag|=CLOCAL|CREAD;

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

cfmakeraw(&new_cfg);

3.設(shè)置波特率

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

cfsetispeed(&new_cfg,B115200);

cfsetospeed(&new_cfg,B115200);

一般地,用戶需將終端的輸入和輸出波特率設(shè)置成一樣的。這幾個函數(shù)在成功時返回0,失敗時返回-1。

4.設(shè)置字符大小

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

new_cfg.c_cflag&=~CSIZE;/*用數(shù)據(jù)位掩碼清空數(shù)據(jù)位設(shè)置*/

new_cfg.c_cflag|=CS8;

5.設(shè)置奇偶校驗位

設(shè)置奇偶校驗位需要用到termios中的兩個成員:c_cflag和c_iflag。首先要激活c_cflag中的校驗位使能標志PARENB和是否要進行偶校驗,同時還要激活c_iflag中的對于輸入數(shù)據(jù)的奇偶校驗使能(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.設(shè)置停止位

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

new_cfg.c_cflag&=~CSTOPB;/*將停止位設(shè)置為一個比特*/

new_cfg.c_cflag|=CSTOPB;/*將停止位設(shè)置為兩個比特*/

7.設(shè)置最少字符和等待時間

在對接收字符和等待時間沒有特別要求的情況下,可以將其設(shè)置為0,則在任何情況下read()函數(shù)立即返回,如下所示:

new_cfg.c_cc[VTIME]=0;

new_cfg.c_cc[VMIN]=0;

8.清除串口緩沖

由于串口在重新設(shè)置之后,需要對當前的串口設(shè)備進行適當?shù)奶幚恚@時就可調(diào)用在<termios.h>中聲明的tcdrain()、tcflow()、tcflush()等函數(shù)來處理目前串口緩沖中的數(shù)據(jù),它們的格式如下所示。

inttcdrain(intfd);/*使程序阻塞,直到輸出緩沖區(qū)的數(shù)據(jù)全部發(fā)送完畢*/

inttcflow(intfd,intaction);/*用于暫停或重新開始輸出*/

inttcflush(intfd,intqueue_selector);/*用于清空輸入/輸出緩沖區(qū)*/

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

n TCIFLUSH:對接收到而未被讀取的數(shù)據(jù)進行清空處理。

n TCOFLUSH:對尚未傳送成功的輸出數(shù)據(jù)進行清空處理。

n TCIOFLUSH:包括前兩種功能,即對尚未處理的輸入輸出數(shù)據(jù)進行清空處理。

如在本例中所采用的是第一種方法:

tcflush(fd,TCIFLUSH);

9.激活配置

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

tcsetattr(intfd,intoptional_actions,conststructtermios*termios_p);

其中參數(shù)termios_p是termios類型的新配置變量。

參數(shù)optional_actions可能的取值有以下3種:

n TCSANOW:配置的修改立即生效。

n TCSADRAIN:配置的修改在所有寫入fd的輸出都傳輸完畢之后生效。

n TCSAFLUSH:所有已接受但未讀入的輸入都將在修改生效之前被丟棄。

該函數(shù)若調(diào)用成功則返回0,若失敗則返回-1,代碼如下所示:

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

{

perror("tcsetattr");

return-1;

}

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

intset_com_config(intfd,intbaud_rate,

intdata_bits,charparity,intstop_bits)

{

structtermiosnew_cfg,old_cfg;

intspeed;

/*保存并測試現(xiàn)有串口參數(shù)設(shè)置,在這里如果串口號等出錯,會有相關(guān)的出錯信息*/

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

{

perror("tcgetattr");

return-1;

}

/*設(shè)置字符大小*/

new_cfg=old_cfg;

cfmakeraw(&new_cfg);/*配置為原始模式*/

new_cfg.c_cflag&=~CSIZE;

/*設(shè)置波特率*/

switch(baud_rate)

{

case2400:

{

speed=B2400;

}

break;

case4800:

{

speed=B4800;

}

break;

case9600:

{

speed=B9600;

}

break;

case19200:

{

speed=B19200;

}

break;

case38400:

{

speed=B38400;

}

break;

default:

case115200:

{

speed=B115200;

}

break;

}

cfsetispeed(&new_cfg,speed);

cfsetospeed(&new_cfg,speed);

/*設(shè)置停止位*/

switch(data_bits)

{

case7:

{

new_cfg.c_cflag|=CS7;

}

break;

default:

case8:

{

new_cfg.c_cflag|=CS8;

}

break;

}

/*設(shè)置奇偶校驗位*/

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':/*asnoparity*/

case'S':

{

new_cfg.c_cflag&=~PARENB;

new_cfg.c_cflag&=~CSTOPB;

}

break;

}

/*設(shè)置停止位*/

switch(stop_bits)

{

default:

case1:

{

new_cfg.c_cflag&=~CSTOPB;

}

break;

case2:

{

new_cfg.c_cflag|=CSTOPB;

}

}

/*設(shè)置等待時間和最小接收字符*/

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;

}

return0;

}

6.4.3串口使用詳解

在配置完串口的相關(guān)屬性后,就可以對串口進行打開和讀寫操作了。它所使用的函數(shù)和普通文件的讀寫函數(shù)一樣,都是open()、write()和read()。它們之間的區(qū)別的只是串口是一個終端設(shè)備,因此在選擇函數(shù)的具體參數(shù)時會有一些區(qū)別。另外,這里會用到一些附加的函數(shù),用于測試終端設(shè)備的連接情況等。下面將對其進行具體講解。

1.打開串口

打開串口和打開普通文件一樣,都是使用open()函數(shù),如下所示:

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

可以看到,這里除了普通的讀寫參數(shù)外,還有兩個參數(shù)O_NOCTTY和O_NDELAY。

n O_NOCTTY標志用于通知Linux系統(tǒng),該參數(shù)不會使打開的文件成為這個進程的控制終端。如果沒有指定這個標志,那么任何一個輸入(諸如鍵盤中止信號等)都將會影響用戶的進程。

n O_NDELAY標志通知Linux系統(tǒng),這個程序不關(guān)心DCD信號線所處的狀態(tài)(端口的另一端是否激活或者停止)。如果用戶指定了這個標志,則進程將會一直處在睡眠狀態(tài),直到DCD信號線被激活。

接下來可恢復(fù)串口的狀態(tài)為阻塞狀態(tài),用于等待串口數(shù)據(jù)的讀入,可用fcntl()函數(shù)實現(xiàn),如下所示:

fcntl(fd,F_SETFL,0);

再接著可以測試打開文件描述符是否連接到一個終端設(shè)備,以進一步確認串口是否正確打開,如下所示:

isatty(STDIN_FILENO);

該函數(shù)調(diào)用成功則返回0,若失敗則返回-1。

這時,一個串口就已經(jīng)成功打開了。接下來就可以對這個串口進行讀和寫操作。下面給出了一個完整的打開串口的函數(shù),同樣考慮到了各種不同的情況。程序如下所示:

/*打開串口函數(shù)*/

intopen_port(intcom_port)

{

intfd;

#if(COM_TYPE==GNR_COM)/*使用普通串口*/

char*dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};

#else/*使用USB轉(zhuǎn)串口*/

char*dev[]={"/dev/ttyUSB0","/dev/ttyUSB1","/dev/ttyUSB2"};

#endif

if((com_port<0)||(com_port>MAX_COM_NUM))

{

return-1;

}

/*打開串口*/

fd=open(dev[com_port-1],O_RDWR|O_NOCTTY|O_NDELAY);

if(fd<0)

{

perror("openserialport");

return(-1);

}

/*恢復(fù)串口為阻塞狀態(tài)*/

if(fcntl(fd,F_SETFL,0)<0)

{

perror("fcntlF_SETFL\n");

}

/*測試是否為終端設(shè)備*/

if(isatty(STDIN_FILENO)==0)

{

perror("standardinputisnotaterminaldevice");

}

returnfd;

}

2.讀寫串口

讀寫串口操作和讀寫普通文件一樣,使用read()和write()函數(shù)即可,如下所示:

write(fd,buff,strlen(buff));

read(fd,buff,BUFFER_SIZE);

下面兩個實例給出了串口讀和寫的兩個程序,其中用到前面所講述的open_port()和set_com_config()函數(shù)。寫串口的程序?qū)⒃谒拗鳈C上運行,讀串口的程序?qū)⒃谀繕税迳线\行。

寫串口的程序如下所示。

/*com_writer.c*/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<errno.h>

#include"uart_api.h"

intmain(void)

{

intfd;

charbuff[BUFFER_SIZE];

if((fd=open_port(HOST_COM_PORT))<0)/*打開串口*/

{

perror("open_port");

return1;

}

if(set_com_config(fd,115200,8,'N',1)<0)/*配置串口*/

{

perror("set_com_config");

return1;

}

do

{

printf("Inputsomewords(enter'quit'toexit):");

memset(buff,0,BUFFER_SIZE);

if(fgets(buff,BUFFER_SIZE,stdin)==NULL)

{

perror("fgets");

break;

}

write(fd,buff,strlen(buff));

}while(strncmp(buff,"quit",4));

close(fd);

return0;

}

讀串口的程序如下所示:

/*com_reader.c*/

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<errno.h>

#include"uart_api.h"

intmain(void)

{

intfd;

charbuff[BUFFER_SIZE];

if((fd=open_port(TARGET_COM_PORT))<0)/*打開串口*/

{

perror("open_port");

return1;

}

if(set_com_config(fd,115200,8,'N',1)<0)/*配置串口*/

{

perror("set_com_config");

return1;

}

do

{

memset(buff,0,BUFFER_SIZE);

if(read(fd,buff,BUFFER_SIZE)>0)

{

printf("Thereceivedwordsare:%s",buff);

}

}while(strncmp(buff,"quit",4));

close(fd);

return0;

}

在宿主機上運行寫串口的程序,而在目標板上運行讀串口的程序,運行結(jié)果如下所示。

/*宿主機,寫串口*/

$./com_writer

Inputsomewords(enter'quit'toexit):hello,Reader!

Inputsomewords(enter'quit'toexit):I'mWriter!

Inputsomewords(enter'quit'toexit):Thisisaserialporttestingprogram.

Inputsomewords(enter'quit'toexit):quit

/*目標板,讀串口*/

$./com_reader

Thereceivedwordsare:hello,Reader!

Thereceivedwordsare:I'mWriter!

Thereceivedwordsare:Thisisaserialporttestingprogram.

Thereceivedwordsare:quit

另外,讀者還可以考慮一下如何使用select()函數(shù)實現(xiàn)串口的非阻塞讀寫,具體實例會在本章的后面的實驗中給出。

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉