Hempl/I2C
I2C 代表“積體電路間匯流排”,用於不同矽晶片之間的通訊。更具體地說,匯流排是一種數字通訊通道,可以由多個裝置或外設共享。
I2C 應用範圍廣泛,通常用於同一機箱內積體電路之間的通訊,無論是在同一電路板上還是在不同的電路板之間,只要高速通訊速度不是關鍵。
飛利浦最初開發 I2C 用於電視機內部晶片之間的通訊,但隨著時間的推移,該系統蓬勃發展,從 1982 年首次釋出以來,它現已用於超過 1000 種不同的積體電路。
它取得成功的其中一個原因是,它提供了一種實用且經濟的方法來建立複雜的電路,透過僅使用兩根線(資料線和時鐘線)將所有內容連線到同一總線上,這大大減少了必須在電路板上路由的電氣訊號數量。
現實世界應用的示例包括連線非易失性儲存器、即時時鐘電路、數字感測器、I/O 擴充套件器、數字 LED、液晶顯示器和開關等裝置。
I2C 規範已多次修訂,始終保持向後相容性,從 1992 年的 v1.0、2000 年的 v2.1 和 2007 年的 v3.0。標準模式以高達 100 kbit/s 的速度執行,快速模式以高達 400 kbit/s 的速度執行,快速模式加以高達 1 Mbit/s 的速度執行,或高速模式以高達 3.4 Mbit/s 的速度執行。較高的速度模式是在 I2C 規範的新修訂版中新增的,因此並非所有積體電路都支援所有速度。但是,協議是向後相容的,因此較新的、更快的裝置仍然可以與較舊的、較慢的裝置通訊,並且連線到匯流排的某個裝置的速度不會影響總線上其他裝置的速度。Mizar32 I2C 介面的硬體支援標準模式,達到 100 kbit/s,快速模式高達 400 kbit/s。
一些製造商(例如我們的 Atmel 案例)將 I2C 命名為 TWI(雙線介面),因為它沒有實現完整的 I2C 的每一個細節,但它們是相容的,本質上是相同的。
為了更好地理解 I2C,讓我們更深入地瞭解 I2C 協議的工作原理。
I2C 是一種半雙工協議,這意味著一次只能有一個裝置進行通訊。匯流排有兩根線:時鐘和資料。
主裝置為匯流排提供時鐘。最常見的配置是一個主裝置和一個或多個從裝置。另一種配置是多主模式,其中多個主裝置可以在同一總線上通訊而不會導致錯誤。主裝置可以透過某種方式在它們之間決定誰在每個時刻控制匯流排。用於執行此操作的機制稱為匯流排仲裁和時鐘同步。
在一個包含單個主裝置和多個從裝置的配置中,是主裝置提供時鐘訊號,但從裝置可以將其降低到較低的速度,如果它們需要一些額外的時間。
在電氣上,這兩根線透過每個電阻被拉高,裝置透過將這些線拉低來發送訊號。在標準模式下,匯流排速度最高為 100 Kbit/s,電阻值為 10K 歐姆,快速模式下,高達 400 Kbit/s,每個電阻為 2.2K 歐姆。
每個從裝置都有一個 7 位地址,它在總線上響應該地址,並且同一 I2C 總線上的每個裝置都必須設定為響應不同的地址。
當兩個裝置進行通訊時,其中一個是主裝置,另一個是從裝置,其中一個在總線上傳輸資料,另一個接收資料,因此在任何特定時刻,裝置可以是主發射器、主接收器、從接收器或從發射器。
以下是主發射器(啟動與從裝置通訊的裝置)生成的訊號序列。
第一個事件是主發射器生成一個啟動條件,即資料 (SDA) 線在時鐘 (SCL) 線為高電平時的從高電平到低電平的轉換。所有 I2C 訊息中的第一件事始終是啟動條件。
啟動條件會導致所有從裝置喚醒並監聽,因此主裝置傳送從接收器地址(由 7 位組成),後跟一個方向位(0 表示傳送,1 表示接收),然後從接收器生成一個確認 (ACK) 位,以表示它已識別其地址並正在監聽。如果方向位為 0,表示主裝置要向從裝置傳送資料,它將傳輸 8 位資料,從裝置再次傳送一個 ACK 位,主裝置傳送另一個 8 位資料,從裝置傳送一個 ACK,依此類推。在每個資料位元組之後,接收資料的從裝置必須透過將資料線短時間拉低來發送一個 ACK 位。如果缺少 ACK,則表示沒有人收到資料,並且正在傳輸的任何人都將停止傳輸。在所有資料位元組傳輸完成後,主裝置透過在總線上生成停止條件來關閉通訊,即在時鐘 (SCL) 為高電平時的 SDA 線從低電平到高電平的轉換。所有 I2C 訊息始終以停止條件結束。
以更簡潔的形式
| S | 啟動條件 |
| ADDR | 7 位從裝置地址 |
| R/W | 資料方向位:1 表示讀取或 0 表示寫入 |
| DATA | 8 位資料 |
| ACK | 1 位確認 |
| P | 停止條件 |
有時 ADDR 和 R/W 被視為一個 8 位值,地址在最高 7 位,R/W 標誌在最低有效位。例如,我們可能會談論 7 位從裝置地址 42 和方向位 1,而在其他時刻,我們可能會談論 8 位從裝置地址 85,其含義相同。
以下是主裝置向從裝置傳送兩個資料位元組的簡潔檢視
| S | ADDR | W | ACK | DATA | ACK | DATA | ACK | P |
AVR32UC3A 晶片有一個 I2C 控制器,Mizar32 在左側匯流排聯結器 BUS2 上提供其訊號。
Mizar32 的主機板還具有 PCA9540 雙向 I2C 多路複用器晶片,它可以將 I2C 訊號連線到兩個或更多組 I2C 匯流排引腳中的任一組,即左側和右側 I2C 匯流排,其中一個在 BUS2 上可用,另一個在 BUS5 聯結器上可用。如果您使用這些而不是主 I2C 匯流排引腳,則您的系統中可以擁有兩倍的 I2C 裝置。此外,如果您的硬體設計需要兩個響應相同 I2C 地址的 I2C 裝置,您可以將一個放在左側 I2C 總線上,另一個放在右側。
當 Mizar32 開機時,多路複用器處於非活動狀態,AVR32 的 I2C 訊號僅饋送到主 I2C 匯流排引腳。要使 I2C 匯流排訊號出現在左側 I2C 總線上,您將值 5 程式設計到多路複用器的控制字中,要與右側匯流排通訊,您將值 4 程式設計到控制字中。要停用多路複用器,您將程式設計為 0。
請參見下面的程式碼示例,瞭解如何使用 eLua 執行此操作。
I2C 多路複用器和 Mizar32 附加模組上的所有主 I2C 裝置都在主 I2C 總線上,因此您不必程式設計 I2C 多路複用器即可訪問它們。Mizar32 模組放置在左側和右側 I2C 總線上的唯一裝置是每個附加模組上的 EEPROM。
| 訊號 | GPIO | 匯流排引腳 | 備註 |
|---|---|---|---|
| SDA | PA29 | BUS2 引腳 10 | 主 I2C 匯流排資料 |
| SCL | PA30 | BUS2 引腳 11 | 主 I2C 匯流排時鐘 |
| BUS_SDA_L | - | BUS2 引腳 12 | 左側 I2C 匯流排資料 |
| BUS_SCL_L | - | BUS2 引腳 13 | 左側 I2C 匯流排時鐘 |
| BUS_SDA_R | - | BUS5 引腳 3 | 右側 I2C 匯流排資料 |
| BUS_SCL_R | - | BUS5 引腳 4 | 右側 I2C 匯流排時鐘 |
下表顯示了 Mizar32 及其附加模組上晶片使用的 I2C 從裝置地址。
在下表中,我們同時提供了 7 位程式碼的十進位制表示法和相應的 8 位命令位元組值的十六進位制表示法。
| 裝置 | 7 位地址 (十進位制) |
8 位 (十六進位制) |
備註 |
|---|---|---|---|
| LCD 顯示屏(命令) | 0111110 (62) |
7C/7D |
讀取返回游標位置 |
| LCD 顯示屏(資料) | 0111111 (63) |
7E/7F |
讀取返回按鈕 |
| VGA 板 24LC512 | 1010000 (80) |
A0/A1 |
(1) |
| 乙太網板上的 PCF8563 RTC | 1010001 (81) |
A2/A3 |
|
| 乙太網板上的 DS1337 RTC | 1101000 (104) |
D0/D1 |
|
| I2C 多路複用器 PCA9540 | 1110000 (112) |
E0/E1 |
(1) VGA 的 24LC512 EEPROM 包含執行 VGA 板的 Parallax Propeller 晶片的程式,該程式僅在 VGA 板上焊接了 GS4 和 GS5 兩對觸點時才連線到 Mizar32 的主 I2C 匯流排,從而允許您使用Mizar32 Propeller 程式設計器從 Mizar32 程式設計 Propeller 晶片。
Hempl 具有一個i2c模組,提供設定、啟動、地址、傳送/接收位元組和停止基元。
# Send a byte to the i2c multiplexer to tell it to
# enable the left i2c bus
(setq
id 0 # Which i2c bus to use?
mux-addr 112 # The slave address of the i2c mux
mux-disable 0 # Control word to disable the mux
mux-left 4 # Control word to enable left bus
mux-right 5 ) # Control word to enable right bus
(i2c-start 0)
(if (not (= T (i2c-address id mux-addr *i2c-transmitter*)))
(prinl "The multiplexer did not reply")
(if (not (= (i2c-write id mux-left) mux-left))
(prinl "The multiplexer did not acknowledge the write") ) )
(i2c-stop id)
請注意:您也可以從我們的 GitHub 示例庫中下載上述程式碼 send-data.l。
# Retrieve and print the contents of the i2c splitter's
# control register
# misc.l in the Alcor6L codebase contains
# the function PicoLisp function stringToNum.
# misc.l should exist in /mmc
(load "@misc.l")
(setq
id 0 # Which i2c bus to use? (there's only one!)
mux-addr 112 ) # The slave address of the i2c multiplexer
(i2c-start id)
(if (not (= T (i2c-address id mux-addr *i2c-receiver*)))
(prinl "The multiplexer did not reply")
(let (cr (i2c-read id 1)) # Read the control register (one byte)
(prinl "Control register: " (stringToNum cr)) ) )
(i2c-stop id)
請注意:上述程式需要檔案 misc.l 才能正常工作。此版本的 misc.l 與預裝在現成 PicoLisp 中的版本不同。您也可以從我們的 GitHub 示例庫中下載 read-data.l。
- 維基百科的 I2C 文章
- Atmel AT32UC3A 資料手冊 第 24 章:雙線介面 (TWI)。
- 飛利浦半導體 PCA9540 雙通道 I2C 多路複用器資料手冊
- 飛利浦半導體 I2C 地址分配表