Electronic – i2c on different logic level devices

arm7i2clpcpullup

I'm having a problem making LPC2148 work with SRF10 sensor. LPC is 3.3v device with 5v compatible i2c (at least user docu claims that). On the other side there is SRF10 device which is 5v.
I have tried with both levels as pull-up lvl connected with 4.7k resistor (i have 3 devices on same line so i used higher value resistor).

Strange thing is that it sometimes read the value correctly but it fails to read values from 2 registers… Basically, it doesnt work.

I2c bad readout

Now, what is strange on this picture, is that logic lvl on SDA is 0 by default and it should be 1. That means that pull-up is not doing the job well ? Could that be related to logic lvl differences between uc and slave ?

EDIT:01.03

Here is my implementation of state 0x50, a_chn is i2c0 or i2c1

void slaveDataReceived (uint8_t a_chn)
{
uint8_t k;
volatile unsigned char *i2cConClear;
volatile unsigned char *i2cConSet;
volatile unsigned char *i2cData;

if (a_chn == 1) {
    i2cData = (volatile unsigned char *)(0xE005C008);
    i2cConClear = (volatile unsigned char *)(0xE005C018);
    i2cConSet = (volatile unsigned char *)(0xE005C000);
    }
else {
    i2cData = (volatile unsigned char *)(0xE001C008);
    i2cConClear = (volatile unsigned char *)(0xE001C018);
    i2cConSet = (volatile unsigned char *)(0xE001C000);
    }   

k = *i2cData;
appendToDataBuffer (a_chn, k);
if (i2cDataRcv[a_chn] == i2cDataHead[a_chn]){
    I2CMasterState[a_chn] = I2C_IDLE;
    *i2cConSet = I2CON_SET_STO;
    *i2cConClear = I2CON_CLR_AAC;
    }
else {
    *i2cConSet = I2CON_SET_AA;
    }
*i2cConClear = I2CON_CLR_SIC;   
}

Best Answer

I see valid start and restart conditions in your waveform, so I don't think SDA is the 'wrong polarity'. The valid start condition is there before writing 0xC0 (indicated by the first green dot in the capture) and the valid restart is the second green dot (before 0xC1). The fact that SDA stays low after the master ACKs the slave shouldn't be an issue as long as the master releases it before the next rising edge of SCL.

One issue could be the size of the pull-ups. If you're trying to operate faster than 100kHz, you may need stiffer pull-ups to ensure the edges are sharp.

Another issue is that the master should NACK the last expected read byte, even if it is valid data, since many slaves expect a NACK before they will allow a valid stop condition to come through. For your single-byte reads, the master should NACK the data byte. For the 16-bit registers, it should ACK the first byte and NACK the second one. I've seen quite a few slave devices hang the bus or malfunction if the last read isn't 'terminated' by a NACK.