0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何僅在兩個(gè)Aduino之間進(jìn)行2路I2C通信

454398 ? 來源:網(wǎng)絡(luò)整理 ? 作者:網(wǎng)絡(luò)整理 ? 2019-11-25 15:16 ? 次閱讀

步驟1:您需要什么:

我們假設(shè)您具有以下部分:

兩個(gè)Arduino UNO

一些公對母電線

一些公對公電線

一個(gè)旋轉(zhuǎn)電位計(jì)

一個(gè)面包板

步驟2:I2C的工作方式

I2C是一種通信協(xié)議,使您可以在微控制器和某些傳感器等電路之間進(jìn)行通信。它僅使用兩根線(如此高效?。5谝痪€是時(shí)鐘線,通常在文檔中寫為SCL。第二根線是數(shù)據(jù)線,通常寫為SDA。

I2C總線上的設(shè)備可以是“主機(jī)”或“從機(jī)”。僅主機(jī)控制時(shí)鐘線上的電壓,而主機(jī)和從機(jī)都可以操縱數(shù)據(jù)線上的電壓。通過仔細(xì)輪流,網(wǎng)絡(luò)上的所有設(shè)備都可以共享信息。

為了將信息發(fā)送到正確的位置,每個(gè)從站都有一個(gè)唯一的地址號碼,就像每個(gè)電話都有一個(gè)唯一的號碼一樣。

當(dāng)我看到I2C器件時(shí),他們有文檔說:“該電路希望接收N字節(jié)表示ABC的數(shù)據(jù),并發(fā)送回M字節(jié)表示DEF的數(shù)據(jù)?!比绻徺I的設(shè)備不包含此信息,則不要購買。

有關(guān)I2C通信內(nèi)部工作的更多詳細(xì)信息,請查看以下鏈接:

http://www.robot-electronics.co.uk/i2c-tutorial

http://www.i2c-bus.org/結(jié)果

https://en.wikipedia.org/wiki/I%C2%B2C

步驟3:設(shè)置

上圖中的設(shè)備使用引腳A4和A5進(jìn)行I2C通信。每種類型的arduino和Wire庫的I2C引腳說明如下:

https://www.arduino.cc/zh/Reference/Wire

主設(shè)置看起來像這樣:

#include

void setup() {

// note that begin() has no parameter.

Wire.begin();

}

從站設(shè)置看起來像這樣:

#include

void setup() {

// note that begin() has a parameter.

// Any number from 0.。..127 will work.

Wire.begin(1);

}

如果您要在該網(wǎng)絡(luò)上使用第二個(gè)從站,則需要除#1外的地址,因?yàn)樵摰刂芬驯皇褂?。這意味著只能通過仔細(xì)計(jì)劃來添加和刪除網(wǎng)絡(luò)上的設(shè)備。許多使用I2C的設(shè)備都將帶有一個(gè)帶撥碼開關(guān)(小光開關(guān))的PCB,可以將其撥動(dòng)以更改地址。便宜的型號將有裸露的接觸。要翻轉(zhuǎn)這些開關(guān),必須觸摸裸觸點(diǎn)。

第4步:發(fā)送數(shù)據(jù)

與之交談的人,然后發(fā)送信息,然后說“我完成了。”

void loop() {

Wire.beginTransmission(1);

Wire.write(“hello, ”);

Wire.endTransmission();

}

從站僅需發(fā)送信息。每個(gè)人都假定從服務(wù)器正在與主機(jī)通信。

void loop() {

Wire.write(“world!”);

}

Wire.write()具有三個(gè)版本:一個(gè)用于單個(gè)數(shù)字,一個(gè)用于字符串,以及一個(gè)用于數(shù)據(jù)塊。您必須告訴Wire數(shù)據(jù)塊有多長時(shí)間。

步驟5:接收數(shù)據(jù)

主機(jī)可以使用

Wire.read()

從網(wǎng)絡(luò)獲取單個(gè)字節(jié)的數(shù)據(jù),而不管是誰發(fā)送的。

Wire.read()是阻塞操作-您的Arduino在讀取一個(gè)字節(jié)之前不會做其他任何事情。如果沒有要讀取的字節(jié),則可能要等待很長時(shí)間!為避免此問題,還有

Wire.available()

將返回等待讀取的字節(jié)數(shù)。

將兩者放在一起,

while(Wire.available()) {

char c = Wire.read();

// do something with c

// maybe count how much we received,

// do something when we get the whole message.

}

// do other stuff while we wait for the whole message.

第6步:請求/接收

您已經(jīng)擁有運(yùn)行I2C網(wǎng)絡(luò)所需的一切,但是我想讓您了解另外一項(xiàng)功能,這有點(diǎn)棘手,所以請忍受我。實(shí)際上,我會說這完全是不需要,但是我將其包括在內(nèi)是為了徹底。也許表明有很多方法可以完成相同的工作,有些方法比其他方法更好。

您已經(jīng)知道,在C代碼中,有諸如setup()和loop()之類的方法。您也可以創(chuàng)建自己的方法并按名稱調(diào)用它們。您是否知道可以將方法名稱作為參數(shù)發(fā)送給另一個(gè)方法?通常用于稱為回調(diào)的東西。在這種情況下,我們將告訴線庫(I2C)當(dāng)從站從網(wǎng)絡(luò)接收數(shù)據(jù)時(shí)調(diào)用哪種方法。

// a master is calling and requesting something.

void requestEvent() {

// definitely send something back.

Wire.write(2); // one byte as an example.

}

// a master has sent something.

// Might not be requesting anything.

// Might not be all the data that was sent (yet)

void receiveEvent(int bytes) {

int i;

for(i=0;i char c = Wire.read();

// do something with c.

}

// maybe send something back

}

void setup() {

Wire.begin(1); // slave address = 1

Wire.onRequest(requestEvent);

Wire.onReceive(receiveEvent);

}

void loop() {

// do nothing!

}

此處的一些注意事項(xiàng):

requestEvent()不會收到數(shù)字,說明主機(jī)期望多少字節(jié)。

據(jù)我所知,這些事件是中斷-無論loop()中發(fā)生了什么,它們都會盡快發(fā)生。如果時(shí)間和代碼正確,那么無論循環(huán)做什么,都可能會嚴(yán)重混亂。由于很難重新創(chuàng)建導(dǎo)致問題的條件,因此很難診斷出它為什么混亂。

因此,正如我所說的,盡管您可以使用這些工具,但我不建議您這樣做

第7步:雙向通信

現(xiàn)在讓我們將它們放在一起。

主代碼:

#include

#define TO_MASTER_SIZE 3

#define TO_SLAVE_SIZE 4

#define START_NODE 1 // The starting I2C address of slave nodes

#define END_NODE 2 // last node to probe +1

#define NODE_READ_DELAY 100 // Some delay between I2C node reads

byte messageToMaster[TO_MASTER_SIZE];

byte messageToSlave[TO_SLAVE_SIZE];

void setup() {

Serial.begin(9600);

Serial.println(“MASTER”);

Wire.begin(); // Activate I2C link

}

void loop() {

for (int address = START_NODE; address 《 END_NODE; address++) {

sendToSlave(address);

readFromSlave();

}

delay(NODE_READ_DELAY);

}

void sendToSlave(int address) {

// message is 0123

for(int i = 0; i 《 SEND_SIZE; i++) {

messageToSlave[i] = (byte)i;

}

Wire.beginTransmission(address);

Wire.write(messageToSlave, TO_SLAVE_SIZE);

Wire.endTransmission();

}

void readFromSlave() {

// if data size is available from nodes

if(Wire.available() == TO_MASTER_SIZE) {

for (int i = 0; i 《 TO_MASTER_SIZE; i++) {

messageToMaster[i] = Wire.read(); // get data

}

int fromAddress = messageToMaster[0];

int value = ((int)messageToMaster[1] 《《 8 ) | (int)messageToMaster[2];

Serial.print(“Slave ”);

Serial.print(fromAddress);

Serial.print(“ says ”);

Serial.print(value);

}

}

從站代碼:

#include

// Change this unique address for each I2C slave node

#define NODE_ADDRESS 1

// matches values on master side.

#define TO_MASER_SIZE 3

#define TO_SLAVE_SIZE 4

#define NODE_READ_DELAY 100

byte messageToMaster[TO_MASTER_SIZE];

byte nodeReceive[TO_SLAVE_SIZE];

void setup() {

Serial.begin(9600);

Serial.print(“SLAVE #”);

Serial.println(NODE_ADDRESS);

Wire.begin(NODE_ADDRESS); // Activate I2C network

}

void loop() {

delay(NODE_READ_DELAY);

if(Wire.avaialable() == TO_SLAVE_SIZE) {

readFromMaster();

sendToMaster();

}

}

void readFromMaster() {

for(int i = 0; i 《 TO_SLAVE_SIZE; i ++){

nodeReceive[i] = Wire.read();

}

Serial.print(“Master says ”);

for(int i = 0; i 《 TO_SLAVE_SIZE; i ++){

Serial.print(nodeReceive[i]);

}

Serial.println();

}

void sendToMaster() {

int x = analogRead(A0);

messageToMaster[0] = NODE_ADDRESS;

messageToMaster[1] = (x0》》8) & 0xff; // the top byte of x

messageToMaster[2] = (x0 ) & 0xff; // the bottom byte of x

Wire.write(messageToMaster,TO_MASTER_SIZE);

Serial.print(“Sensor value: ”);

Serial.println(x);

}

有趣的一點(diǎn)是,總線(網(wǎng)絡(luò))上的任何人都可以收聽雙向通信。從理論上講,可以添加一個(gè)靜默設(shè)備,其唯一的工作就是監(jiān)視網(wǎng)絡(luò)。

第8步:最終想法

單個(gè)I2C網(wǎng)絡(luò)可能有多個(gè)主機(jī),但這是多余的棘手的問題–主機(jī)之間必須進(jìn)行協(xié)商以避免彼此之間的交談,這會導(dǎo)致混亂。

責(zé)任編輯:wv

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • aduino
    +關(guān)注

    關(guān)注

    0

    文章

    3

    瀏覽量

    3442
收藏 人收藏

    評論

    相關(guān)推薦

    ad如何設(shè)置兩個(gè)元器件的距離

    之間應(yīng)保持的最小距離,以確保電路板的電氣性能和制造過程的可靠性。以下是如何在AD中設(shè)置兩個(gè)元器件之間距離的步驟: 一、進(jìn)入規(guī)則設(shè)置界面 打開AD軟件 :首先,確保你已經(jīng)打開了Altium Designer軟件,并加載了需要
    的頭像 發(fā)表于 09-02 15:31 ?2933次閱讀

    兩個(gè)ESP8266模塊之間如何進(jìn)行TCP通信?

    嗨,我有兩個(gè)ESP8266模塊,我希望它們之間進(jìn)行TCP通信。 我已經(jīng)編寫了固件,將一個(gè) ESP 配置為 AccessPoint,另一
    發(fā)表于 07-12 06:26

    使用UDP廣播在兩個(gè)ESP8266之間進(jìn)行通信,發(fā)送會存在延遲是怎么回事?

    我正在使用 UDP 廣播在兩個(gè)ESP8266 (wemos) 之間進(jìn)行通信。 作為測試,我只是從第一個(gè)設(shè)備發(fā)送 10 個(gè)字節(jié),第二
    發(fā)表于 07-11 06:27

    兩個(gè)PLC之間如何交互信號

    在工業(yè)自動(dòng)化系統(tǒng)中,PLC(Programmable Logic Controller,可編程邏輯控制器)是核心的控制設(shè)備。在許多復(fù)雜的應(yīng)用場景中,需要兩個(gè)或多個(gè)PLC之間進(jìn)行信號交互,以實(shí)現(xiàn)更高
    的頭像 發(fā)表于 06-14 16:57 ?3069次閱讀

    I3C接口通信基礎(chǔ)

    I 2 CI3C之間顯著的變化是時(shí)鐘速度。I 2
    發(fā)表于 05-03 10:22 ?3032次閱讀
    <b class='flag-5'>I3C</b>接口<b class='flag-5'>通信</b>基礎(chǔ)

    arcgis中如何關(guān)聯(lián)兩個(gè)屬性表

    在ArcGIS中,關(guān)聯(lián)兩個(gè)屬性表是一個(gè)重要的操作,可以通過此操作將兩個(gè)表中的數(shù)據(jù)關(guān)聯(lián)起來,以便進(jìn)行分析和查詢。下面是詳細(xì)介紹如何在ArcGIS中實(shí)現(xiàn)屬性表的關(guān)聯(lián)。 首先,我們需要明確
    的頭像 發(fā)表于 02-25 11:01 ?3693次閱讀

    使用片ADU360進(jìn)行I2C通信,當(dāng)與從機(jī)進(jìn)行通信時(shí),從機(jī)無法進(jìn)入I2C中斷是為什么?

    問題說明:使用片ADU360進(jìn)行I2C通信,主機(jī)使用IO口模擬方式,從機(jī)使用內(nèi)部外設(shè) 主機(jī)IO口模擬方式,確認(rèn)是可行,當(dāng)與從機(jī)進(jìn)行
    發(fā)表于 01-15 06:47

    i2c接口和spi接口區(qū)別

    重要的區(qū)別。 I2C接口和SPI接口都屬于串行通信接口標(biāo)準(zhǔn),廣泛應(yīng)用在嵌入式系統(tǒng)和電子設(shè)備中。它們之間的主要區(qū)別在于通信協(xié)議、電氣特性、速度和適用場景等方面。
    的頭像 發(fā)表于 12-25 15:02 ?3436次閱讀

    如何給C語言中的函數(shù)定義兩個(gè)不同的名字?

    最近有位哥問我,如何給C語言中的函數(shù)定義兩個(gè)不同的名字?就是這兩個(gè)名字都是指向同一個(gè)函數(shù),同一個(gè)地址,而且
    的頭像 發(fā)表于 12-19 16:21 ?671次閱讀

    i2c工作原理及使用方法

    的標(biāo)準(zhǔn)。 I2C協(xié)議具有以下特點(diǎn): 簡單:I2C使用根線(數(shù)據(jù)線SDA和時(shí)鐘線SCL)進(jìn)行通信,極大地簡化了連接的線路。 多主機(jī):支持多個(gè)
    的頭像 發(fā)表于 12-19 16:17 ?1097次閱讀

    兩個(gè)硬盤2個(gè)系統(tǒng)開機(jī)切換

    切換兩個(gè)硬盤上的系統(tǒng)是一種常見的行為,可以讓用戶在不同的操作系統(tǒng)之間進(jìn)行切換,以滿足不同的需求。在本文中,我們將詳細(xì)介紹如何配置和使用兩個(gè)硬盤上的系統(tǒng)
    的頭像 發(fā)表于 11-28 15:08 ?6850次閱讀

    UART、SPI、I2C比較 串口通信介紹

    UART、SPI、I2C比較 I2C線更少,比UART、SPI更為強(qiáng)大,但是技術(shù)上也更加麻煩些,因?yàn)?b class='flag-5'>I2C需要有雙向IO的支持,而且使用上拉電阻,抗干擾能力較弱,一般用于同一板卡上芯片之間
    的頭像 發(fā)表于 11-09 18:06 ?1206次閱讀
    UART、SPI、<b class='flag-5'>I2C</b>比較 串口<b class='flag-5'>通信</b>介紹

    兩個(gè)單片機(jī)之間串口通信的例程

    今天來分享一下兩個(gè)單片機(jī)之間串口通信的例程吧!仿真文件的話,只要添加兩個(gè)單片機(jī)就OK了。那么如果想用手里的單片機(jī)來實(shí)現(xiàn)的話,不妨接收端用電腦來接收吧。下面就來看一下今天的例程吧!
    的頭像 發(fā)表于 11-09 10:05 ?6145次閱讀
    <b class='flag-5'>兩個(gè)</b>單片機(jī)<b class='flag-5'>之間</b>串口<b class='flag-5'>通信</b>的例程

    ch340怎么實(shí)現(xiàn)兩個(gè)單片機(jī)之間的io口通信?

    使用ch340,怎么實(shí)現(xiàn)兩個(gè)單片機(jī)之間的io口通信
    發(fā)表于 11-03 06:33

    兩個(gè)51單片機(jī)之間能實(shí)現(xiàn)藍(lán)牙通信嗎?

    兩個(gè)51單片機(jī)之間能實(shí)現(xiàn)藍(lán)牙通信
    發(fā)表于 10-28 07:48