串口通信
串行接口是一種可以將接受來自CPU的并行數(shù)據(jù)字符轉(zhuǎn)換為連續(xù)的串行數(shù)據(jù)流發(fā)送出去,同時(shí)可將接受的串行數(shù)據(jù)流轉(zhuǎn)換為并行的數(shù)據(jù)字符供給CPU的器件。一般完成這種功能的電路,我們稱為串行接口電路。
串口通信(Serial Communications)的概念非常簡單,串口按位(bit)發(fā)送和接收字節(jié)。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時(shí)用另一根線接收數(shù)據(jù)。它很簡單并且能夠?qū)崿F(xiàn)遠(yuǎn)距離通信。比如IEEE488定義并行通行狀態(tài)時(shí),規(guī)定設(shè)備線總長不得超過20米,并且任意兩個(gè)設(shè)備間的長度不得超過2米;
而對(duì)于串口而言,長度可達(dá)1200米。典型地,串口用于ASCII碼字符的傳輸。通信使用3根線完成,分別是地線、發(fā)送、接收。由于串口通信是異步的,端口能夠在一根線上發(fā)送數(shù)據(jù)同時(shí)在另一根線上接收數(shù)據(jù)。其他線用于握手,但不是必須的。串口通信最重要的參數(shù)是波特率、數(shù)據(jù)位、停止位和奇偶校驗(yàn)。對(duì)于兩個(gè)進(jìn)行通信的端口,這些參數(shù)必須匹配。
a,波特率:這是一個(gè)衡量符號(hào)傳輸速率的參數(shù)。指的是信號(hào)被調(diào)制以后在單位時(shí)間內(nèi)的變化,即單位時(shí)間內(nèi)載波參數(shù)變化的次數(shù),如每秒鐘傳送240個(gè)字符,而每個(gè)字符格式包含10位(1個(gè)起始位,1個(gè)停止位,8個(gè)數(shù)據(jù)位),這時(shí)的波特率為240Bd,比特率為10位*240個(gè)/秒=2400bps。一般調(diào)制速率大于波特率,比如曼徹斯特編碼)。通常電話線的波特率為14400,28800和36600。波特率可以遠(yuǎn)遠(yuǎn)大于這些值,但是波特率和距離成反比。高波特率常常用于放置的很近的儀器間的通信,典型的例子就是GPIB設(shè)備的通信。
b,數(shù)據(jù)位:這是衡量通信中實(shí)際數(shù)據(jù)位的參數(shù)。當(dāng)計(jì)算機(jī)發(fā)送一個(gè)信息包,實(shí)際的數(shù)據(jù)往往不會(huì)是8位的,標(biāo)準(zhǔn)的值是6、7和8位。如何設(shè)置取決于你想傳送的信息。比如,標(biāo)準(zhǔn)的ASCII碼是0~127(7位)。擴(kuò)展的ASCII碼是0~255(8位)。如果數(shù)據(jù)使用簡單的文本(標(biāo)準(zhǔn) ASCII碼),那么每個(gè)數(shù)據(jù)包使用7位數(shù)據(jù)。每個(gè)包是指一個(gè)字節(jié),包括開始/停止位,數(shù)據(jù)位和奇偶校驗(yàn)位。由于實(shí)際數(shù)據(jù)位取決于通信協(xié)議的選取,術(shù)語“包”指任何通信的情況。
c,停止位:用于表示單個(gè)包的最后一位。典型的值為1,1.5和2位。由于數(shù)據(jù)是在傳輸線上定時(shí)的,并且每一個(gè)設(shè)備有其自己的時(shí)鐘,很可能在通信中兩臺(tái)設(shè)備間出現(xiàn)了小小的不同步。因此停止位不僅僅是表示傳輸?shù)慕Y(jié)束,并且提供計(jì)算機(jī)校正時(shí)鐘同步的機(jī)會(huì)。適用于停止位的位數(shù)越多,不同時(shí)鐘同步的容忍程度越大,但是數(shù)據(jù)傳輸率同時(shí)也越慢。
d,奇偶校驗(yàn)位:在串口通信中一種簡單的檢錯(cuò)方式。有四種檢錯(cuò)方式:偶、奇、高和低。當(dāng)然沒有校驗(yàn)位也是可以的。對(duì)于偶和奇校驗(yàn)的情況,串口會(huì)設(shè)置校驗(yàn)位(數(shù)據(jù)位后面的一位),用一個(gè)值確保傳輸?shù)臄?shù)據(jù)有偶個(gè)或者奇?zhèn)€邏輯高位。例如,如果數(shù)據(jù)是011,那么對(duì)于偶校驗(yàn),校驗(yàn)位為0,保證邏輯高的位數(shù)是偶數(shù)個(gè)。如果是奇校驗(yàn),校驗(yàn)位為1,這樣就有3個(gè)邏輯高位。高位和低位不真正的檢查數(shù)據(jù),簡單置位邏輯高或者邏輯低校驗(yàn)。這樣使得接收設(shè)備能夠知道一個(gè)位的狀態(tài),有機(jī)會(huì)判斷是否有噪聲干擾了通信或者是否傳輸和接收數(shù)據(jù)是否不同步。
串口通信屬性及事件解析
RS-232串口,串口按位(bit)發(fā)送和接收字節(jié)。盡管比按字節(jié)(byte)的并行通信慢,但是串口可以在使用一根線發(fā)送數(shù)據(jù)的同時(shí)用另一根線接收數(shù)據(jù)。典型地,串口用于ASCII碼字符的傳輸。通信使用3根線完成:
?。?)地線,
?。?)發(fā)送,
(3)接收。
本文以c#中的SerialPort類為例,分析串口各參數(shù)及事件,其他平臺(tái)串口庫的操作類似。
專門串口通信的朋友,建議參看《Visual C++串口通信工程開發(fā)實(shí)例導(dǎo)航》。
一、屬性
1. PortName 串口名 默認(rèn)值COM1
串口對(duì)于操作系統(tǒng)來說是一個(gè)文件,如果設(shè)置PortName為本機(jī)不存在的串口名(即文件名),如“COM7”或“COMK”,Open()打開串口將失敗,提示“端口COM7不存在”。
2. BaudRate 獲取或設(shè)置串行波特率bit/s 默認(rèn)值9600
比特率=波特率X單個(gè)調(diào)制狀態(tài)對(duì)應(yīng)的二進(jìn)制位數(shù)。
RS232是要用在近距離傳輸上最大距離為30M
RS485用在長距離傳輸最大距離1200M
3. DataBits 獲取或設(shè)置每個(gè)字節(jié)的標(biāo)準(zhǔn)數(shù)據(jù)位長度 默認(rèn)值8
當(dāng)計(jì)算機(jī)發(fā)送一個(gè)信息包,實(shí)際的數(shù)據(jù)不會(huì)是8位的,標(biāo)準(zhǔn)的值是5、7和8位。如何設(shè)置取決于你想傳送的信息。比如,標(biāo)準(zhǔn)的ASCII碼是0~127(7位)。擴(kuò)展的ASCII碼是0~255(8位)。如果數(shù)據(jù)使用簡單的文本(標(biāo)準(zhǔn) ASCII碼),那么每個(gè)數(shù)據(jù)包使用7位數(shù)據(jù)。每個(gè)包是指一個(gè)字節(jié),包括開始/停止位,數(shù)據(jù)位和奇偶校驗(yàn)位。由于實(shí)際數(shù)據(jù)位取決于通信協(xié)議的選取,術(shù)語“包”指任何通信的情況。
4. StopBits 獲取或設(shè)置每個(gè)字節(jié)的標(biāo)準(zhǔn)停止位數(shù) 默認(rèn)值One
用于表示單個(gè)包的最后一位。典型的值為1,1.5和2位。由于數(shù)據(jù)是在傳輸線上定時(shí)的,并且每一個(gè)設(shè)備有其自己的時(shí)鐘,很可能在通信中兩臺(tái)設(shè)備間出現(xiàn)了小小的不同步。因此停止位不僅僅是表示傳輸?shù)慕Y(jié)束,并且提供計(jì)算機(jī)校正時(shí)鐘同步的機(jī)會(huì)。適用于停止位的位數(shù)越多,不同時(shí)鐘同步的容忍程度越大,但是數(shù)據(jù)傳輸率同時(shí)也越慢。
5. Parity 獲取或設(shè)置奇偶校驗(yàn)檢查協(xié)議 默認(rèn)值None
在串口通信中一種簡單的檢錯(cuò)方式。有四種檢錯(cuò)方式:偶、奇、高和低。當(dāng)然沒有校驗(yàn)位也是可以的。對(duì)于偶和奇校驗(yàn)的情況,串口會(huì)設(shè)置校驗(yàn)位(數(shù)據(jù)位后面的一位),用一個(gè)值確保傳輸?shù)臄?shù)據(jù)有偶個(gè)或者奇?zhèn)€邏輯高位。例如,如果數(shù)據(jù)是011,那么對(duì)于偶校驗(yàn),校驗(yàn)位為0,保證邏輯高的位數(shù)是偶數(shù)個(gè)。如果是奇校驗(yàn),
校驗(yàn)位位1,這樣就有3個(gè)邏輯高位。高位和低位不真正的檢查數(shù)據(jù),簡單置位邏輯高或者邏輯低校驗(yàn)。這樣使得接收設(shè)備能夠知道一個(gè)位的狀態(tài),有機(jī)會(huì)判斷是否有噪聲干擾了通信或者是否傳輸和接收數(shù)據(jù)是否不同步。
6. ParityReplace 獲取或設(shè)置一個(gè)字節(jié),該字節(jié)在發(fā)生奇偶校驗(yàn)錯(cuò)誤時(shí)替換數(shù)據(jù)流中的無效字節(jié) 默認(rèn)值63(?)
7. ReadBufferSize 獲取或設(shè)置 SerialPort 輸入緩沖區(qū)的大小 默認(rèn)值4096
ReadBufferSize 屬性忽略任何小于 4096 的值??由于 ReadBufferSize 屬性只表示 Windows 創(chuàng)建的緩沖區(qū),而 BytesToRead 屬性除了表示 Windows 創(chuàng)建的緩沖區(qū)外還表示 SerialPort 緩沖區(qū),所以 BytesToRead 屬性可以返回一個(gè)比 ReadBufferSize 屬性大的值。
8. ReadTimeout 獲取或設(shè)置讀取操作未完成時(shí)發(fā)生超時(shí)之前的毫秒數(shù) 默認(rèn)值-1
確切的說ReadTimeout設(shè)置了Read(outBuf, offset, count)超時(shí)等待的時(shí)間,即如果接收緩沖區(qū)一直沒有數(shù)據(jù),則Read()等待ReadTimeout毫秒后甩TimeoutException異常。但是在ReadTimeout期間,只要有一個(gè)數(shù)據(jù),則Read()立馬返回,而不是等待count個(gè)字節(jié)數(shù)據(jù)。ReadTimeout不是為了Read()阻塞等待count個(gè)字節(jié),那它有什么意義?
9. ReceivedBytesThreshold 獲取或設(shè)置 DataReceived 事件發(fā)生前內(nèi)部輸入緩沖區(qū)中的字節(jié)數(shù) 默認(rèn)值1
如果緩沖區(qū)一次性有4個(gè)字節(jié)數(shù)據(jù),那么DataReceived事件是觸發(fā)1次還是4次?
10. WriteBufferSize 獲取或設(shè)置串行端口輸出緩沖區(qū)的大小 默認(rèn)值2048
ReadBufferSize 屬性忽略任何小于 4096 的值。
由于 ReadBufferSize 屬性僅表示 Windows 創(chuàng)建的緩沖區(qū),所以它可以返回比 BytesToRead屬性小的值,這表示 SerialPort 和 Windows 創(chuàng)建的緩沖區(qū)。
11. WreiteTimeout 獲取或設(shè)置寫入操作未完成時(shí)發(fā)生超時(shí)之前的毫秒數(shù) 默認(rèn)值-1
寫入超時(shí)值在 Win32 通信 API 中最初被設(shè)置為 500 毫秒。此屬性允許您設(shè)置此值。此值可以設(shè)置為 0 以立即從寫入操作返回,或設(shè)置為任意正值,也可以設(shè)置為默認(rèn)的 InfiniteTimeout。此屬性不影響 BaseStream 的 BeginWrite 方法。
12. BytesToRead 獲取接收緩沖區(qū)中數(shù)據(jù)的字節(jié)數(shù)
由于 ReadBufferSize 屬性只表示 Windows 創(chuàng)建的緩沖區(qū),而 BytesToRead 屬性除了表示 Windows 創(chuàng)建的緩沖區(qū)外還表示 SerialPort 緩沖區(qū),所以 BytesToRead 屬性可以返回一個(gè)比 ReadBufferSize 屬性大的值。
13. BytesToWrite 獲取發(fā)送緩沖區(qū)中數(shù)據(jù)的字節(jié)數(shù)
14. NewLine 獲取或設(shè)置用于解釋 ReadLine( )和WriteLine( )方法調(diào)用結(jié)束的值 默認(rèn)值“\n”
15. DiscardNull 獲取或設(shè)置一個(gè)值,指示 Null 字節(jié)在端口和接收緩沖區(qū)之間傳輸時(shí)是否被忽略 默認(rèn)值false
正常情況下,特別是對(duì)于二進(jìn)制傳輸而言,此值應(yīng)該設(shè)置為 false。將此屬性設(shè)置為 true 會(huì)使 UTF32 和 UTF16 編碼字節(jié)產(chǎn)生意外結(jié)果。
16. Handshake 獲取或設(shè)置串行端口數(shù)據(jù)傳輸?shù)奈帐謪f(xié)議 默認(rèn)值None
使用握手時(shí),將指示連接到 SerialPort 對(duì)象的設(shè)備在緩沖區(qū)中至少有 (ReadBufferSize-1024) 個(gè)字節(jié)時(shí)停止發(fā)送數(shù)據(jù)。當(dāng)緩沖區(qū)中的字節(jié)數(shù)小于等于 1024 時(shí),將指示設(shè)備重新開始發(fā)送數(shù)據(jù)。如果設(shè)備在大于 1024 個(gè)字節(jié)的塊中發(fā)送數(shù)據(jù),可能會(huì)導(dǎo)致緩沖區(qū)溢出。
如果將 Handshake 屬性設(shè)置為 RequestToSendXOnXOff 并將 CtsHolding 設(shè)置為 false,則不會(huì)發(fā)送 XOff 字符。如果后來將 CtsHolding 設(shè)置為 true,則必須發(fā)送更多的數(shù)據(jù)后才會(huì)發(fā)送 XOff 字符。
17. Encodeing 獲取或設(shè)置傳輸前后文本轉(zhuǎn)換的字節(jié)編碼 默認(rèn)為 ASCIIEncoding
ASCIIEncoding 不提供錯(cuò)誤檢測。出于安全原因,建議您使用 UTF8Encoding、UnicodeEncoding 或 UTF32Encoding 并啟用錯(cuò)誤檢測。
ASCIIEncoding 僅支持 U+0000 和 U+007F之間的 Unicode 字符值。因此,UTF8Encoding、UnicodeEncoding 和 UTF32Encoding 可以更好地適應(yīng)全球化的應(yīng)用程序。
18. DtrEnable 獲取或設(shè)置一個(gè)值,該值在串行通信過程中啟用數(shù)據(jù)終端就緒 (DTR) 信號(hào) 默認(rèn)值 false
在 XON/XOFF 軟件握手、請(qǐng)求發(fā)送/可以發(fā)送 (RTS/CTS) 硬件握手和調(diào)制解調(diào)器通信的過程中通常啟用數(shù)據(jù)終端就緒 (DTR)。
19. RtsEnable 獲取或設(shè)置一個(gè)值,該值指示在串行通信中是否啟用請(qǐng)求發(fā)送 (RTS) 信號(hào) 默認(rèn)值false
請(qǐng)求發(fā)送 (RTS) 信號(hào)通常用在請(qǐng)求發(fā)送/可以發(fā)送 (RTS/CTS) 硬件握手中。
20. CDHolding 獲取端口的載波檢測行的狀態(tài)
此屬性可用于監(jiān)視端口的載波檢測行的狀態(tài)。無載波通常表明接收方已掛斷且載波已被丟棄。
21. CtsHolding 獲取“可以發(fā)送”行的狀態(tài)
在請(qǐng)求發(fā)送/可以發(fā)送 (RTS/CTS) 硬件握手中使用可以發(fā)送 (CTS) 行。發(fā)送數(shù)據(jù)之前端口會(huì)查詢 CTS 行。
22. DsrHolding 獲取數(shù)據(jù)設(shè)置就緒 (DSR) 信號(hào)的狀態(tài)
在數(shù)據(jù)設(shè)置就緒/數(shù)據(jù)終端就緒 (DSR/DTR) 握手中使用此屬性。通常由調(diào)制解調(diào)器將數(shù)據(jù)設(shè)置就緒 (DSR) 信號(hào)發(fā)送到端口,以表明它已經(jīng)為數(shù)據(jù)傳輸或數(shù)據(jù)接收做好準(zhǔn)備。
23. BufferSize 值1024
24. maxDataBits 值8
25. minDataBits 值5
26. SERIAL_NAME 值\\Device\\Serial
二、方法
1. Open() 打開一個(gè)新的串行端口連接
2. Close() 關(guān)閉端口連接,將 IsOpen 屬性設(shè)置為 false,并釋放內(nèi)部 Stream 對(duì)象
3. Read(Byte[], int, int) 輸入緩沖區(qū)讀取一些字節(jié)并將那些字節(jié)寫入字節(jié)數(shù)組中指定的偏移量處
4. ReadByte() 從 SerialPort 輸入緩沖區(qū)中同步讀取一個(gè)字節(jié)
5. ReadChar() 從 SerialPort 輸入緩沖區(qū)中同步讀取一個(gè)字符
6. ReadExisting() 在編碼的基礎(chǔ)上,讀取 SerialPort 對(duì)象的流和輸入緩沖區(qū)中所有立即可用的字節(jié)
6. ReadLine() 一直讀取到輸入緩沖區(qū)中的 NewLine 值
7. ReadTo() 一直讀取到輸入緩沖區(qū)中的指定 value 的字符串
8. Write(string) 將指定的字符串寫入串行端口
9. Write(Byte[], int, int) 使用緩沖區(qū)的數(shù)據(jù)將指定數(shù)量的字符寫入串行端口
10. WriteLine() 將指定字符串和NewLine值寫入輸出緩沖區(qū)
11. DiscardInBuffer() 丟棄接收緩沖區(qū)的數(shù)據(jù)
12. DiscardOutBuffer() 丟棄發(fā)送緩沖區(qū)的數(shù)據(jù)
12. static GetPortNanes() 獲取當(dāng)前計(jì)算機(jī)的串口名稱數(shù)組
三、事件
1. DataReceive事件 數(shù)據(jù)接收事件的方法
不保證對(duì)接收到的每個(gè)字節(jié)引發(fā) DataReceived 事件。 使用 BytesToRead 屬性確定緩沖區(qū)中剩余的要讀取的數(shù)據(jù)量。從 SerialPort 對(duì)象接收數(shù)據(jù)時(shí),將在輔助線程上引發(fā) DataReceived 事件。
2. PinChanged事件 串行管腳更改事件的方法
在 SerialPort 對(duì)象進(jìn)入 BreakState 時(shí)引發(fā),但在端口退出 BreakState 時(shí)不引發(fā)。將在輔助線程上引發(fā) PinChanged 事件。
3. ErrorReceived事件 錯(cuò)誤事件的方法
如果在流的尾字節(jié)上出現(xiàn)奇偶校驗(yàn)錯(cuò)誤,將向輸入緩沖區(qū)添加一個(gè)值為 126 的額外字節(jié)。將在輔助線程上引發(fā) PinChanged 事件。
評(píng)論
查看更多