I've tried to setup I2C communication between two LPC 2129 boards where one is the master and the other board is the slave. The code follows the following flow. 1.Initialize the output pins. 2.Initialize the interrupts. 3.Setup the I2C with proper symbol rate and Master/Slave config. 4.Start communication.
The simulation of these programs work properly on keil. All the registers initialize properly but in the hardware the communication doesn't happen. I've used a pull up resistor of 2.7K for the line with a 3.3V supply and the line remains high throughout. The start never bit never gets initialized and the controllers go into a loop waiting for the communication to interrupt the system.
Is there anything I have missed in the program ??
a not too uncommon problem is that the master get ready some milliseconds before the slave and what you see could be a result of that.
a simple way to check is to set a breakpoint in the master before it start communicating, if that makes the thingy work, Voila!
Erik
Thanks erik
I tried the solution you proposed. I even tried starting the master much after the slave, also added a 0.5 msec delay but this has yielded the same results. I've attached the code for the master for your reference
# include <LPC21xx.h> int measurementrq(void); int datafetch(void); void uart(void); void i2cirq(void)__irq; void startbit (void); void restart (void); void datarcv (void); void lastdat(void); /*global variables*/ unsigned int datcnt,count,SA = 0x27,datbuf,temp,hum,tempi,tempi1,dati; unsigned char data[4],dir,si,tempc,humc; int main(void) { si = 0; //initialise the SI register to keep track of the activity of the i2c bus IODIR1 = 0x00010000; /* setup the vector for I2C interrupt*/ VICVectAddr2 = (unsigned)i2cirq; //Set the timer ISR vector address VICVectCntl2 = 0x00000029; PINSEL0 = 0x00000055; VICIntEnable =0x00000200; /* setup the I2C bus for Master operation*/ I2CONCLR = 0x6C; I2SCLL = 0x0c; I2SCLH = 0x0d; IOCLR1 = 0x00010000; /*setup the UART 2400*/ U0LCR = 0X0000008B; U0DLL = 0X00000004; U0DLM = 0X00000001; U0LCR = 0X0000000B; while (!(U0LSR & 0x20)); U0THR = 0x43; while (!(U0LSR & 0x20)); while(1) { int cnt; I2CONSET = 0x40; for (cnt = 0;cnt<0xFFFF;cnt++) { IOCLR1 = 0x00010000; } for (cnt = 0;cnt<0xFFFF;cnt++) { IOSET1 = 0x00010000; } measurementrq(); IOSET1 = 0x00010000; datafetch(); IOSET1 = 0x00010000; uart(); } } /*interrupt subroutine for various condition handling */ void i2cirq(void)__irq { IOSET1 = 0x00010000; /*transmit byte conditions*/ switch(I2STAT) { case (0x08): //Start bit tramsmitted startbit(); break; case(0x10) : //repeat start condition restart(); break; case (0x18): //Slave address+W, ACK I2CONSET = 0x50; //change more to a read mode to read the data from the memory operation send STOP [clear the SI flag ] si = 0; //release the I2C loop wait mode and process data break; //Receive byte conditions case (0x40) : //Slave Address +R, ACK I2CONSET = 0x04; //data bit will be recvd ack will be returned break; case (0x50) : //Data Received, ACK finally NACK datarcv(); break; case(0X58) : //last data recieved lastdat(); break; default : break; } I2CONCLR |=0x08; VICVectAddr = 0x00000000; return ; } int measurementrq(void) { //int cnt; si = 1; dir = 0; I2CONSET = 0x20; while(si == 1 ) { //;for (cnt = 0;cnt<0xFFFF;cnt++) { IOCLR1 = 0x00010000; } /*for (cnt = 0;cnt<0xFFFF;cnt++) { IOSET1 = 0x00010000; }*/ } return dir; } int datafetch(void) { si = 1; //bus is busy hence forth all the action will be handled by the ISR only data processing will be done in the end dir = 1; I2CONSET |= 0x60; while(si == 1 ) { ; } I2CONCLR = 0x40; //data[0] = 0x00; //un comment this part in case for operation with the sensor /* if (data[0] & 0xC0) { datafetch(); } else { uart(); } */ return dir; } void uart(void) { dati = data[0] & 0x3F; hum = ((dati<<8)+data[1]); tempi = data[2]; tempi1 = (data[3] & 0xFC); temp = (((tempi<<8)+tempi1)>>2); /* calculations */ datbuf = ((hum*0x64)/0x3FFE); humc = datbuf; datbuf = ((temp/0x3FFE)*0xA5)-0x28; tempc = datbuf; while (!(U0LSR & 0x20)); U0THR = humc; while (!(U0LSR & 0x20)); U0THR = tempc; while (!(U0LSR & 0x20)); return; } void startbit (void) { I2CONCLR = 0x20; //Clear start bit I2DAT = ((SA<<1)|dir); //Send address and appropriate read/write bit count = 0; IOSET1 = 0x00010000; //si = 0; } void restart (void) { I2CONCLR |= 0x20; //Clear start bit I2DAT = ((SA<<1)|dir); //Send address and appropriate read/write bit count = 0; } void datarcv (void) { if(count<=2) { data[count] = I2DAT; I2CONSET = 0x04;//assert an ack to the signal when the count reaches When the final count asser a nak on the bus as well as a stop on the bus count++; } else { data[count] = I2DAT; I2CONCLR = 0x04; //Stop condition count++; } } void lastdat(void) { data[count] = I2DAT; I2CONSET = 0x50; //data BYTE AND NACK STOP [clear the SI flag ] IOCLR1 = 0x00010000; si = 0; //release the I2C loop wait mode and process data }
I wld be grateful for the help Thank You