這篇文章來(lái)源于DevicePlus.com英語(yǔ)網(wǎng)站的翻譯稿。
今天,我們將討論arduino通信協(xié)議的有關(guān)內(nèi)容。設(shè)備往往需要相互通信以中繼所處環(huán)境相關(guān)信息,顯示其狀態(tài)變化,或請(qǐng)求執(zhí)行輔助操作。在進(jìn)行任何電子設(shè)備愛(ài)好相關(guān)研究時(shí),您將需要使用多個(gè)不同的傳感器或多個(gè)不同的模塊(如ESP8266),屆時(shí)必然會(huì)遇到一個(gè)或多個(gè)主流的通信協(xié)議。在本教程中,我們將會(huì)介紹電子設(shè)備使用的標(biāo)準(zhǔn)通信協(xié)議,并使用Arduino Uno對(duì)其進(jìn)行詳細(xì)說(shuō)明。
二進(jìn)制數(shù)字系統(tǒng)
設(shè)備間的通信通過(guò)數(shù)字信號(hào)進(jìn)行。在討論通信協(xié)議之前,我們將首先討論如何傳輸這些信號(hào)。
在數(shù)字信號(hào)中,數(shù)據(jù)由一系列的高電平到低電平或低電平到高電平的脈沖進(jìn)行傳輸,并且切換非常迅速。數(shù)字信號(hào)中的高電平和低電平分別代表1和0,當(dāng)按照順序連在一起時(shí),就攜帶了可由微控制器編譯的信息。聽(tīng)說(shuō)過(guò)位和字節(jié)嗎?這些1和0是位,當(dāng)它們以8個(gè)為一組時(shí),就稱(chēng)之為位,當(dāng)它們以8個(gè)為一組時(shí),就稱(chēng)之為字節(jié)!
一個(gè)字節(jié)看起來(lái)大概是這樣:10111001
事實(shí)證明,這個(gè)由8位組成的序列代表了一個(gè)數(shù)字,就像597這個(gè)數(shù)字代表了597一樣。每個(gè)數(shù)字占據(jù)了一個(gè)位置值,該位置值中的1或者0表示該位置值被計(jì)數(shù)了多少次。
在597的示例中,5表示有5個(gè)100,9表示有9個(gè)10,7表示有7個(gè)1。加在一起,就表示5個(gè)100+9個(gè)10+7個(gè)1(500 + 90 + 7)……或597。因?yàn)?是100 ,10是101,100是102等等,因此這叫做基于10的系統(tǒng)!在基于10的系統(tǒng)中,每個(gè)數(shù)字的取值范圍為0到9(0到10-1)。
現(xiàn)在我們?cè)賮?lái)看10111001。我們可以看出這是基于2的系統(tǒng),因?yàn)槊總€(gè)數(shù)字的取值范圍為0到1。我們可以說(shuō)每個(gè)數(shù)字都是2的冪,這意味著10111001實(shí)際為1 * 27 + 0 * 26 + 1 * 25 + 1 * 24 + 1 * 23 + 0 * 22 + 0 * 21 + 1 * 20,或者說(shuō)為基于10的系統(tǒng)中的185。
可以想象,您可以擁有基于任何數(shù)字的數(shù)字系統(tǒng)!常見(jiàn)的一些數(shù)字為2、8、10和16。為了簡(jiǎn)單起見(jiàn),數(shù)學(xué)家為這些常見(jiàn)的數(shù)字系統(tǒng)命了名——基于2的為二進(jìn)制,基于8的為八進(jìn)制,基于10的為十進(jìn)制,基于16的為十六進(jìn)制。每個(gè)數(shù)字系統(tǒng)都遵循相同的原理:每個(gè)數(shù)字代表該基數(shù)的冪被計(jì)數(shù)的次數(shù),并且每個(gè)數(shù)字的值都只能在0到(基數(shù)-1)之間。
了解不同的基數(shù)系統(tǒng)很有用,因?yàn)樽止?jié)和數(shù)據(jù)通常以不同的方式進(jìn)行表達(dá)。可以看出,寫(xiě)B(tài)9(十六進(jìn)制)比寫(xiě)10111001(二進(jìn)制)容易。在軟件中,二進(jìn)制數(shù)以0b作為前綴,八進(jìn)制數(shù)以0作為前綴,十六進(jìn)制數(shù)以0x作為前綴。十進(jìn)制數(shù)沒(méi)有前綴。
知道如何在基數(shù)之間進(jìn)行轉(zhuǎn)換也很有用,因?yàn)橐恍┖芸岬臄?shù)學(xué)技巧通常用二進(jìn)制數(shù)進(jìn)行表達(dá)。但是,出于本教程的目的,我們僅講述到這里。請(qǐng)查看以下本教程的附錄來(lái)獲取有關(guān)這些技巧的文章!
3 種協(xié)議:UART,SPI和I2C
電氣工程行業(yè)使用三種通信協(xié)議對(duì)電子設(shè)備進(jìn)行標(biāo)準(zhǔn)化,以確保設(shè)備之間的兼容性。將設(shè)備以幾種協(xié)議為中心進(jìn)行標(biāo)準(zhǔn)化,意味著設(shè)計(jì)者可以通過(guò)掌握每個(gè)通信協(xié)議的一些基本概念實(shí)現(xiàn)任何設(shè)備之間的交互。UART,SPI和I2C這三種協(xié)議的實(shí)現(xiàn)方式不同,但都會(huì)達(dá)到相同的目的:將數(shù)據(jù)高速傳輸?shù)饺魏渭嫒莸脑O(shè)備上。
1. UART
我們將要介紹的第一個(gè)通信協(xié)議是通用異步收發(fā)器(UART)。UART是一種串行通信,因?yàn)閿?shù)據(jù)是一位一位依次進(jìn)行傳輸?shù)模ㄎ覀儗⒃谏院蠼榻B)。設(shè)置UART通信的接線(xiàn)非常簡(jiǎn)單:一根用于傳輸數(shù)據(jù)(TX)的線(xiàn),另一根用于接收數(shù)據(jù)(RX)的線(xiàn)。如您所料,TX線(xiàn)用于發(fā)送數(shù)據(jù),RX線(xiàn)用于接收數(shù)據(jù)。使用串行通信的設(shè)備的TX線(xiàn)和RX線(xiàn)將一起形成一個(gè)串行端口,通過(guò)該端口可以進(jìn)行通信。
圖1:UART的硬件連接圖
UART一詞實(shí)際上是指管理串行數(shù)據(jù)打包和轉(zhuǎn)換的板載硬件。如果希望設(shè)備能夠通過(guò)UART協(xié)議進(jìn)行通信,就必須具有該硬件!在 Arduino Uno上,有一個(gè)專(zhuān)用于與Arduino所連接計(jì)算機(jī)之間進(jìn)行通信的串行端口。對(duì)!通用串行總線(xiàn)USB正是一個(gè)串行端口!在Arduino Uno上,USB的連接通過(guò)板載硬件配置為成兩個(gè)數(shù)字引腳GPIO 0和GPIO 1,可用于涉及與計(jì)算機(jī)以外的電子設(shè)備進(jìn)行串行通信的項(xiàng)目。
圖2:GPIO 0 和GPIO 1是串口RX和TX。任何GPIO引腳都可以通過(guò)SoftwareSerial庫(kù)用作串口RX或TX。
您還可以使用SoftwareSerial Arduino 庫(kù)(SoftwareSerial.h)將其他GPIO引腳用作串口RX和TX線(xiàn)。
UART之所以成為異步,是因?yàn)椴皇褂迷噲D相互通信的兩個(gè)設(shè)備之間的同步時(shí)鐘信號(hào)進(jìn)行通信。由于通信速率不是通過(guò)這種穩(wěn)定信號(hào)定義的,“發(fā)送方”設(shè)備無(wú)法確定“接收方”設(shè)備是否獲取了正確的數(shù)據(jù)。因此,設(shè)備將數(shù)據(jù)分成了固定大小的塊,以確保接收到的數(shù)據(jù)與發(fā)送的數(shù)據(jù)相同。
UART數(shù)據(jù)包如下所示:
圖3:UART數(shù)據(jù)包視圖/ ?electric imp
通過(guò)UART進(jìn)行通信的設(shè)備會(huì)發(fā)送預(yù)定義大小的數(shù)據(jù)包,其中包含有關(guān)消息的開(kāi)始與結(jié)束,以及確認(rèn)消息是否接收的附加信息。例如,為了開(kāi)始通信,發(fā)送設(shè)備將發(fā)送線(xiàn)拉低,指示數(shù)據(jù)包開(kāi)始發(fā)送。然而,目前遇到的問(wèn)題是,與同步通信方式相比,UART速度較慢,因?yàn)閭鬏數(shù)臄?shù)據(jù)只有一部分用于設(shè)備的應(yīng)用程序(其余部分用于通信本身?。?。
在大多數(shù)嵌入式平臺(tái)(例如Arduino)上實(shí)現(xiàn)UART串行通信時(shí),用戶(hù)不用在位的數(shù)據(jù)級(jí)別上進(jìn)行通信,平臺(tái)通常提供更高級(jí)別的軟件庫(kù),用戶(hù)只需在這些軟件庫(kù)中處理通信內(nèi)容即可。在Arduino平臺(tái)上,用戶(hù)可以使用Serial和SoftwareSerial庫(kù)為自己的項(xiàng)目實(shí)現(xiàn)UART通信。
以下是有關(guān)Arduino Serial和SoftwareSerial的初始化和使用的C++簡(jiǎn)要參考。
Serial 和 SoftwareSerial 方法(method) | 目的 | 代碼 | 釋義 |
Constructor (僅SoftwareSerial) | 定義GPIO引腳為UART RX線(xiàn)和TX線(xiàn)。 | SoftwareSerial comms (2 , 3); | 定義GPIO 2 上的RX線(xiàn)與GPIO 3上的TX線(xiàn)為串行連接 |
begin | 定義串行連接的波特率(傳輸速度)在范圍4800~115200之間 | comms.begin(9600); | “comms”串行端口上的通信將以9600波特率的速度進(jìn)行 |
通過(guò)串行連接將字節(jié)數(shù)據(jù)轉(zhuǎn)換為可閱讀的字符 | comms.println(“Hello World”); | 寫(xiě)入等效于Hello World (可讀字符)的字節(jié) | |
write | 通過(guò)串行連接寫(xiě)入原始字節(jié)數(shù)據(jù) | comms.write(45); | 寫(xiě)入值為45的字節(jié) |
available | 當(dāng)數(shù)據(jù)可通過(guò)串行連接獲取時(shí)評(píng)估為真(true) | if (comms.available()) | 如果可獲取通過(guò)串行連接讀取的數(shù)據(jù),執(zhí)行if語(yǔ)句 |
read | 讀取從串行連接獲得的數(shù)據(jù) | comms.read(); | 從串行連接讀取數(shù)據(jù) |
有關(guān)UART通信,有一個(gè)重要的點(diǎn)需要注意,該通信協(xié)議下一次只能實(shí)現(xiàn)兩個(gè)設(shè)備之間的通信。因?yàn)樵搮f(xié)議僅發(fā)送指示消息的開(kāi)始、消息內(nèi)容和消息的結(jié)束的位,所以沒(méi)有辦法區(qū)分同一條線(xiàn)路上的多個(gè)發(fā)送和接收設(shè)備。如果有多個(gè)設(shè)備嘗試在同一條線(xiàn)路上傳輸數(shù)據(jù),則會(huì)發(fā)生總線(xiàn)爭(zhēng)用,并且接收設(shè)備很可能會(huì)接收無(wú)法使用的垃圾數(shù)據(jù)!
此外,UART是半雙工的,這意味著即使可以在兩個(gè)方向上進(jìn)行通信,兩個(gè)設(shè)備也無(wú)法同一時(shí)間相互傳輸數(shù)據(jù)。例如,在一個(gè)項(xiàng)目中,兩個(gè)Arduino通過(guò)串行連接相互通信,這意味著在給定的時(shí)刻,只有其中一個(gè)Arduino可以與另一個(gè)“交流”。對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō),這一特點(diǎn)相對(duì)來(lái)說(shuō)并不重要,并且不會(huì)產(chǎn)生不利影響。
2. SPI
我們將介紹的下一個(gè)通信協(xié)議是串行外圍設(shè)備接口(SPI)。SPI與UART主要有以下不同點(diǎn):
? 同步
? 遵循主從模式,包含一個(gè)主設(shè)備和多個(gè)從設(shè)備
? 應(yīng)用中需要兩條以上的線(xiàn)
SPI的硬件連接圖稍微復(fù)雜一些,看起來(lái)像這樣:
圖4:SPI的硬件連接圖
MOSI (“Master Out Slave In”): 從主設(shè)備到從設(shè)備的數(shù)據(jù)傳輸線(xiàn)
SCK (“Clock”): 定義了傳輸速率和傳輸開(kāi)始/結(jié)束特性的時(shí)鐘線(xiàn)
SS (“Slave Select”): 用于主設(shè)備選擇進(jìn)行通信的從設(shè)備的線(xiàn)
MISO (“Master In Slave Out”):從設(shè)備到主設(shè)備的數(shù)據(jù)傳輸線(xiàn)
SPI的第一個(gè)特點(diǎn)是遵循主從模型。這意味著通信中將會(huì)有一個(gè)設(shè)備為主設(shè)備,而其他設(shè)備為從設(shè)備。在該模式下,會(huì)在設(shè)備之間創(chuàng)建層次結(jié)構(gòu),從而顯示出哪個(gè)設(shè)備有效地“控制”了其他設(shè)備。我們會(huì)在闡述一個(gè)主從設(shè)備之間的通信示例時(shí)簡(jiǎn)單地討論一下此主從模型。
前面我們提到,多個(gè)從設(shè)備可以連接到一個(gè)主設(shè)備。這種系統(tǒng)的硬件圖如下所示:
圖5:連接到一個(gè)主設(shè)備的多個(gè)從設(shè)備
SPI不需要為連接到主設(shè)備的每個(gè)從設(shè)備提供單獨(dú)的發(fā)送線(xiàn)和接收線(xiàn)。在所有從設(shè)備和主設(shè)備之間連接了一條公共接收線(xiàn)(MISO)和一條公共發(fā)送線(xiàn)(MOSI),以及一條公共時(shí)鐘線(xiàn)(SCK)。主設(shè)備通過(guò)每個(gè)從設(shè)備分別配置的SS線(xiàn)來(lái)決定將與哪個(gè)從設(shè)備進(jìn)行通信。這意味著每增加一個(gè)與主設(shè)備通信的從設(shè)備,都需要在主設(shè)備一側(cè)再使用一個(gè)GPIO引腳。
SPI是同步的,也就是說(shuō)主設(shè)備和從設(shè)備之間的通信與主設(shè)備定義的時(shí)鐘信號(hào)(固定頻率的方波)緊密相關(guān)。從這里我們可以看出主從模型的直接影響之一,即主設(shè)備通過(guò)時(shí)鐘信號(hào)指定通信速率來(lái)驅(qū)動(dòng)通信,而從設(shè)備在該速率下進(jìn)行通信來(lái)響應(yīng)主設(shè)備。所定義的速率適用于主設(shè)備所主導(dǎo)的任何通信過(guò)程(在從設(shè)備可以承受的最大速率范圍內(nèi))。
在SPI中,時(shí)鐘信號(hào)的兩個(gè)特征決定了數(shù)據(jù)傳輸?shù)拈_(kāi)始和結(jié)束:時(shí)鐘極性(CPOL)和時(shí)鐘相位(CPHA)。CPOL是指時(shí)鐘信號(hào)的空閑狀態(tài)(低電平或高電平)。為了節(jié)省功耗,設(shè)備在不與任何從設(shè)備通信時(shí)會(huì)將時(shí)鐘線(xiàn)置于空閑狀態(tài),并且在該空閑狀態(tài)下可用的兩個(gè)選項(xiàng)為低電平或高電平。CPHA是指時(shí)鐘信號(hào)的跳變沿,決定何時(shí)對(duì)數(shù)據(jù)進(jìn)行采樣。方波有兩種跳變沿(上升沿和下降沿),并且根據(jù)CPHA設(shè)置,可以對(duì)上升沿或下降沿進(jìn)行采樣。
CPOL和CPHA有四種不同的組合方式,如下表所示:
CPHA = 0 (時(shí)鐘信號(hào)的“第一種跳變沿”) |
CPHA = 1 (時(shí)鐘信號(hào)的“第二種跳變沿”) |
|
CPOL = 0 (空閑狀態(tài)為0) |
“SPI 模式 0” ? 時(shí)鐘第一次從0(空閑)變?yōu)?時(shí)開(kāi)始采樣。 ? 數(shù)據(jù)采樣發(fā)生在時(shí)鐘信號(hào)的上升沿(0→1) |
“SPI 模式 1” ? 時(shí)鐘第一次從0(空閑)變?yōu)?時(shí)開(kāi)始采樣。 ? 數(shù)據(jù)采樣發(fā)生在時(shí)鐘信號(hào)的下降沿 (1→0) |
CPOL = 1 (空閑狀態(tài)為 1) |
“SPI 模式 2” ? 時(shí)鐘第一次從1(空閑)變?yōu)?時(shí)開(kāi)始采樣。 ? 數(shù)據(jù)采樣發(fā)生在時(shí)鐘信號(hào)的上升沿(0→1) |
“SPI 模式 3” ? 時(shí)鐘第一次從1(空閑)變?yōu)?時(shí)開(kāi)始采樣。 ? 數(shù)據(jù)采樣發(fā)生在時(shí)鐘信號(hào)的下降沿(1→0) |
維基百科以圖形方式很好地表示出了CPOL和CPHA的設(shè)置與其所傳輸數(shù)據(jù)的關(guān)系!
圖6:CPOL和CPHA的設(shè)置視圖/ ?Wikipedia
現(xiàn)在,我們將重點(diǎn)介紹使用Arduino作為主設(shè)備(SPI.h)在Arduino上實(shí)現(xiàn)SPI的方法。SCK、MOSI和MISO的SPI數(shù)字引腳連接要在Arduino開(kāi)發(fā)板上進(jìn)行預(yù)定義。對(duì)于Arduino Uno,連接如下:
SCK: GPIO 13 或 ICSP 3
MOSI: GPIO 11 或 ICSP 4
MISO: GPIO 12 或 ICSP 1
SS: GPIO 10
任何數(shù)字引腳都可以作為SS引腳。為了選擇設(shè)備,該數(shù)字引腳必須被驅(qū)動(dòng)為低電平。
圖7:MOSP、MISO和SCK引腳分配在ICSP接頭以及GPIO 11、GPIO 12 和GPIO 13上
以下是有關(guān)Arduino SPI初始化和使用的C++簡(jiǎn)要參考。
SPI 方法(Method) | 目的 | 代碼 | 釋義 |
Constructor | 定義時(shí)鐘速率、數(shù)據(jù)位順序(最高有效位在前或最低有效位在前)以及SPI模式 |
SPI.beginTransaction (SPISettings(14000000, MSBFIRST, SPI_MODE0)); |
在SPI模式0定義14MHz下的SPI連接,并以最高有效位在前的方式進(jìn)行數(shù)據(jù)傳輸 |
digitalWrite | 選擇連接到該GPIO引腳的從設(shè)備 | digitalWrite(10, LOW); | 將GPIO引腳驅(qū)動(dòng)為低電平以選擇從設(shè)備。然后將引腳驅(qū)動(dòng)為高電平以取消選擇從設(shè)備。 |
transfer | 將字節(jié)傳送到所選擇的從設(shè)備 | SPI.transfer(0x00); | 發(fā)送值為0的字節(jié) |
endTransaction | 結(jié)束SPI程序(應(yīng)在SS線(xiàn)上調(diào)用digitalWrite(high)之后調(diào)用) | SPI.endTransaction(); | 結(jié)束SPI程序 |
SPI是全雙工的,這意味著即使在應(yīng)用中只要求在一個(gè)方向上進(jìn)行數(shù)據(jù)傳輸,通信也始種是雙向進(jìn)行的。SPI全雙工數(shù)據(jù)傳輸通常通過(guò)移位寄存器來(lái)實(shí)現(xiàn)。(請(qǐng)參閱附錄中有關(guān)移位寄存器的教程?。_@表明在讀取一個(gè)位時(shí),前面的位將被移動(dòng)一位,隨后,最前邊的位將會(huì)被觸發(fā),并通過(guò)SPI連接發(fā)送到另一臺(tái)設(shè)備上!
3. I2C
內(nèi)部集成電路總線(xiàn)(I2C)的發(fā)音為“I方C”,是我們?cè)诒窘坛讨薪榻B的最后一個(gè)通信協(xié)議。雖然該協(xié)議的實(shí)現(xiàn)是三種協(xié)議中最復(fù)雜的,但是I2C解決了其他通信協(xié)議中存在的一些問(wèn)題,使其在某些應(yīng)用程序中比其他通信協(xié)議更具有優(yōu)勢(shì)。這些優(yōu)勢(shì)包括:
能夠?qū)崿F(xiàn)多個(gè)主設(shè)備與多個(gè)從設(shè)備之間的連接
同步(同SPI),具有更高的通信速率
簡(jiǎn)易性:僅需要兩根線(xiàn)和一些電阻即可實(shí)現(xiàn)
從硬件層面來(lái)說(shuō),I2C是一種兩線(xiàn)接口—I2C連接中僅需要的兩根線(xiàn)是數(shù)據(jù)線(xiàn)(成為SDA)和時(shí)鐘線(xiàn)(稱(chēng)為SCL)。數(shù)據(jù)線(xiàn)和時(shí)鐘線(xiàn)在空閑狀態(tài)下被拉高,而在需要通過(guò)連接發(fā)送數(shù)據(jù)時(shí),這些線(xiàn)會(huì)通過(guò)一些MOSFET電路被拉低。在本教程中,我們將不討論I2C電路內(nèi)部的MOSFET操作,這里需要說(shuō)明的一個(gè)重要點(diǎn)是該系統(tǒng)是漏極開(kāi)路的,即線(xiàn)路只能由設(shè)備驅(qū)動(dòng)為低電平。因此,在項(xiàng)目中使用I2C時(shí),上拉電阻(通常為4.7k?)這一步至關(guān)重要,以確保在空閑狀態(tài)下線(xiàn)路確實(shí)被拉高。
圖8:I2C硬件連接圖
I2C具有其獨(dú)特性,因?yàn)樗ㄟ^(guò)尋址解決了與多個(gè)從設(shè)備之間的接口問(wèn)題。與SPI通信一樣,I2C利用主從模型建立了通信的“層次結(jié)構(gòu)”。但是,主設(shè)備不是通過(guò)單獨(dú)的數(shù)字線(xiàn)路選擇從設(shè)備,而是通過(guò)主設(shè)備中具有唯一性的字節(jié)地址來(lái)選擇從設(shè)備,這種字節(jié)地址大概類(lèi)似于這樣:0x1B。這意味著將從設(shè)備連接到主設(shè)備不再需要添加數(shù)字線(xiàn)路。只要每個(gè)從設(shè)備都有唯一性的地址,應(yīng)用程序就可以區(qū)分這些地址所對(duì)應(yīng)的從設(shè)備。您可以將這些地址視為名稱(chēng)。要調(diào)用從設(shè)備的功能,主設(shè)備僅調(diào)用其名稱(chēng)即可,而只有具有該名稱(chēng)的從設(shè)備會(huì)發(fā)生響應(yīng)。
I2C通信線(xiàn)路中的地址和對(duì)應(yīng)數(shù)據(jù)看起來(lái)像下圖這樣。
圖9:通信中的地址與對(duì)應(yīng)數(shù)據(jù)樣圖/ ?tessel.io
請(qǐng)注意通信線(xiàn)上的ACK 和 NACK請(qǐng)注意通信線(xiàn)上的ACK和NACK位。這些位表示被尋址的從設(shè)備是否響應(yīng)通信—這是一種定期檢查通信是否按照預(yù)期進(jìn)行的方法。這些位當(dāng)然與發(fā)送的地址位或數(shù)據(jù)位無(wú)關(guān),但是在復(fù)雜的通信體系中,與包含許多開(kāi)始和結(jié)束位并會(huì)發(fā)生停頓的類(lèi)似UART這樣的協(xié)議相比,它們只增加了非常少的額外時(shí)間而已。
I2C 使從設(shè)備可以自由決定通信請(qǐng)求的方式。向不同的從設(shè)備寫(xiě)入或發(fā)出請(qǐng)求需要在SDA線(xiàn)以不同的順序?qū)懭氩煌淖止?jié)。例如,在某些加速計(jì)模塊中,在讀取請(qǐng)求發(fā)送之前,需要寫(xiě)入指示主設(shè)備所要讀取的硬件寄存器的字節(jié)。對(duì)于這些規(guī)格,用戶(hù)需要參考從設(shè)備數(shù)據(jù)手冊(cè)中的設(shè)備地址、寄存器地址和設(shè)備設(shè)置。
在Arduino上,I2C通過(guò)Wire 庫(kù)(Wire.h)實(shí)現(xiàn)應(yīng)用。Arduino可以配置為一個(gè)I2C主設(shè)備或從設(shè)備。在Arduino Uno上的連接如下所示:
SDA: 模擬引腳 4
SCL: 模擬引腳 5
圖9:I2C(Wire)SDA為模擬引腳4(A4),SCL為模擬引腳5(A5)
以下是有關(guān)Arduino I2C初始化和使用的C++簡(jiǎn)要參考。
I2C (線(xiàn)) Method | 目的 | 代碼 | 釋義 |
begin | 啟動(dòng)庫(kù),并以主設(shè)備或從設(shè)備的身份加入I2C 總線(xiàn)。 | Wire.begin(); | 以主設(shè)備的身份加入I2C 總線(xiàn)。如果將地址指定為方法的參數(shù),則Arduino將以該地址作為從設(shè)備加入總線(xiàn)。 |
beginTransmission | 對(duì)于配置為I2C 主設(shè)備的Arduino:?jiǎn)?dòng)與具有給定地址的從設(shè)備之間的傳輸。 | Wire.beginTransmission(0x68); | 開(kāi)始對(duì)具有十六進(jìn)制地址Ox68的從設(shè)備進(jìn)行傳輸。 |
write | 通過(guò)I2C總線(xiàn)寫(xiě)入字節(jié)數(shù)據(jù)。 | Wire.write(0x6B); | 通過(guò)I2C總線(xiàn)寫(xiě)入值Ox68的字節(jié)數(shù)據(jù)。 |
requestFrom |
向具有給定地址的從設(shè)備請(qǐng)求指定值的字節(jié);可以選擇釋放I2C線(xiàn)或?qū)⑵浔A粢赃M(jìn)行進(jìn)一步的通信。 所請(qǐng)求的字節(jié)被放入緩沖區(qū),隨后通過(guò)Wire.read()調(diào)用讀取。 |
Wire.requestFrom(0x68, 6, true); |
向地址為Ox68的從設(shè)備請(qǐng)求6個(gè)字節(jié)。請(qǐng)求完成后釋放I2C線(xiàn)。 如果最后一個(gè)參數(shù)為false,則Arduino將保留I2C線(xiàn)以進(jìn)行進(jìn)一步的通信,而不允許其他設(shè)備通過(guò)該線(xiàn)進(jìn)行通信。 |
read |
從設(shè)備發(fā)送數(shù)據(jù)后,讀取放入緩沖區(qū)的字節(jié)。 該方法將在調(diào)用 Wire.requestFrom之后調(diào)用。 |
Wire.read(); |
從緩沖區(qū)讀取一個(gè)字節(jié)(在調(diào)用requestFrom之后)。要從緩沖區(qū)讀取兩個(gè)字節(jié),必須兩次調(diào)用該方法。 例: Wire.requestFrom(0x68, 2, true); Wire.read(); Wire.read(); |
endTransmission | 結(jié)束當(dāng)前傳輸;可以選擇釋放I2C線(xiàn)或?qū)⑵浔A粢赃M(jìn)行進(jìn)一步的通信。 | Wire.endTransmission(true); | 結(jié)束傳輸并釋放I2C線(xiàn)。 |
只需將SDA和SCL線(xiàn)連接到總線(xiàn)上,就可以通過(guò)I2C總線(xiàn)連接多個(gè)主設(shè)備。但是,一次只能有一個(gè)主設(shè)備與從設(shè)備通信,因?yàn)樽尪鄠€(gè)設(shè)備進(jìn)行相互通信會(huì)導(dǎo)致總線(xiàn)爭(zhēng)用。同樣,不能同時(shí)進(jìn)行主設(shè)備到從設(shè)備和從設(shè)備到主設(shè)備之間的雙向通信,因?yàn)檫@也會(huì)導(dǎo)致總線(xiàn)爭(zhēng)用。這使得I2C變成了半雙工,就像UART那樣!
總之,多個(gè)主設(shè)備無(wú)法通過(guò)同一個(gè)I2C總線(xiàn)實(shí)現(xiàn)相互通信。在將多個(gè)主設(shè)備連接到從設(shè)備的應(yīng)用中,主設(shè)備可以通過(guò)單獨(dú)的總線(xiàn)或單獨(dú)的通信協(xié)議實(shí)現(xiàn)相互之間的通信。
如果您學(xué)完了本教程,那么應(yīng)該已經(jīng)擁有所有使用UART、SPI和I2C通信協(xié)議所需的工具了!查看我們的一些Arduino項(xiàng)目,可以獲取有關(guān)使用這些協(xié)議的更多示例!
審核編輯:湯梓紅
-
通信協(xié)議
+關(guān)注
關(guān)注
28文章
883瀏覽量
40308 -
I2C
+關(guān)注
關(guān)注
28文章
1487瀏覽量
123754 -
uart
+關(guān)注
關(guān)注
22文章
1235瀏覽量
101394 -
Arduino
+關(guān)注
關(guān)注
188文章
6469瀏覽量
187069
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論