1. 程式人生 > >串列埠讀寫問題,需要加入'\r'才能讀到資料

串列埠讀寫問題,需要加入'\r'才能讀到資料

  • 英文原文

    串列埠本身,標準和硬體 ?

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

    什麼是序列通訊 ?

    計算機可以每次傳送一個或者多個位(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裝置連線起來的話,需要介面卡或者交叉線纜將訊號對交換。

    什麼是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針聯結器和電壓。

    訊號定義 ?

    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。

    非同步通訊 ?

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

    在非同步模式中,除非有字元被傳輸,否則序列資料線總是處於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”。

    什麼是全雙工和半雙工 ?

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

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

    什麼是流控制 ?

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

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

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

    什麼是BREAK ?

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

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

    同步通訊 ?

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

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

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

    使用者看到的串列埠和使用者空間的串列埠程式設計 ?

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

    串列埠的裝置檔案 ?

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

    串列埠裝置檔名

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

    開啟串列埠 ?

    因為串列埠和其他裝置一樣,在類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電壓否則這個程式會一直睡眠。

    給埠上寫資料 ?

    給埠上寫入資料也很簡單,使用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)訊號線弄掉了,就會發生這個錯誤。而且,直至關閉埠這個情況會一直持續。

    從埠上讀取資料 ?

    從串列埠上讀取資料的時候就得耍花招了。因為,如果你在原資料模式(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標誌開啟串列埠的,你也可在之後使用這個方法改變讀取的行為方式。

    關閉串列埠 ?

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

    close(fd);

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

    配置串列埠 ?

    POSIX終端介面 ?

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

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

    termios結構體成員

    成員 描述
    c_cflag

    相關推薦

    串列問題需要加入'\r'才能資料

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

    FIFO阻塞式的開啟和管道阻塞式的

    最近看網路程式設計卷2時,對其中的圖4-21表格的內容感覺翻譯得比較生澀,這裡自己通過程式驗證後重新用自己的語言組織了一下。 一、對於FIFO,需要open去開啟FIFO的讀端或是寫端的描述符。 1> 如果open的時候沒有指定O_NONBLOCK標誌,且open的是

    串列將讀取的內容在檔案裡以及一些檔案的操作

    串列埠讀寫操作(上) 隔了好多天,終於要來發布我的第二篇心得了。鑑於之前寫過的一些關於檔案讀寫的操作,這次我要寫的是對串列埠的讀寫以及一些操作。 以下是關於串列埠定義的一些函式。

    QT4串列通訊(QT4需要用第三方庫QT5自帶串列通訊)

    在Qt5之前的版本中並沒有特定的串列埠控制類,現在大部分人使用的是第三方寫的qextserialport類,本文章主要是講解怎樣利用此類實現串列埠通訊。 2、檔案下載地址:      http://sourceforge.net/projects/qextserialport/files/ 3、檔案內容:

    在linux上串列程式後利用windows上的串列除錯助手互發資料

    我是用QT4在Linux上寫的串列埠程式,具體的程式碼就不寫了,網上搜一下很多。這裡主要說一下寫完程式碼之後,之前也行。要做的事情。 1,使用命令在終端上檢視有哪些串列埠驅動。 可以看出ttyS0 ttyS1能用 .一般ttyS0指com1,ttyS1指co

    openwrt韌體串列flash

    原文地址:http://blog.chinaunix.net/uid-25631578-id-4011568.html AR系列分割槽地址 4M flash的分割槽地址:分割槽名      

    利用async和await異步操作解決node.js裏面fs模塊異步同步結果的問題

    地獄 一個 cnblogs resolv 我們 瀏覽器 問題 分開 不容易 async await 解決異步問題,這兩個關鍵字是es7提出的,所以測試,node和瀏覽器版本提高一些 async await 操作基於promise實現的 async await這兩個關鍵字

    Go語言的文件操作:文件的文件的新建打開和刪除

    文件讀取 and 調用 inux 一個 find %s 刪除 數據 # 建立與打開文件 // 新建文件可以通過如下兩個方法: func Create(name string) (file *File, err Error) 根據提供的文件名創建新的文件,返回一個文件對象,默

    使用Java驅動ACR122U對IC卡進行總結

    1。站在他的肩膀上,快速的看完,動手自己實戰了下。對過程寫下總結。總歷時3.5小時。 2。手上有一個ACR122U,讀卡器。不貴有條件的買一個,畢竟是神器,很好用。 3。那文中提示的JavaCard文件,和,ACR官方的文件。很重要,是核心內容。 就像數學中的公式概念,定義。沒有它,

    ajax提交 data中包含陣列時(list)需要加入引數traditional:true

    需要加入引數traditional:true,伺服器端提取資料時使用request.POST.getlist("key")獲取到一個數組 $.ajax({ url:"/XXX/", data:{"key":[11,22,33]}, dataType:JSON, t

    java檔案

    /**  *   */ package com.struts2.other; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.F

    [轉]web串列除錯助手瀏覽器控制串列裝置

    本文轉自:https://blog.csdn.net/ldevs/article/details/39664697 開啟串列埠時查詢可用串列埠供選擇   通過javascript呼叫activex控制串列埠收發資料,可以通過輪詢每個串列埠狀態找到指定的裝置,簡化使用者操作 選擇並開啟串列埠

    學習筆記四 檔案集合元組函式

    一、檔案讀寫幾種模式總結: 讀模式: r 開啟不存在的檔案會報錯、不能寫(不能呼叫write方法),可以讀(能呼叫read方法) 寫模式: w # 1、開啟不存在的檔案,會新建一個檔案,但每次開啟都會清空原有檔案內容       # 2、不能讀(不能呼叫read方法),可以寫(能呼叫write方法)

    檔案的定位檔案的相關操作

    什麼是定位? <1>獲取當前讀寫的位置 在讀寫檔案的過程中,如果想知道當前的位置,可以使用tell()來獲取 # 開啟一個已經存在的檔案 f = open("test.txt", "r") str = f.read(3) print "讀取的資料是 : ",

    Qt 檔案的將讀取的資料儲存到Qvector

    #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {

    檔案函式元組和集合

    1、檔案讀寫 f = open('day4','r+',encoding = 'utf-8') #讀模式 r 開啟不存在的檔案會報錯、只能讀、不能寫 #寫模式 w #1、開啟不存在的檔案,會新建一個檔案,會清空原有檔案 #2、不

    串列通訊中解決serialport.DataReceived接收到的資料不完整

    private SerialPort serialport = new SerialPort(); private StringBuilder builder = new StringBuilder(); // private String

    STM32F10在iap和app模式下除錯模式串列可以通訊下載後卻不能通訊的問題

    開發環境:iar for arm ,開發晶片是STM32F103, 問題點:在除錯模式下,usart1可以接受和傳送資料,但是下載到晶片內部時,或者使用iap升級之後就出現資料無法接受的問題。 第一就像想到的啟動檔案和中斷向量表沒有配置好: 如圖所示:ICF配置 對比之

    Python-OpenCV基礎:影象的尺寸和儲存

    為什麼使用Python-OpenCV 雖然python 很強大,而且也有自己的影象處理庫PIL,但是相對於OpenCV 來講,它還是弱小很多。跟很多開源軟體一樣OpenCV 也提供了完善的python 介面,非常便於呼叫。OpenCV 的穩定版是2.4.8,最新版是4.0,包含了超過2500

    JS:對txt檔案進行替換和新增

    親測必須將程式碼放在記事本中,改成html格式,在用IE執行(必須) <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/h