1. 程式人生 > >Linux串列埠通訊

Linux串列埠通訊

一、串口簡介

串列埠是計算機上的序列通訊的物理介面。計算機歷史上,串列埠曾經被廣泛用於連線計算機和終端裝置和各種外部裝置。雖然乙太網介面和USB介面也是以一個序列流進行資料傳送的,但是串列埠連線通常特指那些與RS-232標準相容的硬體或者調變解調器的介面。雖然現在在很多個人計算機上,原來用以連線外部裝置的串列埠已經廣泛的被USB和Firewire替代;而原來用以連線網路的串列埠則被乙太網替代,還有用以連線終端的串列埠裝置則已經被MDA或者VGA取而代之。但是,一方面因為串列埠本身造價便宜技術成熟,另一方面因為串列埠的控制檯功能RS-232標準高度標準化並且非常普及,所以直到現在它仍然被廣泛應用到各種裝置上。 某些計算機使用一個叫做UART的積體電路來作為串列埠裝置。這個積體電路可以進行字元和非同步序列通訊序列之間的轉換,並且可以自動地處理資料的時序。而某些低端裝置則會讓CPU直接通過輸出針來傳送資料,這種技術叫做bit-banging。 因為“串列埠”,RS-232和UARTs基本上總是在同一個語境中出現,所以這些名詞通常會被搞混。下面逐一解釋以下一些重要的名詞和術語。

1、什麼是序列通訊

計算機可以每次傳送一個或者多個位(bit)的資料。“序列”指的式每次只傳輸一位(1bit)資料。 當需要通過序列通訊傳輸一個字(word)的資料時,只能以每次一位的方式接收或者傳送。每個位可能是on(1)或者off(0)。很多技術術語中經常用mark表示on,而space表示off。

序列資料的速度通常用每秒傳輸的位元組數bits-per-second(bps)或者波特率(baud)表示。這個值表示的是每秒鐘被送出的0和1的個數。很久很久以前,300bps就是很快的速度了,而現在的電腦可以處理高達430,800的RS-232速率。表示波特率的單位還有kpbs和Mbps,1kps=1000bps而1Mbps=1000kbps。 一般有人提到序列裝置的時候,它通常說可能是某種資料通訊裝置-DCE(Data Communications Equipment)或者資料終端裝置-DTE(Data Terminal Equipment)。它們之間的區別非常簡單,每個訊號對,比如傳送和接收,它們倆正好是相反的。如果需要將兩個DTE或者DCE裝置連線起來的話,需要介面卡或者交叉線纜將訊號對交換。

2、什麼是RS-232

RS-232是EIA(Electronic Industries Association)定義的序列通訊的電器介面。RS-232事實上有三種(A,B和C),它們分別採用不同的電壓來表示on和off。最被廣泛使用的是RS-232C,它將mark(on)位元的電壓定義為-3V到-12V之間,而將space(off)的電壓定義到+3V到+12V之間。雖然RS-232C標準說訊號最遠被傳輸8m,但事實上你可以使用它傳輸更長的距離,直到訊號波特率已經小到不行了為止。 RS-232的連結線中除去用來傳入傳出資料的電線,還有一些用來提供時序,狀態和握手的電線:

RS-232 針腳定義

DB-25

針腳 描述 針腳 描述 針腳 描述 針腳 描述 針腳 描述
1 Earth Ground 6 DSR - Data Set Ready 11 Unassigned 16 Secondary RXD 21 Signal Quality Detect
2 TXD - Transmitted Data 7 GND - Logic Ground 12 Secondary DCD 17 Receiver Clock 22 Ring Detect
3 RXD - Received Data 8 DCD - Data Carrier Detecter 13 Secondary CTS 18 Unassigned 23 Data Rate Select
4 RTS - Request To Send 9 Reserved 14 Secondary TXD 19 Secondary RTS 24 Transmit Clock
5 CTS - Clear To Send 10 Reserved 15 Transmit Clock 20 DTR - Data Terminal Ready 25 Unassigned

DB-9

針腳 名稱 全名 方向(主機 外設)
3 TD Transmit Data ->
2 RD Receive Data <-
7 RTS Request To Send ->
8 CTS Clear To Send <-
6 DSR Data Set Ready <-
4 DTR Data Terminal Ready ->
1 CD Data Carrier Detect <-
9 RI Ring Indicator <-
5 - Signal Ground

另外兩個比較常見的序列介面的標準式RS-422和RS-574。RS-422使用更低的電壓和差分訊號,這樣可以將傳輸距離擴張到300m。而RS-574定義了通常可以見到的用在電腦上的9針聯結器和電壓。

3、訊號定義

RS-232標準定義了18個不同的序列通訊的訊號。而這些之中,僅僅有如下6個可以在UNIX環境中使用。

  • GND - Logic Ground

    從技術角度講,GND不能算是訊號。但是沒有它其他訊號都不能用了。基本上,logic ground有點像一個參考電壓,通過它來判斷哪個電壓表示正哪個電壓表示負。

  • TXD - Transmitted Data

    TXD訊號負載著從你的電腦或者裝置到另一端(比如調變解調器)的資料。Mark範圍的電壓被解析成1,而space範圍電壓被解析成0。

  • RXD - Received Data

    RXD於TXD正好相反。它負載著從另一端的電腦或者裝置上傳到你的工作站的資料。Mark和space的解析方法於TXD一致。

  • DCD - Data Carrier Detect

    DCD訊號通常來自串列埠連結線的另一端。這條訊號線上的space電壓表示另一端的電腦或者裝置現在已經連線。但是,DCD訊號線卻不是總可以得到的,有些裝置上有這條訊號線,而有的則沒有。

  • DTR - Data Terminal Ready

    DTR訊號是你的工作站產生的,用以告訴另一端的電腦或者裝置你已經是否已經準備好了。Space電壓表示準備好了,而mark電壓表示沒有準備好。當你在工作站上開啟序列介面時,DTR通常自動被設定位有效。

  • CTS - Clear To Send

    CTS則通常來自連結線的另一端。Space電壓表示你可以從工作站送出更多的資料。CTS通常用來協調你的工作站和另一端之間的序列資料流。

  • RTS - Request To Send

    如果RTS訊號被設定成space電壓,這表示你準備好了一些資料需要傳送。和CTS一樣,RTS也被用來協調工作站和另一端的電腦或者裝置之間的資料流。有些工作站上會一直將這個訊號設定位space。

4、非同步通訊

計算機為了弄懂傳給它的序列資料,它需要確定每個字元開始和結束的位置。這通常是用非同步序列資料來完成的。

在非同步模式中,除非有字元被傳輸,否則序列資料線總是處於mark(1)狀態。有一個start位會被加入傳輸字元的各個位之前,在字元本身的位之後會有一個可選的parity位和一個或者多個stop位。Start位總是space(0)並且它會告訴計算機新的序列資料過來了。資料可以隨時被送出或者接收,這就是所謂的非同步。

#ref(): File not found: "async.gif" at page "Linux串列埠程式設計詳解"

那個可選的parity位僅僅是所有傳輸位的和,這個和用以表示傳輸字元中有奇數個1還是偶數個1。在偶數parity中,如果有傳輸字元中有偶數個1,那麼parity位被設定成0,而傳輸字元中有奇數個1,那麼parity位被設定成1。在奇數parity中,位設定與此相反。還有一些術語,比如space parity, mark parity和no parity。Space parity是指parity位會一直被設定位0,而mark parity正好與此相反,parity會一直是1。No parity的意思就是根本不會傳輸parity位。 剩餘的位叫做stop位。傳輸字元之間可以有1個,1.5個或者2個stop位,而且,它們的值總是1。傳統上,Stop位式用給計算機一些時間處理前面的字元的,但是它只是被用來同步接收資料的計算機和接受的字元。 非同步資料通常被表示成"8N1","7E1",或者與此類似的形式。這表示“8資料位,no parity和1個stop bit”,還有相應得,“7資料位,even parity和1個stop bit”。

5、什麼是全雙工和半雙工

全雙工(Full duplex)是說計算機可以同時接受和傳送資料——也就是它有兩個分開的資料傳輸通道(一個傳入,一個傳出)。

半雙工(Half duplex)表示計算機不能同時接受和傳送資料,而在某一時刻它只能單一的傳送或者接收。這通常意味著,它只有一個數據通道。半雙工並不是說RS-232的某些訊號不能使用,而是,它通常是使用了有別於RS-232的其他不支援全雙工的標準。

6、什麼是流控制

兩個序列介面之間的傳輸資料流通常需要協調一致才行。這可能是由於用以通訊的某個序列介面或者某些儲存介質的中間序列通訊鏈路的限制造成的。對於非同步資料這裡有兩個方法做到這一點。

第一種方法通常被叫做“軟體”流控制。這種方法採用特殊字元來開始(XON,DC1,八進位制數021)或者結束(XOFF,DC3或者八進位制數023)資料流。而這些字元都在ASCII中定義好了。雖然這些編碼對於傳輸文字資訊非常有用,但是它們卻不能被用於在特殊程式中的其他型別的資訊。

第二種方法叫做“硬體”流控制。這種方法使用RS-232標準的CTS和RTS訊號來取代之前提到的特殊字元。當準備就緒時,接受一方會將CTS訊號設定成為space電壓,而尚未準備就緒時它會被設定成為mark電壓。相應得,傳送方會在準備就緒的情況下將RTS設定成space電壓。正因為硬體流控制使用了於資料分隔的訊號,所以與需要傳輸特殊字元的軟體流控制相比它的速度很快。但是,並不是所有的硬體和作業系統都支援CTS/RTS流控制。

7、什麼是BREAK

通常,直到有資料傳輸時,接收和傳輸訊號會保持在mark電壓。如果一個訊號掉到space電壓並且持續了很長時間,一般來說是1/4到1/2秒,那麼就說有一個break條件存在了。

BREAK經常被用來重置一條資料線或者用來改變像調變解調器這樣的裝置的通訊模式。

8、同步通訊

與非同步資料不同,同步資料是一個穩定的位元組流。為了能夠線上路上讀取到資料,計算機必須提供或者接受一個時鐘,這樣才能保證傳送端和接收端同步。儘管已經有同步時鐘,計算機還是必須以某種方式標誌資料流的開端。做這件事情最常見的辦法就是使用像Serial Data Link Control("SDLC")或者High-Speed Data Link Control("HDLC")這樣的資料包通訊協議。

這些協議每個都定義了一個確定的位元序列來表示資料包的開始和結束。當然,它們也定義了一個用來表示沒有資料傳輸的位元序列。這些位元序列可以幫助計算機識別資料包的開端。

因為同步協議可以不使用每個字元的同步位元位,所以通常它們的效能比非同步通訊快最少25%,而且一般比較適用於遠距離的網路連結或者有兩個串列埠介面的配置的情況。儘管同步通訊的速度有優勢,大部分RS-232硬體卻不支援它,因為同步通訊需要其他的硬體和軟體。

二、Linux下的串列埠通訊API

和其他裝置一樣,Linux也是通過裝置檔案來提供訪問串列埠的功能。當需要訪問串列埠的時候,你只需要open相應的檔案。

1、串列埠的裝置檔案

Linux系統上一般有一個或者多個串列埠,而這些串列埠裝置檔名字比較奇怪,如比下面這樣

串列埠裝置檔名

作業系統 串列埠1 串列埠2 USB/RS-232轉換器
Windows COM1 COM2 -
Linux /dev/ttyS0 /dev/ttyS1 /dev/ttyUSB0
2、開啟串列埠

因為串列埠和其他裝置一樣,在類Unix系統中都是以裝置檔案的形式存在的,所以,理所當然得你可以使用open(2)系統呼叫/函式來訪問它。但Linux系統中卻有一個稍微不方便的地方,那就是普通使用者一般不能直接訪問裝置檔案。你可以選擇以下方式做一些調整,以便你編寫的程式可以訪問串列埠。

  • 改變裝置檔案的訪問許可權設定 [#cd9bd1e0]
  • 以root超級使用者的身份執行程式 [#kdd0e577]
  • 將你的程式編寫位setuid程式,以串列埠裝置所有者的身份執行程式 [#s7b703ff]

OK.假如你已經準備好了讓串列埠裝置檔案可以被所有使用者訪問,你可以在Linux系統中實驗一下下面這個程式,它可以開啟計算機的串列埠1。

#include

#include

 #include

 #include /* File control definitions */

 #include 

 #include /* POSIX terminal control definitions */ 

 /* * 'open_port()' - Open serial port 1 * Returns the file descriptor on success or -1 on error. */ 

 int open_port(void) 

 {

int fd; /* File descriptor for the port */

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

     if (fd == -1) { /* * Could not open the port. */

       perror("open_port: Unable to open /dev/ttyS0 -");

     } else {

       fcntl(fd, F_SETFL, 0); return (fd);

     } 

 }

開啟檔案的選項

開啟串列埠連線的時候,程式在open函式中除了Read+Write模式以外還指定了兩個選項;

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

O_NOCTTY:可以告訴UNIX這個程式不會成為這個埠上的“控制終端”。如果不這樣做的話,所有的輸入,比如鍵盤上過來的Ctrl+C中止訊號等等,會影響到你的程序。而有些程式比如getty(1M/8)則會在開啟登入程序的時候使用這個特性,但是通常情況下,使用者程式不會使用這個行為。

O_NDELAY:則是告訴UNIX,這個程式並不關心DCD訊號線的狀態——也就是不關心埠另一端是否已經連線。如果不指定這個標誌的話,除非DCD訊號線上有space電壓否則這個程式會一直睡眠。

3、給埠上寫資料

給埠上寫入資料也很簡單,使用write(2)系統呼叫就可以傳送資料了:

n = write(fd, "ATZ\r", 4); if (n < 0) fputs("write() of 4 bytes failed!\n", stderr);

和寫入其他裝置檔案的方式相同,write函式也會返回傳送資料的位元組數或者在發生錯誤的時候返回-1。通常,傳送資料最常見的錯誤就是EIO,當調變解調器或者資料鏈路將Data Carrier Detect(DCD)訊號線弄掉了,就會發生這個錯誤。而且,直至關閉埠這個情況會一直持續。

4、從埠上讀取資料

從串列埠上讀取資料的時候就得耍花招了。因為,如果你在原資料模式(raw data mode)操作埠的話,每個read(2)系統呼叫都會返回從串列埠輸入緩衝區中實際得到的字元的個數。在不能得到資料的情況下,read(2)系統呼叫就會一直等著,只到有埠上新的字元可以讀取或者發生超時或者錯誤的情況發生。如果需要read(2)函式迅速返回的話,你可以使用下面這個方式:

fcntl(fd, F_SETFL, FNDELAY);

FNDELAY:可以保證read(2)函式在埠上讀不到字元的時候返回0。

需要回到正常(阻塞)模式的時候,需要再次在不帶FNDELAY標誌的情況下呼叫fcntl(2)函式:

fcntl(fd, F_SETFL, 0);

當然,如果你最初就是以O_NDELAY標誌開啟串列埠的,你也可在之後使用這個方法改變讀取的行為方式。

5、關閉串列埠

可以使用close(2)系統呼叫關閉串列埠:

close(fd);

關閉串列埠會將DTR訊號線設定成low,這會導致很多調變解調器掛起。

三、配置串列埠 1、POSIX終端介面

很多系統都支援POSIX終端(串列埠)介面。程式可以利用這個介面來改變終端的引數,比如,波特率,字元大小等等。要使用這個埠的話,你必須將標頭檔案包含到你的程式中。這個標頭檔案中定義了終端控制結構體和POSIX控制函式。

與串列埠操作相關的最重要的兩個POSIX函式可能就是tcgetattr(3)和tcsetattr(3)。顧名思義,這兩個函式分別用來取得設設定終端的屬性。呼叫這兩個函式的時候,你需要提供一個包含著所有串列埠選項的termios結構體:

termios結構體成員

成員 描述
c_cflag 控制選項
c_lflag 行選項
c_iflag 輸入選項
c_oflag 輸出選項
c_cc 控制字元
c_ispeed 輸入波特率(NEW)
c_ospeed 輸出波特率(NEW)
控制選項

通過termios結構體的c_cflag成員可以控制波特率,資料的位元數,parity,停止位和硬體流控制。下面這張表列出了所有可以使用的常數。

c_cflag常數

常量 描述
CBAUD Bit mask for baud rate
B0 0 baud (drop DTR)
B50 50 baud
B75 75 baud
B110 110 baud

相關推薦

Linux串列通訊

一、串口簡介 串列埠是計算機上的序列通訊的物理介面。計算機歷史上,串列埠曾經被廣泛用於連線計算機和終端裝置和各種外部裝置。雖然乙太網介面和USB介面也是以一個序列流進行資料傳送的,但是串列埠連線通常特指那些與RS-232標準相容的硬體或者調變解調器的介面。雖然現在在

Linux--串列通訊詳解

This chapter discusses how to configure a serial port from C using the POSIX termios interface. Most systems support the POSIX terminal (serial) interfac

Linux作業系統下的串列通訊學習筆記

一、什麼是串列埠通訊 串列埠通訊是指計算機主機與外設之間以及主機系統與主機系統之間資料的序列傳送。使用串列埠通訊時,傳送和接收到的每一個字元實際上都是一次一位的傳送的,每一位為1或者為0。 二、串列埠通訊的分類 串列埠通訊可以分為同步通訊和非同步通訊兩類。同步通訊是按照

linux 下基於特定通訊協議利用多執行緒同步通訊機制實現的串列通訊

</pre><pre name="code" class="cpp">/** *@Title:利用多執行緒同步通訊機制實現串列埠通訊 *@Introduce:主要完成根據特定的通訊協議實現串列埠與PC上特定串列埠 * 通訊軟體的通訊。測試版,只

target裝置主動通訊遇到linux串列預設模式的尷尬

issue:sahara fail,場景linux系統第一次開機時,切到9008下載口 高通提供了一種升級方式是firehose,它工作在9008口,firehose的執行程式需要由sahara寫入pbl。 firehose可以很好的工作在windows端,模組系統接入android,會生成/dev/tt

linux arm-tiny-6410實現串列通訊

#include <stdio.h> #include <string.h> #include <sys/types.h> #include <errno.h> #include <sys/stat.h> #include <fcnt

linux c/c++串列通訊

/*串列埠裝置無論是在工控領域,還是在嵌入式裝置領域,應用都非常廣泛。而串列埠程式設計也就顯得必不可少。 偶然的一次機會,需要使用串列埠,而且作業系統還要求是Linux,因此,趁著這次機會,綜合別人的程式碼, 進行了一次整理和封裝。具體的封裝格式為C程式碼,這樣做是為了很好的

Linux下C語言串列通訊

最近在做一個GPS專案,第一部分是將開發板和GPS用串列埠通訊,接受GPS上傳來的資料。Linux下所有的裝置都是以檔案形式儲存的,串列埠也是。整個串列埠通訊的流程圖為:所用到的標頭檔案為:#include<stdio.h>#include<fcntl.h&

linux下的串列通訊

2> 把串列埠線的一端短接(用金屬把2,3號腳連通),用萬用表測另一端的2,3號如果正常的話會有嘀嘀的短接報警聲。二、linux下串列埠的基本操作 1、串列埠的操作 1.1開啟:fd = open("/dev/ttySAC1", O_RDWR | O_NOCTTY | O_NDELAY);       

串列通訊程式設計詳解(Linux

rs232是三芯通訊,即DB9的第2引腳RXD(接收)、第3引腳TXD(傳送資料)、第5引腳DG(訊號地)。 rs232是三芯通訊,485是兩芯通訊的,RS-232串列埠線 通常 是 DB9--DB9 的 串列埠通訊線,9芯 RS-485資料線 是 雙絞線或者遮蔽雙絞線,2

Linux串列通訊詳解(上)開啟串列串列初始化詳解

linux下串列埠通訊主要有下面幾個步驟 串列埠通訊流程圖 下面我會一一介紹這幾個步驟。 1.開啟串列埠 程式碼(串列埠為ttyUSB0) //開啟串列埠 int open_port(void) { int fd; fd=open("/dev/ttyUSB0

Linux主機和VirtualBox之間實現串列通訊

Linux相關開發工作中,經常會用到串列埠,特別是嵌入式開發領域的,串列埠通訊一般是必不可少的。同時,它也是雙機除錯(如KGDB)的主要通訊渠道。 這裡以VirtualBox虛擬機器和Linux主機之間實現虛擬串列埠通訊。 環境: HOST:Deep

關於Linux串列通訊的一點心得

這幾天,由於長春門檢系統專案的需要,涉及到了讀卡器資訊的串列埠讀取,所以在Linux下串列埠資訊的讀取有了一點心得體會。 1.         開啟串列埠 與其他的關於裝置程式設計的方法一樣,在Linux下,操作、控制串列埠也是通過操作起裝置檔案進行的。在Linux下,串列埠的裝置檔案是/dev/ttyS0

Linux C開發之用modbus實現串列通訊

    想要讀取串列埠資料,modbus是一個很好用的第三方庫。該庫適用於windows和Linux,支援RTP、RTU等協議,基於Linux的開發較難一些,是我前段時間主要的研究方向。http://www.modbus.org/是modbus的主頁,有興趣的朋友可以檢視一

Linux串列程式設計教程(三)——串列程式設計詳(原始碼)解:http://blog.csdn.net/u011192270/article/details/48174353 Linux下的串列程式設計(二)----(圖文並茂,講解深刻)http://blog.csdn.net/w28252

Linux串列埠程式設計教程(三)——串列埠程式設計詳(原始碼)解:http://blog.csdn.net/u011192270/article/details/48174353 Linux下的串列埠程式設計(二)----(圖文並茂,講解深刻)http://blog.csdn.ne

Linux串列程式設計詳解 linux串列相關設定函式

tcgetattr    函式用於獲取與終端相關的引數。引數fd為終端的檔案描述符,返回的結果儲存在termios 結構體中 http://baike.baidu.com/view/5644808.htm?fr=aladdin tcset

MFC串列通訊例項

參考MSComm控制元件的用法和函式說明。裡面講得也算詳細了。所以這裡直接獻上原始碼示例。 github下載地址 CSDN下載地址 效果如圖: 需要注意的是: 1.如果想同時recv/send,則必須加個執行緒。 2.奇偶校驗中,引數設定為,無(n),偶校驗(o),

Linux串列程式設計

串列埠通訊是指一次只傳送一個數據位。雖然在通訊的時候串列埠有 8 位或者 9 位等,但是在物理層面傳輸的時候,它仍然是以單個 bit 的方式傳輸的 一般特指 RS232 標準的介面 在 linux 下串列埠程式設計流程如下: 開啟串列埠 核心是用op

Linux 串列驅動相關

Linux串列埠驅動相關主要涉及3個重要的結構體,uart_driver,uart_port,uart_ops。本文主要以msm8917平臺分析, 先貼dts相關程式碼 blsp1_uart2: [email protected]78b0000 { compatible

C++實現串列通訊上位機軟體

串列埠使用的是RS232匯流排進行通訊,通訊方式是半雙工。有兩種方式可以實現串列埠通訊,一種是通過ActiveX控制元件這種方法程式簡單,但欠靈活。第二個是可以通過呼叫Windows的API函式,本例程通過第二種方式。 一般通過四步來完成通訊(1)開啟串列埠(2)配置串列埠(3)讀寫串列埠(4)