EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC176X I2C reading ADC121C021

Started by sig5534 February 4, 2013
Great frustration trying to get the 16b data read back from a ADC121C021. I've got many other I2C chips on the bus, not much problem getting them working right, but I can't get the ARM I2C state machine to do the right things to read this ADC.

I have written the ISR Read routine like the NXP doc says in the manual, but that results in an infinite loop that the ADC/MCU never comes out of, bouncing between states 0x10 and 0x40 forever. Also tried some Keil library I2C code (which doesn't match the NXP doc), but it didn't work right either. This is a MasterRead setup.

For this ADC the protocol is suppose to be:
- Send SlaveAdr+R
- ACK from ADC
- Read MSB from ADC
- ACK from MCU
- Read LSB from ADC
- NAK & STOP from MCU

Sounds simple. Yeah right, 2 days later still fighting it.
The best I have been able to do is get the MSB data byte out of the ADC, but have yet to see the LSB byte come out.

The kind of traffic I see through the ISR looks like this:

I2C_OP: BusNum=1 DevAdr PMem007F54 ByteCnt=2 (0xAD+r)
I2C: STS08 DAT CNT000000 LEN000002
I2C: STS40 DAT CNT000000 LEN000002
I2C: STS50 DAT CNT000000 LEN000002
I2C: STS50 DAT CNT000001 LEN000002
I2C: STS50 DAT CNT000002 LEN000002

It should be returning 0x0123 for the last 2 data bytes.
I can modify the code to get "01" and "01", but still not the LSB "23". I would have expected the states to run: 08,40,50,58 also.

So there is some tricky way to get the Bit Flags set perfect,
and when to read the I2DAT reg that has to be done exactly right.

Anyone who has been through this, all help is appreciated.

Regards, Chris.

Here's my ISR MasterRead code routine:

===================================================
// * Start/ReStart: 0x08 or 0x10
if ((PCTRL->Status==I2C_I2STAT_M_RX_START) ||
(PCTRL->Status==I2C_I2STAT_M_RX_RESTART )) {
PI2C->I2DAT = (PCTRL->Dev_adr |
I2C_AdrReadBit); // set SLA+R byte
PI2C->I2CONCLR = I2C_I2CONCLR_STAC;// Clr START
PI2C->I2CONSET = I2C_I2CONSET_AA; // Set ACK
PI2C->I2CONCLR =I2C_I2CONCLR_SIC; // Clr SI
return;
}

// * SLA+R, ACK rtn : 0x40
if (PCTRL->Status==I2C_I2STAT_M_RX_SLAR_ACK) {
PI2C->I2CONCLR = I2C_I2CONCLR_SIC; // Clr SI
return;
} // ack received

// * Data RX, ACK/NAK rtn : 0x50 or 0x58
if ((PCTRL->Status==I2C_I2STAT_M_RX_DAT_ACK) || (PCTRL->Status == I2C_I2STAT_M_RX_DAT_NACK)) {
// Rcve data BYTE
if (PCTRL->Count < PCTRL->Length) {
PCTRL->Dev_dat = PI2C->I2DAT & I2C_I2DAT_BITMASK;
*(uint8_t *)(PCTRL->Pdata +PCTRL->Length -PCTRL->Count -1) = PCTRL->Dev_dat; // MSB first
PCTRL->Count++;
PI2C->I2CONSET = I2C_I2CONSET_AA; // Set ACK
PI2C->I2CONCLR = I2C_I2CONCLR_SIC;// Clr SI
return;
}
else {
PCTRL->Dev_dat = PI2C->I2DAT & I2C_I2DAT_BITMASK;
*(uint8_t *)(PCTRL->Pdata +PCTRL->Length -PCTRL->Count -1) = PCTRL->Dev_dat; // MSB byte first
PCTRL->Count++;
PI2C->I2CONCLR = I2C_I2CONSET_AA; // Set NAK
PI2C->I2CONSET = I2C_I2CONSET_STO;// Set STOP
PI2C->I2CONCLR = I2C_I2CONCLR_SIC;// Clr SI
return;
}

===================================================

An Engineer's Guide to the LPC2100 Series


The 2024 Embedded Online Conference