connection issues with i2C KL25Z as master and LK05Z as slave

03 Sep 2019

Hi,

I tried to use I2C to connect KL25Z as master and KL05Z as slave, but it seems like the KL25Z master is not writing the correct data to the bus. It'd be great if anyone notice an error in the code. When I print out the slave.receive() from the slave KL05Z, it always shows 0, so I guess it does not get any command from the master. Also I checked the oscilloscope, the waveform seems to be sending the correct address and command. With 0xA0 shifted one bit to the right and last bit is high indicates write as described in the handbook in I2C_SDA.

Here's the code

<<code title=KL25Z master>> KL25Z_master

  1. include "mbed.h"
  2. include <I2C.h> define pin outs Serial pc(USBTX, USBRX); I2C i2c(I2C_SDA, I2C_SCL);

void i2C_master(); i2C parameters const int slave_addr = 0xA0 << 1;

int main() {

i2c.frequency(100000); while(1) { i2C_master(); } }

char cmd[1]; void i2C_master() { cmd[0] = 0x01; i2c.write(slave_addr,cmd,1); read and write takes the 8-bit version of the address. set up configuration register (at 0x01) wait(0.5); i2c.read(slave_addr, cmd, 2);

float tmp = (((cmd[0]<<8)|cmd[1])); printf("Temp = %s\n", cmd); } <<\code>>

<<code title=KL05Z slave>>

  1. include "mbed.h"

define pinouts I2CSlave slave(PTB4, PTB3); Serial pc(USBTX, USBRX); DigitalOut green(LED_GREEN); DigitalOut blue(LED_BLUE); DigitalOut red(LED_RED);

void i2C_slave(); i2C parameters const int addr = 0xA0 ;

int main() { slave.frequency(100000); green = 1; blue = 1; red = 1;

slave.address(addr); while(1) { i2C_slave(); } }

char buf[10]; char msg[] = {12345};

void i2C_slave() {

int i = slave.receive(); switch (i) { case I2CSlave::ReadAddressed: slave.write(msg, strlen(msg) + 1); Includes null char green = 0; wait(0.5); break; case I2CSlave::WriteGeneral: blue = 0; wait(0.5); slave.read(buf, 10); printf("Read G: %s\n", buf);

break; case I2CSlave::WriteAddressed: red = 0; wait(0.5); slave.read(buf, 10); printf("Read A: %s\n", buf); break; } pc.printf("%i",slave.receive()); for(int i = 0; i < 10; i++) buf[i] = 0; Clear buffer

} <<\code>>

/media/uploads/conrad2001/i2c.png

03 Sep 2019

Hi Conrad,

Refer to user manual of KL05Z

http://cache.freescale.com/files/32bit/doc/ref_manual/KL05P48M48SF1RM.pdf

It uses 7-bit i2c address, that means you should set i2c_address to const int slave_addr = 0xA0;.

Regards, Desmond

04 Sep 2019

it turns out I need to put a i2cSlave.stop(); after the i2cSlave.write command here's my code in case someone runs into similar problem

I2C Slave

//I2C setup
int main(){
    dacout = 0.5f;
    
    
    const int slave_addr = 0x70;
    

    I2CSlave i2c_slave1(I2C_SDA, I2C_SCL);


    //Module Initialization (Slave)
    //enable general call in Control Register 2
    I2C0->C2 |= 0x80;
    //Write: Address Register 1 to set the slave address
    //i2c_slave1.address(slave_addr);
    I2C0->A1 = slave_addr | 0;
    //I2C Frequency Divider
    I2C0->F = 0x1B;

    // Write: Control Register 1 to enable the I2C module and interrupts
    I2C0->C1 |= 0xC0;
    // Initialize RAM variables (IICEN = 1 and IICIE = 1) for transmit data
    float VDAC, VTHERMISTOR;
    
    char buf[1];
    while(1) {
        temperature_and_DACout(&VDAC, &VTHERMISTOR);
        int i = i2c_slave1.receive();
        switch (i) {
            case I2CSlave::ReadAddressed:
                i2c_slave1.write((char*)&VDAC, sizeof(VDAC));
                //put a stop bit to stop the slave from pulling the SCL line down
                i2c_slave1.stop();
                break;
            case I2CSlave::WriteAddressed:
                i2c_slave1.read(buf,strlen(buf));
                break;
        }

        for(int i = 0; i < 10; i++) buf[i] = 0;    // Clear buffer
    }
}