Giao tiếp I2C 2 chiều giữa Arduino Uno và Arduino Mega


7

Nếu tôi loại bỏ mã truyền từ Slave thì nó hoạt động đúng nhưng tôi cần truyền từ Slave.

Đây là mã chủ của tôi

#include <Wire.h>
void setup() {
  Wire.begin(3); 
  Wire.onReceive(receiveEvent);
}
byte x = 0;

void loop() {
  Wire.beginTransmission(9); 
  Wire.write("s");        
  Wire.write(x);                
  Wire.endTransmission();    
  x++;
  delay(500);
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    int x = Wire.read();
    Serial.println(x);
  }
}

Đây là mã nô lệ của tôi:

#include <Wire.h>
void setup() {
  Wire.begin(9);                // join i2c bus with address #9
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

void receiveEvent(int howMany) {
  if(Wire.available()){
    char c = Wire.read(); 
    Serial.print(c);
    if(c == 's'){
      int x = Wire.read();
      Serial.println(x);
      //transmit to master 
      Wire.beginTransmission(3);
      Wire.write(1);
      Wire.endTransmission();
    } else {
      Wire.read();
    }
  }
}

Có thể không sử dụng Wire.onRequest (requestCallback); để gửi dữ liệu cho chủ? Giúp đỡ một cách tử tế.


1
Khi một bản phác thảo gọi Wire.begin () và vượt qua một số, nó đã tự chỉ định mình là nô lệ trên xe buýt. Vì vậy, bạn dường như có hai nô lệ. Thông thường người ta sẽ có một chủ và một nô lệ.

Những gì bạn có vẻ muốn là một sự kết hợp của Arduino Arduino Tutorial arduino.cc/en/Tutorial/MasterReaderarduino.cc/en/Tutorial/MasterWriter bạn có đồng ý không?

tôi đã có một cái nhìn nhưng không thể thực hiện nó đúng bất kỳ đề nghị? nếu tôi cho 2 dây. Viết chủ không đọc đúng

Tôi không biết ý của bạn là gì, xin lỗi.

Wire.requestFrom chỉ có một dây. Tôi cần nhiều dây. Không được hỗ trợ, vậy có cách giải quyết nào không?
srinivas

Câu trả lời:


6

Để tham gia xe buýt với tư cách là chủ, bạn không thể cung cấp địa chỉ nô lệ 7 bit để mã của bạn có hai nô lệ.

Dưới đây bạn sẽ tìm thấy 2 bản phác thảo gửi thành công dữ liệu cho một nô lệ. Tôi sẽ đề nghị bạn bắt đầu nhìn vào giao thức I2C và hiểu rằng có 4 Chế độ:

  • Master-> Máy phát
  • Master-> Người nhận
  • Nô lệ-> Máy phát
  • Nô lệ-> Người nhận

Tất cả các thông tin liên lạc bất kể dữ liệu được truyền như thế nào đều cần có chủ. Đó là bậc thầy điều khiển các xung đồng hồ, đó là lý do tại sao nó luôn là chủ nhân khởi tạo sự khởi đầu.

Các MasterReader / MasterWriter hướng dẫn trên diễn đàn Arduino bây giờ sẽ có thể bắt đầu làm cho một chút ý nghĩa hơn khi tìm hiểu những chế độ.

Mã này cho thấy cách một chủ gửi dữ liệu đến một nô lệ, và sau đó là cách nó yêu cầu dữ liệu từ nô lệ. Nếu chúng ta xem mã này từ quan điểm chính, bạn có thể thấy nó về cơ bản là nói, gửi byte này đến máy khách (m-> t & s-> r), sau đó yêu cầu dữ liệu từ Slave (m-> r, s-> t)

mã chủ

#include <Wire.h>

#define SLAVE_ADDRESS 0x60

void setup()
{
  Wire.begin(); 
  randomSeed(analogRead(3));
  Serial.begin(9600);  
}

byte x = 0;

void loop()
{
  x = random(0,255);
  Serial.print("Sent: ");
  Serial.print(x, HEX);
  Serial.print("\n");
  Wire.beginTransmission(0x60);   
  Wire.write(x);                
  Wire.endTransmission();   
  delay(500);
  Serial.println("Requesting Data"); 
  Wire.requestFrom(SLAVE_ADDRESS, 1);

  int bytes = Wire.available();
  Serial.print("Slave sent ");
  Serial.print(bytes);
  Serial.print(" of information\n");
  for(int i = 0; i< bytes; i++)
  {
    x = Wire.read();
    Serial.print("Slave Sent: ");
    Serial.print(x, HEX);
    Serial.print("\n");
  }  
  delay(500);
}

Mã nô lệ

#include <Wire.h>

#define SLAVE_ADDRESS 0x60
byte x = 0x00;
void setup()
{
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
  Serial.begin(9600);
}

void loop()
{
  delay(100);
}

void requestEvent() 
{
  Serial.print("Request from Master. Sending: ");
  Serial.print(x, HEX);
  Serial.print("\n");

  Wire.write(x);
}

void receiveEvent(int bytes)
{
  if(Wire.available() != 0)
  {
    for(int i = 0; i< bytes; i++)
    {
      x = Wire.read();
      Serial.print("Received: ");
      Serial.print(x, HEX);
      Serial.print("\n");
    }
  }
}

Trên tổng thể, bạn có thể quét phạm vi địa chỉ cho thiết bị được kết nối. Đây sẽ là một cách tiếp cận đúng đắn.
wajatimur

Trong cả hai trình xử lý sự kiện của bạn: Không thực hiện in nối tiếp bên trong ISR. Nó có thể hoạt động cho đến khi bộ đệm nối tiếp lấp đầy, sau đó nó sẽ bị treo.
Nick Gammon

1
Bạn không cần kiểm tra if(Wire.available() != 0)bytesbiến có số byte bạn nhận được. Nếu có bất cứ điều gì, hãy kiểm tra xem bytes > 0tuy nhiên tôi cho rằng một sự kiện nhận sẽ có ít nhất một byte.
Nick Gammon

1

Tôi đã trải qua vấn đề này gần đây. Nô lệ của bạn cần hai chức năng: một để gửi và chức năng khác để nhận dữ liệu.

// function: what to do when asked for data
void requestEvent() {
Wire.write(t); 
}

// what to do when receiving data from master
void receiveEvent(int howMany)
{Val = Wire.read();}

Đây là một mã hoạt động cả hai cách giao tiếp i2c trong một mã

Gửi và nhận các loại dữ liệu khác nhau thông qua I2C trong Arduino


0

Bạn có:

 void receiveEvent(int howMany)
 {
   {         
         if(Wire.available()){
           char c = Wire.read(); 
           Serial.print(c);
           if(c == 's'){
             int x = Wire.read();
             Serial.println(x);

             //transmit to master 
             Wire.beginTransmission(3);
             Wire.write(1);
             Wire.endTransmission();

           }else{
             Wire.read();
           }
         }

       }

Có một số vấn đề với mã nô lệ của bạn.

  1. Không thực hiện in nối tiếp trong ISR (dịch vụ thường xuyên bị gián đoạn)
  2. Đừng bắt đầuTransmission / endTransmission trong một sự kiện nhận.
  3. Đừng viết
  4. Để gửi lại dữ liệu, hãy sử dụng requestEvent chứ không phải receiveEvent.

Tốt hơn sẽ là:

// add in setup()
Wire.onRequest (requestEvent);  // interrupt handler for when data is wanted

...


volatile byte what;

void receiveEvent(int howMany)
{
  if (howMany < 2)
    return;

  char c = Wire.read ();
  if (c != 's')
    return;

  what = Wire.read ();  // remember what we got
}  // end of receiveEvent

void requestEvent()
{
  Wire.write (1);  // return a response
}  // end of requestEvent

Wire.requestFrom chỉ có một Wire.write. Tôi cần nhiều Wire.write không được hỗ trợ để có cách giải quyết nào không?

Batch up trả lời và viết một:

void requestEvent ()
  {
  byte buf [4] = { 1, 2, 3, 4 };
  Wire.write (buf, sizeof buf);   // send response
  }  // end of requestEvent

Tài liệu tham khảo

Có rất nhiều ví dụ tại I2C - Giao diện ngoại vi hai dây - cho Arduino

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.