http://wpp9977777.blog.163.com/blog/static/4625100720138495943540/
串口通訊是電子工程師和嵌入式開發工程師面對的最基本問題,RS232則是其中最簡單最常用的通訊方式。但是初學者往往搞不清有關的名詞如UART和RS232或RS485之間是什么關系,因為它們經常被放到語句中同等的位置使用。在百度搜索二者的區別,可以看到排在最前面的答案充斥着混淆的概念。就此,談談我對這幾個概念的理解,希望能幫初學者厘清它們之間的關系。
~
~
公交運行可以簡單分成兩個部分:
通訊問題,和交通是一樣的。串口通信,我們這里可以用公交來類比。


1、車站
2、公路
其中車站決定了車上裝什么(人),怎么發送(班次)等。
當汽車跑在路上,就要遵守公路交通的規則,過橋有過橋的規則,高速有高速的規則,和車站沒有關系了。
~
回到串口通訊,其實,UART就相當於車站,而RS232/RS485則對應於公路的規則。
UART,是通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter),既然是“器”,顯然,它就是個設備而已,要完成一個特定的功能的硬件,它本身並不是協議。那么它要完成什么功能呢?它的最基本功能,是串行數據和並行數據之間的轉換。我們知道,計算機中的數據以Byte為基本單位,對一個Byte的存取是並行的,即,同時取得/寫入8個bit。而串行通信,需要把這個Byte“打碎”,按照時間順序來收發以實現串行。例如:
內存中的數據是: 1 1 1 0 0 1 0 1
串行發送的實際效果是(按時間排序【注1】):
1
0
1
0
0
1
1
1
接收則是上述過程的逆過程。
這就是UART做的最基本工作,進一步的,它還要控制“發車的班次”,比如確認一個Byte的這8個bit是什么時候開始的,又是什么時候結束的,兩個班次之間至少要隔多長時間的緩沖,等等。這一部分,也具有協議的特征,但是相對於道路上的協議,更具有一般性,或曰,是與車在什么道路上開,相對獨立的。
那么道路上的規定是什么樣的呢?
RS232/RS485,是兩種不同的電氣協議,也就是說,是對電氣特性以及物理特性的規定,作用於數據的傳輸通路上,它並不內含對數據的處理方式。比如,最顯著的特征是:RS232使用3-15v有效電平,而UART,因為對電氣特性並沒有規定,所以直接使用CPU使用的電平,就是所謂的TTL電平(可能在0~3.3V之間)。更具體的,電氣的特性也決定了線路的連接方式,比如RS232,規定用電平表示數據,因此線路就是單線路的,用兩根線才能達到全雙工的目的;而RS485, 使用差分電平表示數據,因此,必須用兩根線才能達到傳輸數據的基本要求,要實現全雙工,必需用4根線。但是,無論使用RS232還是RS485,它們與UART是相對獨立的,但是由於電氣特性的差別,必須要有專用的器件和UART接駁,才能完成數據在線路和UART之間的正常流動。

RS232甚至規定了接口的具體樣式,圖為DB9接口
~
總結:從某種意義上,可以說,線路上存在的僅僅是電流,RS232/RS485規定了這些電流在什么樣的線路上流動和流動的樣式;在UART那里,電流才被解釋和組裝成數據,並變成CPU可直接讀寫的形式。
~
~
【注1】這里是例子是小端發送模式,是基本的串口傳輸方式,但是,大端模式的串口傳輸模式也是存在的,少見而已。
編程區別:
Linux下串口編程沿襲了Unix的POSIX標准,編程時只要包含<termios.h>,然后調用tcgetattr tcsetattr等函數,就可以完成對串口波特率,啟停位,校驗方式等的設置。
有人會問,這些設置里,看不到對RS232或者RS485的區分啊,對於這兩種協議沒有編程的區別嗎?
其實,看了我這篇
講UART和RS232和RS485關系的文章的話,就會理解:RS232和RS485定義是電氣特性,影響的是數據在線路上的傳輸過程,RS232和RS485的收發器通過UART才能被CPU訪問,所以,只要控制了UART,就可以控制串口的傳輸方式,而所謂的編程其實就是對UART編程,所以RS232個RS485從程序員視角是不可見的。
“那你就直接說RS485和RS232編程上沒有區別不就完了?”
問題是,實際總比理論復雜,這里有一種例外:
RS232用兩根線實現全雙工,兩根線各做各的,互不影響,可以同時進行;RS485雖然可以用四根線實現全雙工,但是實際應用中比較少見,更常見的是只用兩根線實現半雙工,這樣一來,就涉及到“收狀態”和“發狀態”的切換,這一切換又涉及兩種情況:
1、驅動程序中已經含有對半雙工情況下的接受切換,驅動程序會根據你讀或寫的動作,自動進行切換。這種情況下,RS485的編程就與RS232完全沒有區別。
2、驅動程序不帶自動切換,此時,為了完成切換,必須使用額外的GPIO連接RS485收發模塊的接受使能端,在接受、發送數據之前,首先對使能端置位,使之處於正確的“接收”或“發送”狀態。