Hello,
I want to write some data out the I2C port and I'm really close. I am looking at the signals on a scope to verify what's going on, and I see that it works fine for the first transfer (a total of 3 bytes). I see the start, address, and two bytes of data (all acknowledged), followed by a stop. I'm generating a chip select on a GPIO line and I see it assert and de-assert at the right time as well so it's just about perfect.
The big problem is that nothing happens after that. Same routine, but no clock, no data, nothing. I've even tried to reset the I2C module between calls to the routine, but still nothing. So I'm guessing I'm missing some sort of reset or status clearing but I haven't been able to figure out what it is.
I'm not using interrupts because I have other interrupts that I don't want to interfere with. I am using the transmit FIFO.
Here's the routine that writes the data:
void i2ca_xmit( Uint16 devAddr, Uint16 regAddr, Uint16 data)
{
Uint16 timeout;
// Setup the slave (device) address
I2caRegs.I2CSAR = devAddr;
// Always send two bytes: register address + data.
I2caRegs.I2CCNT = 2;
// Assert the select line so the receiver will listen.
GpioDataRegs.GPCDAT.bit.GPIO87 = 0;
DELAY_US(10);
// Write the data to the transmit FIFO.
I2caRegs.I2CDXR = regAddr;
I2caRegs.I2CDXR = data;
// Generate a START condition to send out the data.
I2caRegs.I2CMDR.bit.STT = 1;
// This will give the bus a chance to start.
DELAY_US(10);
// We're going to wait for a stop, so clear the status bit.
I2caRegs.I2CSTR.bit.SCD = 1;
// Wait until the stop condition is detected.
timeout = 350;
while((I2caRegs.I2CSTR.bit.SCD == 0) && (timeout > 0))
{
DELAY_US(1);
--timeout;
}
// Turn off the select line.
DELAY_US(10);
GpioDataRegs.GPCDAT.bit.GPIO87 = 1;
// Make sure the I2C bus is stopped.
I2caRegs.I2CMDR.bit.STT = 0;
}
Here's the init routine:
void
i2ca_init()
{
I2caRegs.I2CSTR.all = 0xff; // Reset all status bits.
I2caRegs.I2CMDR.all = 0; // Reset the I2C module.
I2caRegs.I2CIER.all = 0; // Disable all interrupts.
// Enable the clock for the I2C module.
EALLOW;
SysCtrlRegs.PCLKCR0.bit.I2CAENCLK = 1;
EDIS;
//==================================================
// Initialize the I/O pins for I2C bus.
// GPIO32: SDA
// GPIO33: SCL
// GPIO87: SEL*
//==================================================
EALLOW;
// GPIO32: SDA. Enable pullup, no synchronizing the input, use I2C.
GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0; // Enable pull-up for GPIO32 (SDAA)
GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3; // Asynch input GPIO32 (SDAA)
GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1; // Configure GPIO32 for SDAA
// GPIO33: SCL. Enable pullup, no synchronizing the input, use I2C.
GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0; // Enable pull-up for GPIO33 (SCLA)
GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3; // Asynch input GPIO33 (SCLA)
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1; // Configure GPIO33 for SCLA
// GPIO87: SEL*. Make it an output, drive it high (not selected).
GpioCtrlRegs.GPCDIR.bit.GPIO87 = 1;
GpioDataRegs.GPCDAT.bit.GPIO87 = 1;
EDIS;
// Divide the 150 MHz DSP clock down for the I2C module clock.
// The module clock must be between 7-12 MHz.
// Dividing by 15 gives a 10 MHz clock.
I2caRegs.I2CPSC.all = 14;
// Create a 50% duty cycle clock for SCL from the 10 MHz module clock.
// The actual divider is 5 more than what is programmed into the register.
// Value = 20: 10 MHz / (2*25) = 200KHz or 5 uSec per bit.
I2caRegs.I2CCLKL = 20;
I2caRegs.I2CCLKH = 20;
I2caRegs.I2CSAR = 0x69; // Slave address.
I2caRegs.I2COAR = 0x05; // Own address.
// Let the I2C run when the DSP is halted with the debugger.
I2caRegs.I2CMDR.bit.FREE = 1;
// Master transmitter, 8 bits per byte.
I2caRegs.I2CMDR.bit.MST = 1;
I2caRegs.I2CMDR.bit.TRX = 1;
// Release reset for I2C module.
I2caRegs.I2CMDR.bit.IRS = 1;
// This will wait for a bit to allow the bus busy bit to update.
DELAY_US(50);
// Always generate a stop condition after each data transfer.
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CFFTX.all = 0; // Reset/Disable the TXFIFO.
I2caRegs.I2CFFTX.all = 0x6002; // Enable FIFO mode and TXFIFO
}