极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 11937|回复: 6

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

[复制链接]
发表于 2015-8-1 23:32:05 | 显示全部楼层 |阅读模式
本帖最后由 Super169 于 2015-8-1 23:34 编辑

相关指令:

指令发出者作用
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 的资料


slave 延迟处理

之前的一篇, 不是已经可以由 master 向 slave 发送资料, 而 slave 亦成功收到了, 为什麽又搅个 延迟处理出来?

之前一篇, 处理 master 送来的资料, 都是在接收的函数之内.  但大家不要忘记, arduino 的主线, 是在 loop 之内执行的.  接收函数太大, 或会影响主程式进行, 而且, 有些时候, 主程式或许需要用到接收回来的资料.

延後处理就是把资料放进缓存一样, 让主程式去处理.
方法很简单, 可以直接把资料放有有关变数, 又或用最通用的方式, 先放入一个 buffer 中.

以下例子, 就是用最通用的方式处理,

[pre lang="arduino" line="1" file="slave_03.ino"]#include <Wire.h>

#define SLAVE_ADDRESS 0x12
#define SERIAL_BAUD 57600

#define I2C_BUFFER_SIZE 32  
uint8_t i2cBuffer[I2C_BUFFER_SIZE];
uint8_t i2cBufferCnt = 0;
boolean dataPending = false;

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.03 started\n");
}

void loop() {
  if (dataPending) {
    Serial.println("Receive Data:");
    for (int idx = 0; idx < i2cBufferCnt; idx++) Serial.print((char) i2cBuffer[idx]);
    Serial.println("\n");   
    dataPending = false;
  }
}

void receiveEvent(int count) {
  i2cBufferCnt = 0;
  while(Wire.available()) {
    i2cBuffer[i2cBufferCnt++] = Wire.read();
  }
  dataPending = true;
}[/code]

执行後, 跟之前的是没分别的.
当然, 你也可以尝试把 i2c 的 buffer 加大或收细, 看看有什麽影响.


相关程式下载 (master_03 跟 master_02 是一样的)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2016-5-8 00:54:50 | 显示全部楼层
这个好,实用价值大!
回复 支持 反对

使用道具 举报

发表于 2016-5-8 11:05:14 | 显示全部楼层
你好,首先感谢您,看了这篇帖子我的问题解决了95%,之前是我不够认真。还有一点小问题向请教您:
这是我的主机
#include <Wire.h>

#define SLAVE_ADDRESS 0x12
#define SERIAL_BAUD 9600


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(50);
    }
    Wire.endTransmission();
  }
}
从机:
#include <Wire.h>
#include <HX711.h>
#include <Stepper.h>

#define SLAVE_ADDRESS 0x12
#define SERIAL_BAUD 9600
#define STEPS 100// 这里设置步进电机旋转一圈是多少步
Stepper stepper(20, 10, 11);// attached to设置步进电机的步数和引脚
HX711 hx(6, 7, 128,0.00237642);

#define I2C_BUFFER_SIZE 32  
uint8_t i2cBuffer[I2C_BUFFER_SIZE];
uint8_t i2cBufferCnt = 0;
boolean dataPending = false;

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.03 started\n");
  stepper.setSpeed(5000);      // 设置电机每分钟的转速为5000步
  hx.set_offset(390800);
}

void loop() {
  if (dataPending) {
    Serial.println("Receive Data:");
    for (int idx = 0; idx < i2cBufferCnt; idx++) Serial.print((char) i2cBuffer[idx]);
    Serial.println("\n");  
    dataPending = false;
   
    Serial.println("measure Data:");
    int sum0 = 0;
    int sum1 = 0;
    for (int i = 0; i < 10; i++) {
      sum0 += hx.read();
      sum1 += hx.bias_read();
   }
     Serial.print(sum0/10);
     Serial.print(" ");
     Serial.println(sum1/10);
     stepper.step(sum1/10-i2cBuffer);
     Serial.println("\n");
  
  }
}

void receiveEvent(int count) {
  i2cBufferCnt = 0;
  while(Wire.available()) {
    i2cBuffer[i2cBufferCnt++] = Wire.read();
  }
  dataPending = true;
}

问题出现这一行,stepper.step(sum1/10-i2cBuffer);  我想用主机发送的数据,也就是i2cBuffer,但是提示出错,invalid operands of types 'int' and 'uint8_t [32] {aka unsigned char [32]}' to binary 'operator-',这个错误不太明白,请指教下,谢谢
回复 支持 反对

使用道具 举报

发表于 2016-5-8 19:15:02 | 显示全部楼层
本帖最后由 soolge 于 2016-5-8 23:02 编辑

之后,我想了个结果方法,在这句话 for (int idx = 0; idx < i2cBufferCnt; idx++) Serial.print((char) i2cBuffer[idx]);
    Serial.println("\n");  
后面加了一句,char c=1000*i2cBuffer[0]+100*i2cBuffer[1]+10*i2cBuffer[2]+i2cBuffer[3];
                      Serial.println(c,dec);  
但是这个数会乱码。比如我在主机上输0567,结果这个c显示的是随机一个数67.请问这是什么原因
[url=上一个代码问题解决了,现在提取数组中的数出了问题 http://www.geek-workshop.com/thread-26752-1-1.html][/url]
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-5-9 01:28:38 | 显示全部楼层
soolge 发表于 2016-5-8 19:15
之后,我想了个结果方法,在这句话 for (int idx = 0; idx < i2cBufferCnt; idx++) Serial.print((char) i2 ...
  1. char c=1000*i2cBuffer[0]+100*i2cBuffer[1]+10*i2cBuffer[2]+i2cBuffer[3];
复制代码
這個語句相信這裡很多人也可以指出問題來, 你也實在太亂來了.

你的問題基本上跟 i2c 通訊無關的.   建議你先了解一下 Serial (或者 stream) 庫的用法 以及 C++ 的基本語法吧.

回复 支持 反对

使用道具 举报

发表于 2016-5-9 11:26:32 | 显示全部楼层
本帖最后由 soolge 于 2016-5-9 13:12 编辑

改完了  可以用了  谢谢您了 这段时间不停的指导  真的感谢
回复 支持 反对

使用道具 举报

发表于 2016-5-9 17:17:27 | 显示全部楼层
厉害,支持一下
回复 支持 反对

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-4-29 13:46 , Processed in 0.073866 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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