极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11666|回复: 1

Arduino 之间的 I2C 通讯 (2) 由 master 向 slave 发送资料/发出指令 [直接处理]

[复制链接]
发表于 2015-8-1 21:22:06 | 显示全部楼层 |阅读模式
本帖最后由 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
回复

使用道具 举报

发表于 2016-5-8 00:49:01 | 显示全部楼层
学习了,真不错,期待4、5、6、7、8、9........章节,谢谢!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-29 11:07 , Processed in 0.058899 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表