We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi everyone,
First off I would like to thank those who have taken the time to read this post.
My environment Windows XP uVision 3 Keil MCB2300 with NXP LPC2386
Goal Read a temperature sensor
Physical Setup I have pins 24 and 25 exposed on my Dev board ( just some male headers ) which is I2C Bus 0. Also the appropriate pins are connected to a device with some I2C devices on it.
I am going to display code in the order in which it is executed for simplicity. There is also some defines which I will display too.
Even though documentation and startup code state that all registers are initialized to 0, I do it also.
There are other PINSEL and FIO0DIR registers set, but I believe it is irrelevant.
PINSEL0 &= 0x00000000; PINSEL1 &= 0x00000000; FIO0DIR |= 0x407E8B00; //pins [9:8], 11, 15, [22:17], 30 are ouputs
This function is used to setup I2C. I am showing it all just in case I have overlooked something.
uint8 I2CInit( ) { PCONP |= (1 << 7); /*Enable PCI2C0 interface 0 power/clock control bit */ PINSEL1 |= 0x01400000; /* set P0.27 and P0.28 to I2C0 SDA and SCK */ PCONP |= (1 << 19); /*Enable PCI2C1 interface 1 power/clock control bit */ PINSEL0 |= 0x0000000F; /* set P0.00 and P0.01 to I2C1 SDA and SCK */ PCONP |= (1 << 26); /*Enable PCI2C2 interface 2 power/clock control bit */ PINSEL0 &= ~0x00F00000; PINSEL0 |= 0x00A00000; /* set P0.10 and P0.11 to I2C2 SDA and SCK */ /*--- Clear flags ---*/ I20CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC; I21CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC; //I22CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC; /*--- Reset registers ---*/ I20SCLL = I2SCLL_SCLL; I20SCLH = I2SCLH_SCLH; I21SCLL = I2SCLL_SCLL; I21SCLH = I2SCLH_SCLH; if ( install_irq( I2C0_INT, (void *)I2C0MasterHandler, HIGHEST_PRIORITY ) == FALSE ) { return FAIL; } if ( install_irq( I2C1_INT, (void *)I2C1MasterHandler, HIGHEST_PRIORITY ) == FALSE ) { return FAIL; } I20CONSET = I2CONSET_I2EN; I21CONSET = I2CONSET_I2EN; return SUCCESS; }
At this point everything should be initiated and ready to go
The function below gets called when we want to read an I2C device that requires a write first.
addr = Address of I2C device sz = Size of response offset = The register inside of the device I want to read buff = The buffer that gets passed here contains storage for the response of the read bus = Specify which bus the I2C device is connected to
int write_readI2C(uint8 addr, uint8 sz, uint8 offset, uint8 *buff, uint8 bus) { uint8 i; uint16 stat; /* shift address to bits 7-1; bit 0 is R/W */ I2CMasterBuffer[0] = addr<<1; /* write 2 size: I2C address + offset to read */ I2CWrLength = 2; I2CMasterBuffer[1] = offset; /* now load read command */ I2CMasterBuffer[2] = addr<<1 | RD_BIT; I2CRdLength = sz; stat = I2CEngine(bus); if (stat) return stat; if (RdIndex == 0) //no data was read return FAIL; //(I2C_ERR_MASK | RD_ERR); for ( i = 0; i < sz; i++ ) buff[i] = I2CMasterBuffer[i+3]; return stat; }
The line stat = I2CEngine(bus); above is the function stated below
uint8 I2CEngine( BYTE bus ) { DWORD timeout = 0; I2CMasterState = I2C_IDLE; RdIndex = 0; WrIndex = 0; I2CStop(bus); if (I2CStart(bus) != SUCCESS) { I2CStop(bus); return FAIL; } while ( 1 ) { if ( I2CMasterState == I2C_STOP) //DATA_NACK { I2CStop(bus); break; } if ( timeout >= MAX_TIMEOUT ) return FAIL; timeout++; } return SUCCESS; }
The statement if (I2CStart(bus) != SUCCESS) above is where the error occurs
#define MAX_TIMEOUT 0x00008FFF uint8 I2CStart( uint8 bus ) { uint32 timeout = 0; uint8 returnValue = FAIL; if (bus == 1) I21CONSET = I2CONSET_STA; /* Set Start flag */ else if (bus == 0) I20CONSET = I2CONSET_STA; /* Set Start flag */ /*--- Wait until START transmitted ---*/ while( 1 ) { if (I2CMasterState == I2C_STARTED) { returnValue = SUCCESS; break; } if ( timeout >= MAX_TIMEOUT ) { returnValue = FAIL; break; } timeout++; } return( returnValue ); }
The statement if ( timeout >= MAX_TIMEOUT ) above is where the program takes me if I set a breakpoint inside the IF statement.
I was going to post my I2C0MasterHandler IRQ but this post is getting long.