This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

I2C STOP condition on LPC2387

If anyone has a good sample of I2C on LPC2387 (MCP2300 Dev board) other than the simple example from Keil, I'd like to know. I have a condition where the I2C seems to be running correctly for a two byte read of the LM75 temp sensor, I'm getting the data I expect to see, but I'm not getting a good STOP condition at the end. The I2C controller seems to think it has stopped correctly, but the I2C SDA bus line remains low. Scope trace included. The code is almost exactly Keil's example, but I added a loop and tried to make sure the NAK was being generated on the last byte. Any clues out there? I don't see how to attach the files, so give me an email address and I'll send them over. Code attached in line below.

Main:

while(1) {

for ( i = 0; i < BUFSIZE; i++ ) // clear buffer { I2CMasterBuffer[i] = 0; } I2CWriteLength = 2; I2CReadLength = 0; I2CMasterBuffer[0] = LM75_ADDR; I2CMasterBuffer[1] = LM75_CONFIG; I2CMasterBuffer[2] = 0x00; // configuration value, no change from I2CCmd = LM75_CONFIG; //I2CEngine();

/* Get temp reading */ for ( i = 0; i < BUFSIZE; i++ ) /* clear buffer */ { I2CMasterBuffer[i] = 0; } I2CWriteLength = 1; I2CReadLength = 2; I2CMasterBuffer[0] = LM75_ADDR; I2CMasterBuffer[1] = LM75_TEMP; I2CMasterBuffer[2] = LM75_ADDR | RD_BIT; I2CCmd = LM75_TEMP; I2CEngine(); for ( j = 0; j < 10000000; j++ ) ; }

I2C interrupt routine:

void I2C0MasterHandler(void) __irq
{ BYTE StatValue;

/* this handler deals with master read and master write only */ StatValue = I20STAT; IENABLE; /* handles nested interrupt */ switch ( StatValue ) { case 0x08: /* A Start condition is issued. */ I20DAT = I2CMasterBuffer[0]; I20CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC); I2CMasterState = I2C_STARTED; break;

case 0x10: /* A repeated started is issued */ if ( I2CCmd == LM75_TEMP ) { I20DAT = I2CMasterBuffer[2]; } I20CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC); I2CMasterState = I2C_RESTARTED; break;

case 0x18: /* Regardless, it's a ACK */ if ( I2CMasterState == I2C_STARTED ) { I20DAT = I2CMasterBuffer[1+WrIndex]; WrIndex++; I2CMasterState = DATA_ACK; } I20CONCLR = I2CONCLR_SIC; break;

case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */ case 0x30: if ( WrIndex != I2CWriteLength ) { I20DAT = I2CMasterBuffer[1+WrIndex]; /* this should be the last one */ WrIndex++; if ( WrIndex != I2CWriteLength ) { I2CMasterState = DATA_ACK; } else { I2CMasterState = DATA_NACK; if ( I2CReadLength != 0 ) { I20CONSET = I2CONSET_STA; /* Set Repeated-start flag */ I2CMasterState = I2C_REPEATED_START; } } } else { if ( I2CReadLength != 0 ) { I20CONSET = I2CONSET_STA; /* Set Repeated-start flag */ I2CMasterState = I2C_REPEATED_START; } else { I2CMasterState = DATA_NACK; I20CONSET = I2CONSET_STO; /* Set Stop flag */ } } I20CONCLR = I2CONCLR_SIC; break;

case 0x40: /* Master Receive, SLA_R has been sent */ I20CONSET = I2CONSET_AA; /* assert ACK after data is received */ I20CONCLR = I2CONCLR_SIC; break;

case 0x50: /* Data byte has been received, regardless following ACK or NACK */ case 0x58: I2CMasterBuffer[3+RdIndex] = I20DAT; RdIndex++; if ( RdIndex != I2CReadLength ) { I2CMasterState = DATA_ACK; I20CONSET = I2CONSET_AA; /* assert ACK after data is received */ } else { I20CONCLR = I2CONCLR_AAC; /* assert ACK after data is received */ RdIndex = 0; I2CMasterState = DATA_NACK; } I20CONCLR = I2CONCLR_SIC; break;

case 0x20: /* regardless, it's a NACK */ case 0x48: I20CONCLR = I2CONCLR_SIC; I2CMasterState = DATA_NACK; break;

case 0x38: /* Arbitration lost, in this example, we don't deal with multiple master situation */ default: I20CONCLR = I2CONCLR_SIC; break; } IDISABLE; VICVectAddr = 0; /* Acknowledge Interrupt */ if ( I2CMasterState == DATA_NACK ); { //I20CONSET = I2CONSET_STO; /* Set Stop flag */ }
}

0