Super169 发表于 2015-8-1 23:32:05

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

本帖最后由 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 中.

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

#include <Wire.h>

#define SLAVE_ADDRESS 0x12
#define SERIAL_BAUD 57600

#define I2C_BUFFER_SIZE 32
uint8_t i2cBuffer;
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);
    Serial.println("\n");   
    dataPending = false;
}
}

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

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


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

glmyc 发表于 2016-5-8 00:54:50

这个好,实用价值大!:):):):):):)

soolge 发表于 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;
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);
    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 = Wire.read();
}
dataPending = true;
}

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

soolge 发表于 2016-5-8 19:15:02

本帖最后由 soolge 于 2016-5-8 23:02 编辑

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

Super169 发表于 2016-5-9 01:28:38

soolge 发表于 2016-5-8 19:15 static/image/common/back.gif
之后,我想了个结果方法,在这句话 for (int idx = 0; idx < i2cBufferCnt; idx++) Serial.print((char) i2 ...

char c=1000*i2cBuffer+100*i2cBuffer+10*i2cBuffer+i2cBuffer;這個語句相信這裡很多人也可以指出問題來, 你也實在太亂來了.

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

soolge 发表于 2016-5-9 11:26:32

本帖最后由 soolge 于 2016-5-9 13:12 编辑

改完了可以用了谢谢您了 这段时间不停的指导真的感谢

原野动力 发表于 2016-5-9 17:17:27

厉害,支持一下
页: [1]
查看完整版本: Arduino 之间的 I2C 通讯 (3) 由 master 向 slave 发送资料/发出指令 [延迟处理]