淺談總線通信機制(通信基礎+串口+I2C)
總線的應用非常廣泛,在計算機領域來說。
(1)按系統(tǒng)總線傳輸信息的方式可以分為以下三種:
1、數(shù)據(jù)總線
2、地址總線
3、控制總線
(2)按照總線的使用范圍又可以分為很多很多種:
比如串口通信,計算機外設通信,網(wǎng)絡通信等等。
(3)按數(shù)據(jù)傳送方式的方式可以分為以下兩種:
1、串行傳輸總線
2、并行傳輸總線
當然還有其它的分類,非常非常的多,所以在學習的過程中,把握主體,其它的都是從一個概念中衍生出來的。
那什么是總線呢?總線就是連接多個部件的信息傳輸線,是各個器件共享的傳輸介質。
其實不管是什么通信,本質上其實只有串行和并行。
當有很多個器件和連接到總線上時候,如果出現(xiàn)兩個或者兩個以上器件同時對總線發(fā)送信息的時候,這就勢必會導致競爭關系,也就是到底誰先誰后的問題,這樣會導致通信過程中信號與信號之間產生沖突,就比如說,追求一個女孩(總線),我(器件)也喜歡她,你(器件)也喜歡她,但按照常理,她只能選一個她喜歡的,信得過得男孩,談到合適的時候就結婚對吧?這個時候假設她已經(jīng)有喜歡的男孩了,那么她就有這個男孩相關的信息,這點類比成一個ID好吧,每個追求者都是一個ID,由總線去匹配這個ID,最后才能連接。所以正是考慮到這樣的原因,就有這么一個規(guī)定,在某一個時刻,只允許有一個器件向總線發(fā)送信息,而多個器件可以同時從總線上接收相同的信息,這就更好解釋了,就拿剛剛說的男女關系,我(器件)和你(器件)都追求這個女孩(總線),而現(xiàn)在這個女孩(總線)選擇了我(器件),那么我(器件)和女孩(總線)之間就是戀愛關系(連接)了,當你或者更多的男孩(一個器件或者多個器件)要去追求女孩(總線)的時候,她(總線)會毫不猶豫的告訴你(器件):我有男朋友了,請你們離我遠點?。?!(總線發(fā)廣播,告訴所有的器件,所有的器件就可以同時從總線上接收信息)。當然,他們也可以分手啊,這就不用我說了吧,自己聯(lián)想,道理也是一樣的。純屬個人的理解,我覺得這樣適合我理解哈,如有說得不對的地方,請多多指教。
總線實際上是由許多傳輸線或者通路組成的,每條線可以一位一位的傳輸,這些位可以在規(guī)定的時間里傳輸完成,也可以在一定的時間內,多位同時傳輸;這就是串行通信和并行通信。什么是串行?簡單的理解吧,串行就是一條路,一次過一輛車或者過一個人。那什么又是并行?并行就是多條路,多輛車或者多個人同時過多條路,從效率上看,并行的效率肯定比串行高,這是肯定的,毫無疑問,有點常識的人都應該知道;打個比方,你去坐地鐵,沒有位置的時候,你是喜歡跟別人一起擠著還是喜歡站得寬敞點舒服點?正常人肯定希望寬敞點舒服點啦,就這么個道理。那么,從成本上來講,比如設計同樣長度的傳輸線,這個時候,并行傳輸肯定比串行傳輸?shù)某杀疽叩枚嗔耍热缧抟粭l1000米的路成本貴一點還是修多條1000米的路成本貴一點?并行傳輸在這時候耗費的資源遠遠比串行傳輸要多得多了,為什么?串行傳輸一條線(MCU用一個IO)就可以完成多個位的傳輸,只是耗費的時間長而已,這是劣勢。并行傳輸需要使用多條線(MCU使用多個IO)發(fā)送多個位,但節(jié)省了相應的時間。所以一般情況下,并行通信適合近距離傳輸,通常小于30m,而串行通信比并行通信更適合遠距離傳輸,可以從幾米到上千公里。
串行和并行通信的數(shù)據(jù)傳送速率都與距離成反比。在短距離內,并行通信傳輸效率比串行通信傳送的速率高很多,但隨著大規(guī)模和超大規(guī)模集成電路發(fā)展,數(shù)字電路組成的邏輯驅動器件的價格相對來說價格便宜,但通信線路的費用越來越高,因此對遠距離通信而言,采用串行通信的費用遠遠要比采用并行通信的費用要低得多。
從數(shù)據(jù)的傳輸方式角度來說就是串行和并行這兩種,相信大家也理解了。那么從數(shù)據(jù)的通信方向來說,就會分單工,半雙工,全雙工。從概念上來說:
1、單工:在任何時刻都只能進行一個方向的通訊,即一個固定為發(fā)送設備,另一個固定為接收設備。
2、半雙工: 兩個設備之間可以收發(fā)數(shù)據(jù),但不能在同一時刻進行。
3、全雙工:在同一時刻,兩個設備之間可以同時收發(fā)數(shù)據(jù)。
概念一看對于不理解的人來說就難以理解,只是了解,但實際是怎么樣的他可能不知道。那么舉個簡單的例子得了,這樣大家很快就懂了。
就拿道路與交通來做個類比吧。
單工是什么?單工就類似一個只允許單方向運行的車道,在任何時刻,只允許一輛車向同一個方向走,不允許逆行。
半雙工是什么?半雙工就類似一條道路,在有人過來的時候,你過不去,當這個人過來了,你可以過去。
全雙工是什么?全雙工就類比成兩條車道,同一時間,兩方的車都可以走,互不干擾,互不影響。
這樣的例子夠形象吧,相信一看就懂了,不用解釋哈哈。
傳輸過程中,根據(jù)數(shù)據(jù)傳輸?shù)姆绞讲煌?,可以分為同步和異步兩種。
(1)同步,從字面上來理解,就是同一個時間內雙方都在同時做一件事情,比如去公園跳廣場舞吧,肯定有個領頭的對吧?然后就是跟著領頭一起跳舞的一群人了,他們跳舞是根據(jù)一個音樂來跳的,把握好音樂的節(jié)奏,比劃不同的動作出來,這樣遠遠一看過去,很壯觀對吧,這就需要音樂和人比劃的動作進行相互協(xié)調,這樣才能同步。這在通信中,通常就相當于時鐘線和數(shù)據(jù)線;也就是說,在時鐘線啟動到結束,數(shù)據(jù)線都要跟著時鐘的頻率進行傳輸。
(2)異步,相對于同步來說了,異步雙方不需要共同的時鐘,也就是接收方不知道發(fā)送方什么時候發(fā)送,所以在發(fā)送的信息中就要有提示接收方開始接收的信息,如開始位,同時在結束時有停止位,在開始位和停止位之間就是數(shù)據(jù)了。
所以,從結果來看,同步傳輸?shù)男畔⒒径际侵苯油竭^來數(shù)據(jù),而異步因為包含各種各樣的開始位,停止位,甚至還有數(shù)據(jù)校驗位等等,所以同步傳輸?shù)拿黠@效率要比異步要高得多得多。
在嵌入式領域中,使用串行異步通信的協(xié)議還是挺多的。比如我們接下來要說到的串口,串口協(xié)議就是異步通信的協(xié)議。
那么,什么又是協(xié)議?把話挑明白點說,就是雙方約定好一定的規(guī)則來做,不然我們去辦理一些業(yè)務的時候,一般業(yè)務員都要你簽一個協(xié)議,那個協(xié)議就是約束你和業(yè)務本身的一個規(guī)則。當然,在計算機通信中,也不例外的。
那串口通信又是怎么約定的呢?首先肯定得有電路連接圖對吧:
MCU要和PC機相連,中間多了一個MAX232芯片,它是用來干嘛的呢?其實就是用于電平轉換用的,就是以下電平做轉換,才能相互進行通信。
通常,串口通信由一個起始位,多個數(shù)據(jù)位,一般是8位,或者8位以下,從一個字節(jié)的低位開始傳輸,傳輸完畢后傳輸停止位,這就是一個基本的串口協(xié)議,當然這個協(xié)議中也可以安插一些空閑位,還有奇偶校驗位。我們可以很形象的用一幅圖來表示:
那串口也不能隨便發(fā),假設我是主機,我發(fā)得很快,從機卻接收得很慢,那會造成什么樣的影響?每秒傳輸多少數(shù)據(jù)?那么這里就出現(xiàn)了波特率這個概念。波特率是什么東西?簡單的說,波特率就是每秒傳輸?shù)奈粩?shù),單位是fps/s
常用的波特率有115200、9600、4800等等。
比如,現(xiàn)在我使用波特率為115200,請問1s鐘傳輸多少KB的數(shù)據(jù)?
答:115200 / 8bit / 1024 = 14KB
所以串口傳輸?shù)乃俣绕鋵嵤呛苈苈?,一秒鐘?4KB,真的很慢了。
光說不練假把戲,沒有經(jīng)過驗證的東西不能就說它一定是對的,即使是書本的知識。
[cpp] view plain copy
/**
* @brief ?÷oˉêy
* @param ?T
* @retval ?T
*/
int main(void)
{
int i ;
unsigned char ch = 'a' ;
USART_Config(); //配置串口 波特率:115200 8bit數(shù)據(jù) 0個校驗位 1個停止位
while(1)
{
//發(fā)送一個字節(jié)
Usart_SendByte(DEBUG_USARTx,ch);
for(i = 0 ; i < 50000 ; i++) ;
}
}
下面我使用Saleae Logic 1,1,15來分析一幀串口協(xié)議,使用STM32開發(fā)板作為實驗,向PC發(fā)送一個字節(jié)的數(shù)據(jù),然后用邏輯分析儀連上Rx口,即可得到以下數(shù)據(jù):
上面的圖片有一個地方寫錯了,手抖打少了一個0,解析出來得,1000 0110.
我們只是截取了其中一幀數(shù)據(jù)進行分析,由于這個程序是無線循環(huán),所以實際上從邏輯分析儀得到的結果是這樣的:
因此,我們來總結一下上面寫的內容的關鍵部分。
數(shù)據(jù)通信的種類有:串行通信、并行通信。不管是什么類型的通信,再怎么復雜的,也是在這兩種上面衍生出來的。
數(shù)據(jù)通信的傳輸方向又有:單工、半雙工、全雙工。它們之間各有什么樣的特點,我舉了車輛過道的實例,通俗易懂的跟大家講明白了。
數(shù)據(jù)通信的方式還可以分為:同步、異步。什么是同步?什么是異步?相信大家現(xiàn)在已經(jīng)有個概念了吧?同步就是根據(jù)一定的時鐘周期,做一定的事情,這里我舉了廣場舞的例子,那異步又是什么呢?異步就是隨時都可以,但怎么來區(qū)分開始,動作和結束呢?這就需要一幀數(shù)據(jù)里面安插開始傳輸位、數(shù)據(jù)內容、結束位以作區(qū)分,然后還需要一定的傳輸頻率,這樣才能將數(shù)據(jù)發(fā)送出去。
而串口協(xié)議又是什么東西呢?串口協(xié)議就是一種串行異步通信協(xié)議。有協(xié)議還不行,得有硬件接口嘛,具體是什么就不說了。然后雙方都約定好,比如通信雙方都設置波特率115200,一次發(fā)8bit數(shù)據(jù),0個校驗位,1個停止位。接下來就開始發(fā)數(shù)據(jù),這時候就按照協(xié)議的規(guī)范,發(fā)送端開始發(fā)送一個起始位,通常是0,然后開始傳輸8bit數(shù)據(jù),如果需要校驗,那么就傳輸校驗位,最后再傳輸1bit的停止位,這樣一幀數(shù)據(jù)就發(fā)完了。
接下來,我們來說說I2C協(xié)議,I2C協(xié)議是什么鬼?I2C是(Inter-Integrated Circuit)的英文縮寫,是Philips公司開發(fā)的一個通信協(xié)議,只有兩根線是用來通信的。簡單的來說,如下圖:
我先來說下上面這幅圖具體是什么含義,然后接下來再來說說I2C是怎么操作數(shù)據(jù)的。I2C總線就是通過SDA總線(數(shù)據(jù))、SCL總線(時鐘)來傳輸數(shù)據(jù)的,那為什么I2C總線上還要接兩個上拉電阻呢?根據(jù)I2C規(guī)格設計上手冊上了解到,由于I2C接口設計大多采用的是集電極開路或者是開漏輸出的接口,當總線為空閑的時候,兩根線均為高電平,由于I2C的SDA和SCL都具有線與功能,什么是線與?線與就是有0為0,同1為1,這是數(shù)字電路邏輯相關的了。也就是說只要有一個節(jié)點對總線(SCL或者SDA)發(fā)送了低電平,那么這整根線就會呈現(xiàn)為低電平,你想想,協(xié)議都說了,空閑要高電平,你突然給它來個低電平,這不逗死人嘛?這還叫協(xié)議?這明顯就是亂搞嘛,是不是?所以既然是協(xié)議,那I2C就肯定會有約束條件嘛,這個上拉電阻的其中一個作用就在這里了,給硬件電路的IO口提供一個確定的電平信號。
說到這里,可能有人要問了,我是寫代碼的,硬件我不太熟悉或者根本就不懂啊?他們可能會提出這樣的問題:什么是集電極開路輸出?什么是開漏輸出?什么是上拉電阻?上拉電阻取值要取什么值,這個電阻取大取小對I2C通信的時候有什么影響,應該取什么值最合適?既然有上拉電阻,那是不是有下拉電阻?為什么我看有些I2C的外設接在MCU的IO口里,也沒有看見接上拉電阻啊,那為什么通信也正常?
下面咱們就來說說這些問題該怎么來解答,那什么問題好解釋,我們先從硬件電路開始下手,一步一步的分析上面的這些問題。
我們先來看一個簡單的電路:
想象一下,如果現(xiàn)在把B點上面那一部分去掉了,變成下面這樣:
學習數(shù)字電路后我們知道,電路的輸出狀態(tài)有三種:
1、高電平 2、低電平 3、高阻態(tài)
如圖(5),這種無法確定電路狀態(tài)到底是高電平還是低電平,就是高阻態(tài)。
什么是高阻態(tài)?
答:電路分析時高阻態(tài)可做開路理解。你可以把它看作輸出(輸入)電阻非常大。它的極限狀態(tài)可以認為懸空(開路)。也就是說理論上高阻態(tài)不是懸空,它是對地或對電源電阻極大的狀態(tài)。而實際應用上與引腳的懸空幾乎是一樣的。
所以,我們可以認為,B點在開關斷開的時候,相當于懸空引腳,沒有辦法確定它的狀態(tài),而一般情況下,為了給它確定一個電平,通常就會給IO口加一個上拉電阻,也就是圖(4)看到的情況,也就是當按鍵沒按下的時候,B點為高電平,MCU讀取B點也為高電平。而當按鍵按下的時候,則情況相反,這就是上拉電阻的其中一個作用------確定電路的狀態(tài)。那么下拉電阻也同樣是這么一個功能,該怎么分析,就不用我說了,道理是一樣的。
那么,最前面我們在分析I2C為什么要接上拉電阻的問題,其中一個原因是因為集電極開路輸出和漏極開路輸出,先來搞明白第一個問題,什么是集電極開路輸出?
什么是集電極開路輸出?集電極是什么指的什么東西?
答:集電極是三極管的其中一個電極,這里我們形象的把它畫出來:
那么怎么解決這么不能確定c點到底輸出多少的問題呢?上拉電阻閃亮登場?。。。〈_定電路狀態(tài),這無疑就是個寶貝,關鍵時刻可以用到了,我們來看看怎么改變它。
由此可見,當集電極開路的時候,比如就上面說的,當三極管處于截止狀態(tài)的時候。也就相當于bc之間沒有形成通路的時候,那么c點的電平無法確定,也就是說,將一個無法確定電平的線路接在I2C總線的SDA和SCL上,當I2C為空閑的時候,能保證SDA和SCL輸出高電平嗎?不能?那不能的話,假設輸出低電平,由于I2C總線的線與關系,那不就相當于違背了I2C協(xié)議所說的條件了嗎?所以這就是上拉電阻存在的必要性了。集電極開路也被稱為OC開路,OC,就是Open Collector的英文縮寫。
那么講到這里,有人可能就要問了,那現(xiàn)在我輸入1時,最終就要輸出1,不要反向,我現(xiàn)在輸入0的時候,我就要輸出0,不要被反向,那如何來實現(xiàn)呢?
很簡單,我們接兩個反向器不就得了?來看看怎么接:
但通常在MCU中,不會這么接,但最終的效果是一樣的,原理還是有所區(qū)別。于是經(jīng)過改造就有了如圖(10)所示的電路,由兩只三極管共同控制,當電平不同的時候,總有一只三極管是導通的,當我把上拉電阻換成開關的時候,這個電路就稱為推挽輸出電路。
那么什么又是漏極輸出呢?漏極又是什么東西?漏極是場效應管中的一個極:如圖(11)所示,場效應晶體管(Field Effect Transistor縮寫(FET))簡稱場效應管。主要有兩種類型(junction FET—JFET)和金屬 - 氧化物半導體場效應管(metal-oxide semiconductor FET,簡稱MOS-FET)。由多數(shù)載流子參與導電,也稱為單極型晶體管。它屬于電壓控制型半導體器件。具有輸入電阻高(107~1015Ω)、噪聲小、功耗低、動態(tài)范圍大、易于集成、沒有二次擊穿現(xiàn)象、安全工作區(qū)域寬等優(yōu)點,現(xiàn)已成為雙極型晶體管和功率晶體管的強大競爭者。
場效應管(FET)是利用控制輸入回路的電場效應來控制輸出回路電流的一種半導體器件,并以此命名。
漏極開路(OD)輸出,跟集電極開路輸出是十分類似的。將上面的三極管換成場效應管即可。這樣集電極就變成了漏極,OC就變成了OD,原理分析是一樣的。對于漏極開路(OD)來說,必須在漏極輸出端接上拉電阻,否則只能輸出低電平。
因此為什么I2C總線外要接兩個上拉電阻的原因就在于此。這時候疑問就來了,為什么有些MCU不需要加上拉電阻也可以正常驅動I2C總線呢?
答:有些MCU內部帶了弱上拉電阻,這樣也可以與I2C總線實現(xiàn)線與的功能,這樣可以保證I2C在空閑的時候都為高電平。但考慮到驅動能力的問題,畢竟由芯片輸出的驅動能力有限,所以在外部接上拉電阻可以增加驅動能力。
至于電阻的大小取什么值,可以參考博客末尾的文章。
關于協(xié)議部分,常用的參考以下博客即可,寫得通俗易懂,也很好理解,以下這篇文章考慮的只是主-從模式,而多主機模式在這篇文章中并沒有涉及,建議還是看I2C官方的User Spec來了解,畢竟官方的是最標準的。
http://blog.csdn.net/w89436838/article/details/38660631
接下來看一個分析協(xié)議的實例:以下是使用LA邏輯分析儀從一個I2C接口的設備抓取的時序圖:
一網(wǎng)友寫的一個51單片機的程序,非常好理解,截取過來:
本文參考文獻:
1、I2C原理和上拉下拉電阻的介紹
https://wenku.baidu.com/view/64a4bc3431b765ce04081407.html
2、什么是高阻態(tài)
https://baike.baidu.com/item/%E9%AB%98%E9%98%BB%E6%80%81/7062370?fr=aladdin
3、集電極開路輸出、開漏輸出、推挽輸出
http://forum.eepw.com.cn/thread/242225/1
4、場效應管
https://baike.baidu.com/item/%E5%9C%BA%E6%95%88%E5%BA%94%E7%AE%A1/151400?fr=aladdin
5、關于I2C上拉電阻取值的計算方法
http://blog.csdn.net/zyboy2000/article/details/5789005
6、I2C總線協(xié)議詳解:
http://blog.csdn.net/w89436838/article/details/38660631
免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!