Hi,
I am using the am3359 to communicate with TCA9539 I/O expander by I2C 1. When I send the slave address, then the process stop at this byte every time. No matter what I change the slave address that is no use. So I get the wavefrom form LA that slave is non ack every time. Then I check the things as follow,
(1) VCC in 3.3V, that is correct.
(2) I2C_SDA/ I2C_SCL is connected.
(3) I2C_SDA/ I2C_SCL waveform is correct, just no ack receive
(4) Slave addres is 7-bit address mode
(5) The ISR only enter 2 times
I am afraid that problem is firmware, so have any one advance the issue. Here's my code...
----------------------------------------------------------------------------------------------------------------------------
volatile unsigned int tCount;
volatile unsigned int rCount;
volatile unsigned int flag = 1;
volatile unsigned int numOfBytes;
volatile unsigned char dataToSlave[4];
volatile unsigned char dataFromSlave[50];
int main(void)
{
/* Enable IRQ in CPSR */
IntMasterIRQEnable();
/* Configures AINTC to generate interrupt */
I2CAINTCConfigure();
/* Configures I2C to Master mode and speed of 400khz */
SetupI2C();
dataToSlave[0] = 0x02;
dataToSlave[1] = 0xFF;
dataToSlave[2] = 0xFF;
tCount = 0;
rCount = 0;
// Data Count specifies the number of bytes to be transmitted
I2CSetDataCount(SOC_I2C_1_REGS, 3);
numOfBytes = I2CDataCountGet(SOC_I2C_1_REGS);
// Clear status of all interrupts
CleanUpInterrupts();
// Configure I2C controller in Master Transmitter mode
I2CMasterControl(SOC_I2C_1_REGS, I2C_CFG_MST_TX);
// Transmit interrupt is enabled
I2CMasterIntEnableEx(SOC_I2C_1_REGS, I2C_INT_TRANSMIT_READY|I2C_INT_ADRR_READY_ACESS);
// Generate Start Condition over I2C bus
I2CMasterStart(SOC_I2C_1_REGS);
while(I2CMasterBusBusy(SOC_I2C_1_REGS) == 0); // issue: always stop at this line******
while(tCount != numOfBytes);
flag = 1;
// Wait until I2C registers are ready to access
while(!(I2CMasterIntRawStatus(SOC_I2C_1_REGS) & (I2C_INT_ADRR_READY_ACESS)));
// Data Count specifies the number of bytes to be received
I2CSetDataCount(SOC_I2C_1_REGS, 1);
numOfBytes = I2CDataCountGet(SOC_I2C_1_REGS);
// Clear status of all interrupts
CleanUpInterrupts();
// Configure I2C controller in Master Receiver mode
I2CMasterControl(SOC_I2C_1_REGS, I2C_CFG_MST_RX);
// Receive and Stop Condition Interrupts are enabled
I2CMasterIntEnableEx(SOC_I2C_1_REGS, I2C_INT_RECV_READY |I2C_INT_STOP_CONDITION);
// Generate Start Condition over I2C bus
I2CMasterStart(SOC_I2C_1_REGS);
while(I2CMasterBusBusy(SOC_I2C_1_REGS) == 0);
while(flag);
flag = 1;
}
/* Clear status of all interrupts */
void CleanUpInterrupts(void)
{
I2CMasterIntEnableEx(SOC_I2C_1_REGS, 0x7FF);
I2CMasterIntClearEx(SOC_I2C_1_REGS, 0x7FF);
I2CMasterIntDisableEx(SOC_I2C_1_REGS, 0x7FF);
}
/* I2C Interrupt Service Routine */
void I2CIsr(void)
{
unsigned int status = 0;
/* Get only Enabled interrupt status */
status = I2CMasterIntStatus(SOC_I2C_1_REGS);
/* Clear interrupt status except receive ready and transmit ready interrupt status */
I2CMasterIntClearEx(SOC_I2C_1_REGS,(status & ~(I2C_INT_RECV_READY | I2C_INT_TRANSMIT_READY)));
if(status & I2C_INT_RECV_READY)
{
/* Receive data from data receive register */
dataFromSlave[rCount++] = I2CMasterDataGet(SOC_I2C_1_REGS);
/* Clear receive ready interrupt status */
I2CMasterIntClearEx(SOC_I2C_1_REGS, I2C_INT_RECV_READY);
if(rCount == numOfBytes)
{
/* Disable the receive ready interrupt */
I2CMasterIntDisableEx(SOC_I2C_1_REGS, I2C_INT_RECV_READY);
/* Generate a STOP */
I2CMasterStop(SOC_I2C_1_REGS);
}
}
if (status & I2C_INT_TRANSMIT_READY)
{
/* Put data to data transmit register of i2c */
I2CMasterDataPut(SOC_I2C_1_REGS, dataToSlave[tCount++]);
/* Clear Transmit interrupt status */
I2CMasterIntClearEx(SOC_I2C_1_REGS, I2C_INT_TRANSMIT_READY);
if(tCount == numOfBytes)
{
/* Disable the transmit ready interrupt */
I2CMasterIntDisableEx(SOC_I2C_1_REGS, I2C_INT_TRANSMIT_READY);
}
}
if (status & I2C_INT_STOP_CONDITION)
{
/* Disable transmit data ready and receive data read interupt */
I2CMasterIntDisableEx(SOC_I2C_1_REGS, I2C_INT_TRANSMIT_READY |
I2C_INT_RECV_READY |
I2C_INT_STOP_CONDITION);
flag = 0;
}
if(status & I2C_INT_NO_ACK)
{
I2CMasterIntDisableEx(SOC_I2C_1_REGS, I2C_INT_TRANSMIT_READY |
I2C_INT_RECV_READY |
I2C_INT_NO_ACK |
I2C_INT_STOP_CONDITION);
// Generate a STOP
I2CMasterStop(SOC_I2C_1_REGS);
printf("Data no ack\n");
flag = 0;
}
}
static void SetupI2C(void)
{
/* Enable the clock for I2C1 */
I2C1ModuleClkConfig();
I2CPinMux1Setup();
/* Put i2c in reset/disabled state */
I2CMasterDisable(SOC_I2C_1_REGS);
/* Disable auto Idle functionality */
I2CAutoIdleDisable(SOC_I2C_1_REGS);
/* Configure i2c bus speed to 400khz */
I2CMasterInitExpClk(SOC_I2C_1_REGS, 48000000, 12000000, 400000);
/* Set i2c slave address */
I2CMasterSlaveAddrSet(SOC_I2C_1_REGS, 0x74);
/* Bring I2C out of reset */
I2CMasterEnable(SOC_I2C_1_REGS);
}
/* Configures AINTC to generate interrupt */
void I2CAINTCConfigure(void)
{
/* Intialize the ARM Interrupt Controller(AINTC) */
IntAINTCInit();
/* Registering the Interrupt Service Routine(ISR). */
IntRegister(SYS_INT_I2C1INT, I2CIsr);
/* Setting the priority for the system interrupt in AINTC. */
IntPrioritySet(SYS_INT_I2C1INT, 0, AINTC_HOSTINT_ROUTE_IRQ );
/* Enabling the system interrupt in AINTC. */
IntSystemEnable(SYS_INT_I2C1INT);
}
/* Configures I2C1 pin mux */
void I2CPinMux1Setup(void)
{
HWREG(SOC_CONTROL_REGS + CONTROL_CONF_SPI0_D1) =
(CONTROL_CONF_SPI0_D1_CONF_SPI0_D1_PUTYPESEL |
CONTROL_CONF_SPI0_D1_CONF_SPI0_D1_RXACTIVE |
CONTROL_CONF_SPI0_D1_CONF_SPI0_D1_SLEWCTRL |
CONTROL_CONF_MUXMODE(2));
HWREG(SOC_CONTROL_REGS + CONTROL_CONF_SPI0_CS0) =
(CONTROL_CONF_SPI0_CS0_CONF_SPI0_CS0_PUTYPESEL |
CONTROL_CONF_SPI0_CS0_CONF_SPI0_CS0_RXACTIVE |
CONTROL_CONF_SPI0_D1_CONF_SPI0_D1_SLEWCTRL |
CONTROL_CONF_MUXMODE(2));
}
----------------------------------------------------------------------------------------------------------------------------
So, have any idea?