📄 i2c.c
字号:
I2CCmd = I2C_WRITE_READ;
I2CEngine();
/* De-Initialize I2C1 controller */
I2C1_DeInit();
} // I2C1_Master_Demo
/*****************************************************************************
** Function name: I2C1_Init
** Description: Initialize I2C1 controller
** Parameters: I2c mode is either MASTER or SLAVE
** Returned value: true or false, return false if the I2C
** interrupt handler was not installed correctly
*****************************************************************************/
DWORD I2C1_Init( DWORD I2cMode )
{
BYTE i;
PINSEL1 |= 0x00000014; // Set P0.17 as SCL1 and P0.18 as SDA1
IODIR = 0x00060000; // Set P0.17 and P0.18 ports to output, high
IOSET = 0x00060000;
/*--- Clear flags ---*/
I21CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
/*--- Reset registers ---*/
I21SCLL = I2SCLL_SCLL;
I21SCLH = I2SCLH_SCLH;
if(I2cMode == I2CSLAVE)
{
I21ADR = I2CSL_ADDRS << 1;
}
/* Install interrupt handler */
if(install_irq( I2C1_INT, (void *)I2C1_MasterHandler ) == FALSE)
{
return( FALSE );
}
/* Enable I2C controller for Master or Slave functions */
if(I2cMode == I2CMASTER)
{
I21CONSET = I2CONSET_I2EN;
}
else
{
I21CONSET = I2CONSET_I2EN | I2CONSET_AA;
}
for(i=0; i<BUFSIZE; i++) /* clear buffer */
{
I2C1MasterBuffer[i] = 0;
}
return( TRUE );
} // I2C1_Init
/*****************************************************************************
** Function name: I2C1_DeInit
** Description: De-Initialize I2C1 controller
** Parameters: None
** Returned value: true or false, return false when the interrupt number is
** not found
*****************************************************************************/
DWORD I2C1_DeInit(void)
{
PINSEL1 &= ~0x00000014; // Set P0.17 as SCL1 and P0.18 as SDA1
IODIR &= ~0x00060000; // Set P0.17 and P0.18 ports to input
/* Install interrupt handler */
if(uninstall_irq(I2C1_INT) == FALSE)
{
return( FALSE );
}
VICIntEnClr = 1 << I2C1_INT;
return (TRUE);
} // I2C1_DeInit
/*****************************************************************************
** Function name: I2C1_MasterHandler
** Description: I2C1 interrupt handler, deal with MASTER mode only.
** Parameter: None
** Returned value: None
*****************************************************************************/
void I2C1_MasterHandler (void) __irq
{
BYTE StatValue;
/* Reads the I2C status to branch to one of the I2C state routines */
StatValue = I21STAT;
IENABLE;
I21CONCLR = I2CONCLR_AAC | I2CONCLR_STAC; // Clear STA and AA flags
/* Handles I2C state routines */
switch(StatValue)
{
case 0x08: /* A Start condition is issued. */
I21DAT = I2C1MasterBuffer[0];
I21CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
I2C1MasterState = I2C_STARTED;
break;
case 0x10: /* A repeated start is issued */
if(I2CCmd == I2C_WRITE_READ)
{
I21DAT = I2C1MasterBuffer[1+WrIndex];
WrIndex++;
}
else if(I2CCmd == I2C_READ_WRITE)
{
I21DAT = I2C1MasterBuffer[1+RdIndex];
RdIndex++;
}
I21CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
I2C1MasterState = I2C_RESTARTED;
break;
case 0x18: /* Regardless, it's a ACK */
if(I2C1MasterState == I2C_STARTED)
{
I21DAT = I2C1MasterBuffer[1+WrIndex];
WrIndex++;
I2C1MasterState = DATA_ACK;
}
if(I2CCmd == I2C_READ_WRITE)
{
I21DAT = I2C1MasterBuffer[1+RdIndex];
RdIndex++;
I2C1MasterState = DATA_ACK;
}
I21CONCLR = I2CONCLR_SIC;
break;
case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
case 0x30:
if(WrIndex < I2C1WriteLength)
{
I21DAT = I2C1MasterBuffer[1+WrIndex]; /* This should be the last one */
if(WrIndex < I2C1WriteLength)
{
I2C1MasterState = DATA_ACK;
}
else
{
I2C1MasterState = DATA_NACK;
if(I2C1ReadLength > 0)
{
I21CONSET = I2CONSET_STA; /* Set Repeated-start flag */
I2C1MasterState = I2C_REPEATED_START;
}
}
WrIndex++;
}
else
{
if(I2C1ReadLength > 0)
{
I21CONSET = I2CONSET_STA; /* Set Repeated-start flag */
I2C1MasterState = I2C_REPEATED_START;
}
else
{
I2C1MasterState = DATA_NACK;
}
}
I21CONCLR = I2CONCLR_SIC;
break;
case 0x40: /* Master Receive, SLA_R has been sent */
RdIndex++;
I21CONSET = I2CONSET_AA;
I21CONCLR = I2CONCLR_SIC;
break;
case 0x50: /* Data byte has been received, regardless following ACK or NACK */
I2C1MasterBuffer[1+RdIndex] = I21DAT;
RdIndex++;
if(RdIndex < I2C1ReadLength)
{
I21CONSET = I2CONSET_AA; /* assert ACK after data is received */
I2C1MasterState = DATA_ACK;
}
else
{
RdIndex = 0;
I21CONCLR = I2CONCLR_AAC;
I2C1MasterState = DATA_ACK;
}
I21CONCLR = I2CONCLR_SIC;
break;
case 0x58:
I2C1MasterState = DATA_NACK;
I21CONCLR = I2CONCLR_SIC;
break;
case 0x20: /* Regardless, it's a NACK */
case 0x48:
I21CONSET = I2CONSET_AA;
I21CONCLR = I2CONCLR_SIC;
I2C1MasterState = DATA_NACK;
break;
case 0x38: /* Arbitration lost, in this example, we don't
deal with multiple master situation */
default:
I21CONSET = I2CONSET_AA;
I21CONCLR = I2CONCLR_SIC;
break;
}
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
} // I2C1_MasterHandler
/*****************************************************************************
** Function name: I2CStart
** Descriptions: Create I2C start condition, a timeout value is set if the
** I2C never gets started, and timed out. It's a fatal error.
** Parameters: None
** Returned value: true or false, return false if timed out
*****************************************************************************/
DWORD I2CStart(void)
{
DWORD timeout = 0;
DWORD returnValue = FALSE;
/*--- Issue a start condition ---*/
I21CONSET = I2CONSET_STA; /* Set Start flag */
/*--- Wait until START transmitted ---*/
while(1)
{
if(I2C1MasterState == I2C_STARTED)
{
returnValue = TRUE;
break;
}
if(timeout >= MAX_TIMEOUT)
{
returnValue = FALSE;
break;
}
timeout++;
}
return(returnValue);
} // I2CStart
/*****************************************************************************
** Function name: I2CStop
** Descriptions: Set the I2C stop condition, if the routine never exit,
** it's a fatal bus error.
** Parameters: None
** Returned value: true or never return
*****************************************************************************/
DWORD I2CStop( void )
{
I21CONSET = I2CONSET_STO; /* Set Stop flag */
I21CONCLR = I2CONCLR_SIC; /* Clear SI flag */
/*--- Wait for STOP detected ---*/
while(I21CONSET & I2CONSET_STO);
return TRUE;
} // I2CStop
/*****************************************************************************
** Function name: I2CEngine
** Descriptions: The routine to complete a I2C transaction from start to stop.
** All the intermitten steps are handled in the interrupt
** handler. Before this routine is called, the read length,
** write length, I2C master buffer, and I2C command fields
** need to be filled.
** Parameters: None
** Returned value: true or false, return false only if the start condition
** can never be generated and timed out.
*****************************************************************************/
DWORD I2CEngine( void )
{
I2C1MasterState = I2C_IDLE;
RdIndex = 0;
WrIndex = 0;
if(I2CStart() != TRUE)
{
I2CStop();
return(FALSE);
}
while(1)
{
if(I2C1MasterState == DATA_NACK)
{
I2CStop();
break;
}
}
return (TRUE);
} // I2CEngine
#endif
/******************************************************************************
** End Of File
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -