EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

MSP430F169 I2C peripheral issues

Started by fchambers01 January 9, 2007
Has anyone had a problem with the I2C peripheral on the 169?

I am trying to read and write to a 24LC16B eeProm. I have no trouble
with the writing, either single bytes or pages. I also have no
problems with a current pointer read. Where I can't seem to get it to
work is for a Random Read. This read requires a RESTART and it just
doesn't seem to be happening. I have tried it with a fair number of
configurations and at best I get inconsistent results, if any at all.
I have tried using the I2CNDAT counter and resetting it for the
restart and I have tried writing a byte at a time and keeping track
myself.

One thing I noticed is that the alignment flag shows up more than
occassionally though the only device connected is the eeProm.

The main program at this point calls init and then the read routine.
I have the eeProm programmed with a sequence of numbers in order to
check my addressing, if I can ever read it.

void I2C_24LC16B_init(void)
{
unsigned char baseslave = 0x50; //Top nibble of address
per data sheet
P3SEL |= 0x0A; // Select I2C pins
U0CTL |= I2C + SYNC; // Recommended init procedure
U0CTL &= ~I2CEN; // Recommended init procedure
I2CTCTL |= I2CSSEL1; // SMCLK
I2CSA = baseslave; // Slave Address is 050h
U0CTL |= I2CEN; // Ready to go
I2CTCTL = I2CSTT + I2CSTP; // Make sure at IDLE
_NOP(); //Breakpoint opportunity
}

void I2C_24LC16B_random_readbyte(short block, short page, short addr,
unsigned char *rdata)
{
// DataSheet Read Process - Random Read
// Send START
// Control Byte -R/W = W
// Wait for ACK from Slave
// Send Low Order Address
// Wait for ACK from Slave
// Send START - R/W = R
// Wait for ACK from slave
// Slave transmits byte of data at address
// Master does not ACK but sends STOP
unsigned char baseslave = 0x50;
unsigned char RXData = 0xA5; //Init so can tell if changed
short addrw;
addrw = page; //Put in page - page is 16 bytes
addrw <<= 4; //Shift to allow for address
addrw |= addr; //Or in address
while(I2CDCTL & I2CBUSY); //Wait till quiet
U0CTL &= ~I2CEN; //Disable I2C to change modes
//Will go to SW control writes and read here
I2CTCTL |= I2CRM; //Set for SW Control
U0CTL |= I2CEN; //Renable I2C to change mode
// I2CNDAT = 0x02; //Set count
U0CTL |= MST; // Master mode
I2CSA = baseslave + block; // Set eeProm address and block
I2CTCTL |= I2CTRX; // Set for transmit
while ((I2CIFG & ARDYIFG) == 0); // Wait for transmitter to be
ready
I2CTCTL |= I2CSTT; // Initiate transfer
while ((I2CIFG & TXRDYIFG) == 0); // Wait for transmitter to be
ready
I2CDRB = addrw; // Load I2CDRB with address
I2CTCTL &= ~I2CTRX; //Set for read
while ((I2CIFG & TXRDYIFG) == 0); // Wait for transmitter to be
ready
// I2CNDAT = 0x01;
// I2CTCTL |= I2CSTT + I2CSTP; //Send another start
I2CTCTL |= I2CSTT + I2CSTP; //Send another start
while (I2CIFG & RXRDYIFG); // Wait for receiver to be ready
RXData = I2CDRB; //Transfer the data
*rdata = RXData;
// Now go back to count
U0CTL &= ~I2CEN; //Disable I2C to change modes
//Will go to SW control writes and read here
I2CTCTL &= ~I2CRM; //Set for SW Control
U0CTL &= I2CEN; //Renable I2C to change mode

_NOP(); //For breakpont
}

At this point any help would be appreciated. My alternative is to go
back to a set of routines I wrote for processors without the I2C
peripheral. Basically

Disable the I2C
Read with bit bang routines that work well
Go back to I2C

I would much rather use the peripheral.

I have avoided interrupts because the keeping track of who needs what
was becoming very complicated. In addition to the eeProm there is a
second master and up to 16 slave processors. The 16 don't have the
peripheral so I am going to have to write a slave routine anyway but I
need to get this part done first.

Thanks in advance for any help.

Regards,

Frank

Beginning Microcontrollers with the MSP430


The 2024 Embedded Online Conference