來源:百問網_嵌入式linux wiki_jz2440 新1期視頻維基教程 (視頻文字版)
作者:韋東山
本文字數:1856,閱讀時長:3.5分鐘
I2C協議
I2C在硬件上的接法如下(圖19-1)所示,主控芯片引出兩條線SCL,SDA線,在一條I2C總線上可以接很多I2C設備,我們還會放一個上拉電阻(放一個上拉電阻的原因以后我們再說)。

我們怎么傳輸數據,我們需要發數據從主設備發送到從設備上去,也需要把數據從從設備傳送到主設備上去,數據涉及到雙向傳輸。
舉個例子:

體育老師:可以把球發給學生,也可以把球從學生中接過來。
1.發球:a.老師說:注意了(start) b.老師對A學生說我要球發給你(地址)。
- c.老師就把球發出去了(傳輸)。
- d.A收到球之后,應該告訴老師一聲(回應)。
- e.老師說下課(停止)
2.接球:
- a.老師說注意了(start),
- b.老師說:B把球發給我(地址)
- c.B就把球發給老師(傳輸)
- d.老師收到球之后,給B說一聲,表示收到球了(回應)。
- e.老師說下課(停止)
我們就使用這個簡單的例子,來解釋一下IIC的傳輸協議。
- 老師說注意了,表示開始信號(start)
- 老師告訴某個學生,表示發送地址(address)
- 老師發球/接球,表示數據的傳輸
- 老師/學生收到球,回應表示:回應信號(ACK)
- 老師說下課,表示IIC傳輸接受(P)
IIC傳輸數據的格式
1.寫操作:
剛開始主芯片要發出一個start信號,然后發出一個設備地址(用來確定是往哪一個芯片寫數據),方向(讀/寫,0表示寫,1表示讀)。
回應(用來確定這個設備是否存在),然后就可以傳輸數據,傳輸數據之后,要有一個回應信號(確定數據是否接受完成),然后再傳輸下一個數據。
每傳輸一個數據,接受方都會有一個回應信號,數據發送完之后,主芯片就會發送一個停止信號。
白色背景:主→從
灰色背景:從→主

2.讀操作:
剛開始主芯片要發出一個start信號,然后發出一個設備地址(用來確定是從哪一個芯片讀取數據),方向(讀/寫,0表示寫,1表示讀)。
回應(用來確定這個設備是否存在),然后就可以傳輸數據,傳輸數據之后,要有一個回應信號(確定數據是否接受完成),然后再傳輸下一個數據。
每傳輸一個數據,接受方都會有一個回應信號,數據發送完之后,主芯片就會發送一個停止信號。
白色背景:主→從
灰色背景:從→主

傳輸是以8位為單元數據傳輸的,先傳輸最高位(MSB),主芯片發出start信號之后,然后發出9個時鐘傳輸數據。
(1)開始信號(S):SCL為高電平時,SDA由高電平向低電平跳變,開始傳送數據。
(2)結束信號(P):SCL為高電平時,SDA由低電平向高電平跳變,結束傳送數據。
(3)響應信號(ACK):接收器在接收到8位數據后,在第9個時鐘周期,拉低SDA
SDA上傳輸的數據必須在SCL為高電平期間保持穩定,SDA上的數據只能在SCL為低電平期間變化。如圖

1.問題:如何在SDA上實現雙向傳輸?
答:主芯片通過一根SDA線既可以把數據發給從設備,也可以從SDA上讀取數據,連接SDA線的引腳里面必然有兩個引腳(發送引腳/接受引腳)。
2.問題:主設備(從設備)發送數據時,從設備(主設備)的發送引腳,不影響數據的發送,怎么做到呢?
答:里面放一個三極管,使用開極(極電集開發出去作為輸出)電路,如下圖

下面畫一個真值表:

- 從真值表和電路圖我們可以知道,當某一個芯片不行影響SDA線時,那就不驅動這個三極管。
- 想輸出高電平時;都不驅動(高電平就由上拉電阻決定)。
- 想輸出低電平,就驅動三極管。
從下面的例子可以看看數據是怎么傳的(實現雙向傳輸),比如:主設備發送(8bit)給從設備 1.前8個clk
- 從設備不要影響,從設備不驅動三極管;
- 主設備決定數據;
2.第9個clk,由從設備決定數據
- 主設備不驅動三極管;
- 從設備決定數據;
從上面的例子,就可以知道,怎樣在一條線上實現,雙向傳輸的辦法。這就是為什么在SDA,SCL上放上拉電阻的原因。
在第9個時鐘之后,如果有某一方處于繁忙狀態,它可以一直把SCL拉低當SCL為低電平時候,大家都不應該使用IIC總線,只有當SCL從低電平變為高電平的時候,IIC總線才能被使用。
從前圖我們也可以知道ACK信號應該是低電平。主設備不驅動三極管,如果從設備不驅動三極端的話SDA應該是高電平,當從設備接收數據之后,發出回應信號的時候,就會驅動三極管,讓SDA變為低電平。所以說:ACK信號是低電平。
對于IIC協議它只能規定怎么傳輸數據,數據什么含義它完全不能夠控制,數據的含義有從設備決定。