步骤1:您需要什么:
我们假设您具有以下部分:
两个Arduino UNO
一些公对母电线
一些公对公电线
一个旋转电位计
一个面包板
步骤2:I²C的工作方式
I²C是一种通信协议,使您可以在微控制器和某些传感器等电路之间进行通信。它仅使用两根线(如此高效!)。第一线是时钟线,通常在文档中写为SCL。第二根线是数据线,通常写为SDA。
I²C总线上的设备可以是“主机”或“从机”。仅主机控制时钟线上的电压,而主机和从机都可以操纵数据线上的电压。通过仔细轮流,网络上的所有设备都可以共享信息。
为了将信息发送到正确的位置,每个从站都有一个唯一的地址号码,就像每个电话都有一个唯一的号码一样。
当我看到I²C器件时,他们有文档说:“该电路希望接收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进行I²C通信。每种类型的arduino和Wire库的I²C引脚说明如下:
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外的地址,因为该地址已被使用。这意味着只能通过仔细计划来添加和删除网络上的设备。许多使用I²C的设备都将带有一个带拨码开关(小光开关)的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步:请求/接收
您已经拥有运行I²C网络所需的一切,但是我想让您了解另外一项功能,这有点棘手,所以请忍受我。实际上,我会说这完全是不需要,但是我将其包括在内是为了彻底。也许表明有很多方法可以完成相同的工作,有些方法比其他方法更好。
您已经知道,在C代码中,有诸如setup()和loop()之类的方法。您也可以创建自己的方法并按名称调用它们。您是否知道可以将方法名称作为参数发送给另一个方法?通常用于称为回调的东西。在这种情况下,我们将告诉线库(I²C)当从站从网络接收数据时调用哪种方法。
// 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步:最终想法
单个I²C网络可能有多个主机,但这是多余的棘手的问题–主机之间必须进行协商以避免彼此之间的交谈,这会导致混乱。
责任编辑:wv
-
aduino
+关注
关注
0文章
3浏览量
3445
发布评论请先 登录
相关推荐
评论