5
\$\begingroup\$

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;   
}
\$\endgroup\$
  • 1
    \$\begingroup\$ If it's reading/writing from every device except just 2 registers from one device, then that should tell you the i2c bus is working correctly, and it's possibly either your code, or the srf10 that's buggy. As for the SDA being low, it shouldn't matter until a start condition is attempted in your single master setup. Is one of the other i2c devices not 5v tolerant? Does the line go high if you place only the LPC and the SRF10 on the bus and nothing else? Can you read from all registers with only the LPC and SRF on the bus? \$\endgroup\$ – Passerby Feb 28 '13 at 8:32
  • \$\begingroup\$ All three devices are 5v and only lpc is 3.3v (but 5v tolerant). I tried disconnecting all devices except one and i get the same behavior. SRF is working as i tried it on AVR (5v). SRF has 4 registers. First is revision, which i could read and got 5 as value (which should be ok). Second is unused but it returns 0x80 when reading. (also correctly read). And registers 3-4 are 16bit value. Reading those registers returns strange values. (I have "calibration" environment in which i have tested read values and concluded that they are garbage.) \$\endgroup\$ – Gossamer Feb 28 '13 at 8:57
  • \$\begingroup\$ From your scope output, are you giving it a big enough delay? The ranger will not respond while ranging. Check your code to see if you can find why the SDA output is held low before i2c transmission is enabled, that might be what is throwing things off (But imho, I don't think that's too big of an issue). Aside from that, someone else might chime in. \$\endgroup\$ – Passerby Feb 28 '13 at 9:40
  • \$\begingroup\$ I know that between ranging and readout needs at least 65ms, i have put 100ms. This low level before and after the reading is somewhat strange. When i use SDA/SCL pins as GPIO and create square signal, everything acts normal. Regardless of pull-up which is connected to lines. Output is from LA not scope. I checked it also with scope and i get low lvl as -0.3v and high lvl as ~3v. \$\endgroup\$ – Gossamer Feb 28 '13 at 10:08
  • \$\begingroup\$ These issues are likely beyond the capabilities of a logic analyzer. I highly recommend you use an oscilloscope to check communications because there can be very marginal logic levels that usually work and then fail. \$\endgroup\$ – Gustavo Litovsky Feb 28 '13 at 16:04
3
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ I have noticed that LPC is ACK everything. But as datasheet states, NACK is default. I explicitly cleared ACK on last byte receive interrupt, but it stills ACK it. From the logic lvl, is ACK 1 or 0? Maybe because my SDA is pulled low all the time, ACK is defaulted ? In that case pull-up value is too large ? \$\endgroup\$ – Gossamer Mar 1 '13 at 8:41
  • \$\begingroup\$ I think there is no chance that this is pull-up related. If you disconnect the slave from the bus, do you see NACKs? (The master may be and acknowledging itself) \$\endgroup\$ – Adam Lawrence Mar 1 '13 at 13:20
  • \$\begingroup\$ @Gossamer Acks are logic 0 (Line is actively pulled low). Nacks are logic 1 (line is released, pull-up is used). If your clock rate is too fast for the pull-up, that could be an issue, but you have otherwise working communications using that pull-up. \$\endgroup\$ – Passerby Mar 1 '13 at 14:49
  • \$\begingroup\$ Well it seems i had too many ACK's in the code. I was lead by the documentation for LPC21xx in which they stated that almost every state should set ACK bit in register. Also i have removed *i2cConSet = I2CON_SET_STO; from code in question post. All of those or some of those recent changes in the code made i2c working now. Now i have to analyze what exactly caused the problems by re-enabling the old code line by line. \$\endgroup\$ – Gossamer Mar 4 '13 at 10:29
  • \$\begingroup\$ Well done! I suffered a bit writing my own I2C master code and understand how tricky it can be to get things working, especially on the protocol-side of things. \$\endgroup\$ – Adam Lawrence Mar 4 '13 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.