步驟1:您需要什么:
我們假設您具有以下部分:
兩個Arduino UNO
一些公對母電線
一些公對公電線
一個旋轉電位計
一個面包板
步驟2:I2C的工作方式
I2C是一種通信協議,使您可以在微控制器和某些傳感器等電路之間進行通信。它僅使用兩根線(如此高效!)。第一線是時鐘線,通常在文檔中寫為SCL。第二根線是數據線,通常寫為SDA。
I2C總線上的設備可以是“主機”或“從機”。僅主機控制時鐘線上的電壓,而主機和從機都可以操縱數據線上的電壓。通過仔細輪流,網絡上的所有設備都可以共享信息。
為了將信息發送到正確的位置,每個從站都有一個唯一的地址號碼,就像每個電話都有一個唯一的號碼一樣。
當我看到I2C器件時,他們有文檔說:“該電路希望接收N字節表示ABC的數據,并發送回M字節表示DEF的數據。”如果您要購買的設備不包含此信息,則不要購買。
有關I2C通信內部工作的更多詳細信息,請查看以下鏈接:
http://www.robot-electronics.co.uk/i2c-tutorial
http://www.i2c-bus.org/結果
https://en.wikipedia.org/wiki/I%C2%B2C
步驟3:設置
上圖中的設備使用引腳A4和A5進行I2C通信。每種類型的arduino和Wire庫的I2C引腳說明如下:
https://www.arduino.cc/zh/Reference/Wire
主設置看起來像這樣:
#include
void setup() {
// note that begin() has no parameter.
Wire.begin();
}
從站設置看起來像這樣:
#include
void setup() {
// note that begin() has a parameter.
// Any number from 0.。..127 will work.
Wire.begin(1);
}
如果您要在該網絡上使用第二個從站,則需要除#1外的地址,因為該地址已被使用。這意味著只能通過仔細計劃來添加和刪除網絡上的設備。許多使用I2C的設備都將帶有一個帶撥碼開關(小光開關)的PCB,可以將其撥動以更改地址。便宜的型號將有裸露的接觸。要翻轉這些開關,必須觸摸裸觸點。
第4步:發送數據
與之交談的人,然后發送信息,然后說“我完成了。”
void loop() {
Wire.beginTransmission(1);
Wire.write(“hello, ”);
Wire.endTransmission();
}
從站僅需發送信息。每個人都假定從服務器正在與主機通信。
void loop() {
Wire.write(“world!”);
}
Wire.write()具有三個版本:一個用于單個數字,一個用于字符串,以及一個用于數據塊。您必須告訴Wire數據塊有多長時間。
步驟5:接收數據
主機可以使用
Wire.read()
從網絡獲取單個字節的數據,而不管是誰發送的。
Wire.read()是阻塞操作-您的Arduino在讀取一個字節之前不會做其他任何事情。如果沒有要讀取的字節,則可能要等待很長時間!為避免此問題,還有
Wire.available()
將返回等待讀取的字節數。
將兩者放在一起,
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步:請求/接收
您已經擁有運行I2C網絡所需的一切,但是我想讓您了解另外一項功能,這有點棘手,所以請忍受我。實際上,我會說這完全是不需要,但是我將其包括在內是為了徹底。也許表明有很多方法可以完成相同的工作,有些方法比其他方法更好。
您已經知道,在C代碼中,有諸如setup()和loop()之類的方法。您也可以創建自己的方法并按名稱調用它們。您是否知道可以將方法名稱作為參數發送給另一個方法?通常用于稱為回調的東西。在這種情況下,我們將告訴線庫(I2C)當從站從網絡接收數據時調用哪種方法。
// 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!
}
此處的一些注意事項:
requestEvent()不會收到數字,說明主機期望多少字節。
據我所知,這些事件是中斷-無論loop()中發生了什么,它們都會盡快發生。如果時間和代碼正確,那么無論循環做什么,都可能會嚴重混亂。由于很難重新創建導致問題的條件,因此很難診斷出它為什么混亂。
因此,正如我所說的,盡管您可以使用這些工具,但我不建議您這樣做
第7步:雙向通信
現在讓我們將它們放在一起。
主代碼:
#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);
}
有趣的一點是,總線(網絡)上的任何人都可以收聽雙向通信。從理論上講,可以添加一個靜默設備,其唯一的工作就是監視網絡。
第8步:最終想法
單個I2C網絡可能有多個主機,但這是多余的棘手的問題–主機之間必須進行協商以避免彼此之間的交談,這會導致混亂。
責任編輯:wv
-
aduino
+關注
關注
0文章
3瀏覽量
3462
發布評論請先 登錄
相關推薦
評論