This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Can someone help me troubleshoot my 28035 I2C code?

Hi there, I've been trying to get some I2C devices to work with my 28035, but I get stuck because the I2C peripheral won't clear the STP bit.  It gets hung up on a while loop I created to wait for the message to finish transmitting.

Here is my initialization code: https://dl.dropboxusercontent.com/u/13579266/code_part1.txt

And here is the function I use to send the message:  https://dl.dropboxusercontent.com/u/13579266/code_part2.txt

I've run some debugs and found that the program can't seem to make it past the expression "while(I2caRegs.I2CMDR.bit.STP == 1);"  It just hangs there forever.

Any ideas?

  • I probed the SCL line with an oscilloscope.  It seems to hang high.  I don't even see a flicker of activity even when sending messages repeatedly.

  • I suppose I should also say that I'm using an XDS100v2 JTag emulator to debug this thing.

  • What happens when you comment out the line it hangs at?

  • It hangs at while(I2caRegs.I2CSTR.bit.XRDY == 0); instead.  Still nothing on the oscilloscope.

  • The application gets stuck after transferring 8 bytes to the I2C transmit register.  I think the transmit shift register buffer is getting full.

    That being said, I think the problem is that my start condition isn't beginning the transmission.  That's why the SCL line is being held high, it's in idle mode.  That's why I'm getting stuck waiting for the STP bit, it's never cleared if the transmission never finishes.  That's why I get stuck on XRDY, is because the transmission isn't clearing the buffer.

    Can someone please look at the code in my first post and help give me some guidance?  Thank you!

    I'll be looking through the MCU datasheet myself.

    //////////////////////////////////////////////////////////////////////////////

    Scratch the thing about the STP bit.  It seems to be clearing now.  I'm still getting stuck on XRDY, though.

  • Since you are using the FIFO you dont have to poll the XRDY bit. I think the FIFO on the 335 is 16 deep so you can write 16 words to I2CDXR back to back without waiting.

    Also, analyzing your code

    		for(i = 0; i < IMU_NUMBYTES_OFFSETS; i++) {
    			while(I2caRegs.I2CSTR.bit.XRDY == 0);	// wait until the previous byte has moved to the shift register
    													// before sending the next one
    			switch(i) {
    			case 0:		I2caRegs.I2CDXR = IMU_ADDR_X_OFFS_USRH;		break;		// send the address of the first register
    			case 1:		I2caRegs.I2CDXR = IMU_INIT_X_OFFS_USRH;		break;		// each of these bytes is written in sequence
    			case 2:		I2caRegs.I2CDXR = IMU_INIT_X_OFFS_USRL;		break;		// starting at the register address (first byte sent)
    			case 3:		I2caRegs.I2CDXR = IMU_INIT_Y_OFFS_USRH;		break;
    			case 4:		I2caRegs.I2CDXR = IMU_INIT_Y_OFFS_URSL;		break;
    			case 5:		I2caRegs.I2CDXR = IMU_INIT_Z_OFFS_USRH;		break;
    			case 6:		I2caRegs.I2CDXR = IMU_INIT_Z_OFFS_USRL;		break;
    			}
    		}
    
    		I2caRegs.I2CMDR.all = 0x6E20;				// send the START condition

    the first time you get into the for loop the I2C has just been reset(assume) so XRDY=1, so it proceeds to the switch case and you load the first word into I2CDXR, this sets XRDY=0,
    the next time around in the for loop XRDY stays 0 because you dont start the transmission in the for loop...its outside.... so the data is not transferred from I2CDXR to I2CXSR and onto the line

    so what you can do is
    1. setup for FIFO mode as you have done
    2. in for loop load all 8 bytes, dont poll XRDY.
    3. Set the start bit in I2CMDR
  • Oh, okay, that makes sense.  Should I add pauses between each of the I2CDXR assignments to make sure each byte makes it to the shift register?

  • No, in FIFO mode you should be able to write back-to-back words to I2CDXR till the FIFO queue fills up.

  • I feel that I'm getting close.  Here is my code:

    Initialization: https://dl.dropboxusercontent.com/u/13579266/code2_part1.txt

    Writing to IMU: https://dl.dropboxusercontent.com/u/13579266/code2_part2.txt

    Reading from IMU: https://dl.dropboxusercontent.com/u/13579266/code3_part3.txt

    I'm trying to verify my I2C code by writing to a register then reading from it and comparing the values.  My most immediate issue is that when I read from the IMU, I always receive a 0xFF byte.  I think that SDA may be staying high for the entire read, which would mean that the IMU is not responding.

    I've been having a lot of confusion as to which bits to poll if I want to make sure that a message has been sent/received, so that may be my issue entirely.  I'm really not sure.

    Please let me know if you have any ideas!  Thanks!

    --Daniel

  • Daniel Mayben said:
    I'm trying to verify my I2C code by writing to a register then reading from it and comparing the values.  My most immediate issue is that when I read from the IMU, I always receive a 0xFF byte.  I think that SDA may be staying high for the entire read, which would mean that the IMU is not responding.

    Well since you are using FIFO RX. you could

    1. Set an interrupt level (RXFFIL), say you expect 2 bytes so set the interrupt level to 2. When the FIFO starts filling up and it hits the threshold level it triggers the RXFFINT

    2. IF you dont want the RXFFINT signal to vector to an ISR clear the RXFFIENA bit. So you can then just keeep polling the RXFFINT to see if you have the expected number of bytes on the FIFO...Dont forget to clear this bit after you are done reading

    Daniel Mayben said:
    I always receive a 0xFF byte.  I think that SDA may be staying high for the entire read, which would mean that the IMU is not responding.

    Does the IMU ACK its own address? If it does then the IMU is responsive, but its likely waiting for a command or some additional bytes to be transmitted from the master before it responds. Atleast thats how it is with EEPROMs.

  • How can I tell if the IMU acknowledged its address?

    Or any message, for that matter?

    I ask because it seems like any code I've written in the past has gotten hung up waiting for either an ACK or an NACK.

  • Well the Address stream looks like this

    | ST | A6 | A5 | A4 | A3 | A2 | A1 | A0 | R/nW | ACK/NACK |

    You have the start, 7-bit address followed by read/write bit followed by ACK/NACK phase. During the ACK/NACK phase, the slave must pull the SDA line signifying it acknowledges the comm, if it doesnt the master considers the line condition a NACK. So poll the NACKINT bit to see if the NACK was flagged. Alternatively you could scope the line to see if the slave is wiggling the SDA during the ACK/NACK phase.

    If it isnt ACK'ing the address, check to make sure the address is correct. For instance, on EEPROMs they have pins that configure the last n(usually 2) bits of the slave address. The IMU module might have something similar, you want to ensure you dont have a cold joint at one of those address pins.

  • Vishal_Coelho said:
    the slave must pull the SDA line signifying it acknowledges the comm

    meant to say the slave must pull the SDA line low