|
本帖最后由 Super169 于 2015-8-1 23:34 编辑
Arduino 之间的 I2C 通讯 (2) 由 master 向 slave 发送资料/发出指令 [slave 直接处理]
相关指令:
指令 | 发出者 | 作用 | Wire.begin([<address>]); | master / slave | 启动 Wire (由於 i2c 是用 Wire 的, 这就等同启动 i2c 了) | Wire.beginTransmission(<address>); | master | 开始对 <address> 的连线 | Wire.endTransmission(); | master | 关闭之前的连线 | Wire.write(<data>); | master | 在连线上送出 一个 byte 的资料 | Wire.onReceive(<function>); | slave | 设定用来接收资料的函数 | Wire.available(); | slave | 检查连线上是否有可接收的资料 | Wire.read(); | slave | 读取连线上的一个 byte 的资料 |
通讯也有不同程度的, 先做一个最简单的单向通讯.
由於只有 master 可以主动发出通讯要求, 最简单的就是由 master 向 slave 发送资料了.
这个例子是针对一些操控装置, 例如你做了一个 i2C 的舵机, 由 arduino 发出指令, 要它转到指定的角度, 而舵机是不会回传任何资料的
程式同样分开 mater 及 slave 的部份, master 发送, slave 接收.
master 发送资料
在 master 发送资料, 只有几个简单步骤就可以了:
- 执行 beginTransmission 并指定接收资料地址
- 以 Wire.write 把资料送出去
- 执行 endTransmission 作结束
以下是一个简单的例子, master 把 串口收到的资料, 发送给 slave.
[pre lang="arduino" line="1" file="master_02.ino"]#include <Wire.h>
#define SLAVE_ADDRESS 0x12
#define SERIAL_BAUD 57600
void setup()
{
Wire.begin();
Serial.begin(SERIAL_BAUD);
Serial.println("I2C Master.02 started");
Serial.println();
}
void loop()
{
if (Serial.available()) {
Wire.beginTransmission(SLAVE_ADDRESS);
while(Serial.available()) {
Wire.write(Serial.read());
delay(1);
}
Wire.endTransmission();
}
}
[/code]
slave 接收资料
而 slave 接收, 是有点像 interrupt driven 的形式去做, 简单的做法如下.
- 执行 Wire.onReceive 去设定接收资料的函数
- 在接收资料的函数中, 不断以 Wire.available 检查是否有资源, 并以 Wire.read 把一个 byute 资料提出, 直到所有资料提出後, Wire.available 为 false
注意, 因为 Wire 库的 buffer 只有 32 个 byte, 每次发送的资料应限制在 32 个 byte 之内.
由於 master 进行 write 是没有限制的, 如果发送超过 32 bytes, 之後的资料就会流失.
以下例子, 是在 接收的函数中, 直接处理接收回来的资料.
[pre lang="arduino" line="1" file="slave_02.ino"]#include <Wire.h>
#define SLAVE_ADDRESS 0x12
#define SERIAL_BAUD 57600
void setup() {
Wire.begin(SLAVE_ADDRESS); // join I2C bus as a slave with address 1
Wire.onReceive(receiveEvent); // register event
Serial.begin(SERIAL_BAUD);
Serial.println("I2C Slave.02 started\n");
}
void loop() {
}
void receiveEvent(int count) {
Serial.println("Receive Data:");
while(Wire.available()) {
Serial.print((char) Wire.read());
}
Serial.println("\n");
}
[/code]
注意:
这个例子中在 receiveEvent 中用到 Serial.print, 只是为了简单展示结果, 虽然这里没有问题, 但其实是绝不应该的.
在正常的程式中, 应该尽量避免在 receiveEvent 中放入复杂的程序, 在下一章中会提及正确的做法.
执行程式後, 在 master 板子连线的 serial monitor 输入资料, 就会发送到 slave 板子, 再在相关的 serial monitor 显示出来.
相关程式下载:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|