Problems with I2C communication, mbed to mbed

05 Mar 2012

Hello people! I'm having some problems establishing an I2C communication between two mebds where I put one as Master and the other as Slave, everytime i try sending information from one side to the other, my "returns" from the functions write and read are never 0, hence are never ACK. To tell the truth I'm no pro in I2C, but reading some blogs I think I got a hint of what is causing the problems, I just don't know how to code the solutions. 1- I don't exactly how to referentiate the internal registers of the mbed to perform the reads and writes, I tried making I2C communication without making any reference to them, just passing information as strings but I don't know if it's possible.2- Maybe I'm having some problems because my Slave is actually a microprocessor and my clock stretching is not working properly, not giving enough time for my slave mbed to perform its interruption and save its stateand then sending information. Well, the codes are below, if anybody could give me a hand I'd very much appreciate it. PS: All those waits in the code were just unsuccessful attempts to give some time for the communication to take place.

MASTER:

#include "mbed.h"

I2C i2c(p28, p27);        
Serial pc(USBTX, USBRX); 



int main() {
    int addr = 0x01;
    int a,b;
    char buff[10]; const char data[]="message master"; 
    
    i2c.frequency(10000);    
    
        
    while(1) { 
        i2c.start();               
              
        a=i2c.read(addr, buff,10);
        wait(0.75);
        
        pc.printf("Read %d", a);// only to check if there was an ACK, till now, not working
        
        i2c.stop();  
               
        
        pc.printf("MASTER READ: %s \n\r", buff);
        
        i2c.start();
        
        b=i2c.write( addr, data, 10);
        wait(0.75);
        
        i2c.stop();
        
        pc.printf("Write %d", b); // only to check if there was an ACK, till now, not working
        
        for(int i = 0; i < 10; i++) buff[i] = 0;
           
       
    }
}

SLAVE:
#include "mbed.h"

  I2CSlave slave(p9,p10);
  Serial pc(USBTX, USBRX); 
  

int main() {    

    const char test[]= "message slave";
    char buf[10];
    int i, b;
    
    slave.frequency(10000);
    slave.address(0x01);
    
    
    

    while(1) {
        
        i = slave.receive();
        wait(0.75);
        
        switch (i) {
            
            case I2CSlave::ReadAddressed:
                
                slave.stop();
                b=slave.write(test, strlen(test) + 1); 
                wait(0.75);
                
                pc.printf("Return Slave %d", b);// only to check return value
                
                break;
            case I2CSlave::WriteGeneral:
                
                slave.stop();
                slave.read(buf, 10);
                wait(0.75);
                pc.printf("SLAVE Read G: %s\n\r", buf);
                break;
            case I2CSlave::WriteAddressed:
                
                slave.stop();
                slave.read(buf, 10);
                wait(0.75);
                pc.printf("SLAVE Read A: %s\n\r", buf);
                break;
        }
        for(int i = 0; i < 10; i++) buf[i] = 0;        
        
    }
}
05 Mar 2012

SLAVE:

#include "mbed.h"

  I2CSlave slave(p9,p10);
  Serial pc(USBTX, USBRX); 
  

int main() {    

    const char test[]= "message slave";
    char buf[10];
    int i, b;
    
    slave.frequency(10000);
    slave.address(0x01);
    
    
    

    while(1) {
        
        i = slave.receive();
        wait(0.75);
        
        switch (i) {
            
            case I2CSlave::ReadAddressed:
                
                slave.stop();
                b=slave.write(test, strlen(test) + 1); 
                wait(0.75);
                
                pc.printf("Return Slave %d", b);// only to check return value
                
                break;
            case I2CSlave::WriteGeneral:
                
                slave.stop();
                slave.read(buf, 10);
                wait(0.75);
                pc.printf("SLAVE Read G: %s\n\r", buf);
                break;
            case I2CSlave::WriteAddressed:
                
                slave.stop();
                slave.read(buf, 10);
                wait(0.75);
                pc.printf("SLAVE Read A: %s\n\r", buf);
                break;
        }
        for(int i = 0; i < 10; i++) buf[i] = 0;        
        
    }
}
05 Mar 2012

Your slaveaddress is wrong. The lsb is ignored since it is used to indicate read or write operations. Use 0x02 or some other even value. Also get rid of the slave.stop.

I assume your hardware connections between Master and Slave are OK:

  • connect Master SCL to Slave SCL
  • connect Master SDA to Slave SDA
  • connect GND of both devices
  • connect a pullup R to 3V3 on the SDA and SCL
12 Mar 2012

Hello Wim, thanks for the tips, but it stil doesn't work, i've double checked all the hardware connections and it is alright.Do you have any other ideas?

12 Mar 2012

So what does your code look like now. I assume you changed slaveaddress on master and slave side. Do you get any printf feedback on master and/or slave side.

Has your master side been able to read or write any data to or from a simple hardware device like the port expander PCF8574. That test will at least show that the Master part is OK.

26 Mar 2012

Wim, i'm sending my code, I simplified so that only the master tries to write something for the slave, but it still doesn't work, do you know if the mbed API already takes care for example of setting the internal register in which to write the I2C message in? SLAVE:

#include "mbed.h"

  I2CSlave slave(p9,p10);
  Serial pc(USBTX, USBRX); 
  

int main() {    

    const char test[]= "message slave";
    char buf[10];
    int i, b;
    
    slave.frequency(10000);
    slave.address(0xA0);
    
    
    

    while(1) {
        
        i = slave.receive();
        
        printf("i=%d\n\r",i);
        wait(1);
        
        switch (i) {
            
            case I2CSlave::ReadAddressed:
                pc.printf("aqui1");
               // slave.stop();
                b=slave.write(test, strlen(test) + 1); 
                wait(0.07);
                
                pc.printf("Return Slave %d", b);
                
                break;
            case I2CSlave::WriteGeneral:
                pc.printf("aqui2");
               // slave.stop();
                slave.read(buf, 10);
                //wait(1);
                pc.printf("SLAVE Read G: %s\n\r", buf);
                break;
            case I2CSlave::WriteAddressed:
                pc.printf("aqui3");
                //slave.stop();
                slave.read(buf, 10);
                //wait(1);
                pc.printf("SLAVE Read A: %s\n\r", buf);
                break;
        }
        for(int i = 0; i < 10; i++) buf[i] = 0;        
        
    }
}

SLAVE

#include "mbed.h"

I2C i2c(p28, p27);        
Serial pc(USBTX, USBRX); 



int main() {
    const int addr = 0xA0;
    int a,b;
    char buff[10]; const char data[]="message master"; 
    
    i2c.frequency(10000);
    
    
    
        
    while(1) { 
       /* i2c.start();               
              
        a=i2c.read(addr, buff,10,1);
        wait(1);
        
        pc.printf("Read %d", a);
        
        i2c.stop();
        
               
        
        pc.printf("MASTER READ: %s \n\r", buff);*/
        
        i2c.start();
        
        b=i2c.write( addr, data, strlen(data)+1);
        
        wait(0.07);
        
        i2c.stop();
        
        pc.printf("Write %d\n\r", b);
        
        for(int i = 0; i < 10; i++) buff[i] = 0;
        
           
       
    }
}
28 Mar 2012

Hi Leonardo Leonardo,

I can not test the code at the moment. A few more hints/questions:

  1. slave.frequency(10000); That bitrate is rather low. It should work, but use a more common value like slave.frequency(100000);
  2. There is a mismatch between the send length and the receive length. You send a message ("message master") of 15 bytes (including the 0 at end). The slave receives only 10 bytes and then tries to print that as string (%s). The missing 0 at the end of that string will also cause problems.
  3. Did you test the i2c send code on a simple portexpander. Are you getting any of your printf debugmessages ?
23 Apr 2012

hello Wim, i managed to get the program working, thanks for all the help, i'm just havong some problem to send a char instead of a const char from the slave to the master, i actually started another topic about it. Thanks