i2c pada LPC2368

setting awal register register I2C

void Setup_I2C0 (Int32U IrqSlot)
{
Int32U i;

//set PCLK=CCLK/4=12MHz for I2C0
PCLKSEL0_bit.PCLK_I2C0=0;

//bit7 of PCONP is already 1 after reset, but we set it anyway to enable I2C0
PCONP_bit.PCI2C0 = 1;

//switch P0.27=SDA0 (Bit23=0, Bit22=1) and
//       P0.28=SCL0 (Bit25=0, Bit24=1)to I2C functionality
PINSEL1 &=~((1<<22)|(1<<23)|(1<<24)|(1<<25));
PINSEL1 |= ((1<<22)|(1<<24));

//clear bits in I2C0CON register
I2C0CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;

/*— Reset registers —*/
//I2SCLL_SCLL=I2SCLH_SCLH=17 for 12MHz/34=352KHz
//I2SCLL_SCLL=I2SCLH_SCLH=26 for 18MHz/52=346KHz
#if (core_clk==48)
I2C0SCLL   = 17;//////////////////////////////I2SCLL_SCLL;
I2C0SCLH   = 17;//////////////!!!!!!!!!!!!!!!!!I2SCLH_SCLH;
#endif

#if (core_clk==72)
I2C0SCLL   = 26;//////////////////////////////I2SCLL_SCLL;
I2C0SCLH   = 26;//////////////!!!!!!!!!!!!!!!!!I2SCLH_SCLH;
#endif
//initialize I2CMasterState
I2CMasterState = I2C_IDLE;

/* Install interrupt handler with priority IrqSlot */
//  install_irq( I2C0_INT, (void *)I2C0MasterHandler, I2C0_IRQ_PRIORITY );
//enable I2C interrupt with lowest priority
//    VIC_SetVectoredIRQ(I2C0Isr,IrqSlot,VIC_I2C0);
//    VICINTENABLE |= 1<<VIC_I2C0;

for(i=0;i<20;i++) {
temporary[i]=0;
}

//enable I2C0
I2C0CONSET = I2CONSET_I2EN;
return;
}

START

Int32U I2CStart( void )
{
Int32U timeout = 0;
Int32U retVal = FALSE;
Int8U StatValue;

//Bit5(STA)=1 means I2C0 issues a START condition
I2C0CONSET = I2CONSET_STA;

//wait for the interrupt to state that START has been transmitted
while( 1 ) {

StatValue = I2C0STAT;
//if  START condition has been generated successfully
if (StatValue==0x08) {
//load the Slave address
I2C0DAT = I2CMasterBuffer[0];
WrIndex++;

//clear bits SIC (interrupt) and STAC (START bit) in I2C0CONSET
I2C0CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);

//I2CMasterState=1, showing the transmission has started
I2CMasterState = I2C_STARTED;
temporary[0]=temporary[0]+1;

//if an interrupt is generated with I2C0STAT=0x08, then exit function with
//return=TRUE
retVal = TRUE;
break;
}
else {
//if TIMEOUT>=0x00FFFFFF, then START has not been transmitted, then the
//transmission has to be stopped
if ( timeout >= MAX_TIMEOUT ) {
retVal = FALSE;
temporary[13]=temporary[13]+1;
break;
}
timeout++;
}
}
return( retVal );
}

STOP

Int32U I2CStop( void )
{

//bit STO is set to 1. Orders a STOP condition to be generated
I2C0CONSET = I2CONSET_STO;      /* Set Stop flag */

//clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;  /* Clear SI flag */

//When LPC2368 detects a STOP condition on the bus, bit STO in I2C0CONSET is
//cleared automatically. So we wait until STO becomes 0
while( I2C0CONSET & I2CONSET_STO );

return TRUE;
}

TRANSAKSI 1 FRAME DATA

Int32U I2CEngine( void ) {
Int8U StatValue;
Int32U retVal = FALSE;

I2CMasterState = I2C_IDLE;
RdIndex = 0;
WrIndex = 0;

//if a transmission never gets started (START condition cannot be generated),
//then stop the communication and return FALSE
if ( I2CStart() != TRUE ) {
I2CStop();
return ( FALSE );
}

//stay in this loop until I2CMasterState becomes COMM_FINISHED_OK or DATA_NACK
while (1) {

StatValue = I2C0STAT;
switch ( StatValue ) {
//a repeated START may only occur    during a Read operation, after the
//memory location address has been sent and a read command must start
case 0x10:            /* A repeated started is issued */

//maybe this if is useless and I should only set I2C0DAT=ADE78xx_addr|Bit0
if ( I2CCmd == (I2C_ADE78xx_addr | (1<<0)) ) {
I2C0DAT = I2C_ADE78xx_addr | (1<<0);
}

//clear bits SIC (interrupt) and STAC (START bit) in I2C0CONSET
I2C0CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);

//I2CMasterState=I2C_RESTARTED, showing that I2C sent the
//Repeated START and the slave address (with Bit0=1)
I2CMasterState = I2C_RESTARTED;
temporary[1]=temporary[1]+1;
break;

//if an ACK has been generated by the slave after the master had sent the
//slave address (the first byte in a write command)
case 0x18:            /* Regardless, it’s a ACK */
//if Slave Address has been transmitted and an ACK has been received, then
//send the bytes that are part of the operation. All this info is stored into
//I2CMasterBuffer beginning index=1
//I2CMasterBuffer[1]=MS byte of the memory address that is accessed
//I2CMasterBuffer[2]=LS byte of the memory address that is accessed
//In case of a write operation:
//I2CMasterBuffer[3]=MS byte of the data that will be written at the memory address
//etc
if ( I2CMasterState == I2C_STARTED ) {
I2C0DAT = I2CMasterBuffer[WrIndex];
WrIndex++;
temporary[8]=temporary[8]+1;
//I2CMasterState=DATA_ACK, showing ACK has been generated
I2CMasterState = DATA_ACK;
}
//clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;
temporary[2]=temporary[2]+1;
break;

//the master sent data and the slave acknowledged it
case 0x28:

//if still there are bytes to transmit, load the next
//byte from I2CMasterBuffer
if ( WrIndex != I2CWriteLength ) {
I2C0DAT = I2CMasterBuffer[WrIndex]; /* this should be the last one */
WrIndex++;
temporary[9]=temporary[9]+1;
//if still there are bytes to transmit, I2CMasterState=DATA_ACK
if ( WrIndex != (I2CWriteLength+1) ) {
I2CMasterState = DATA_ACK;
}

//if there are no more bytes to transmit (WrIndex=I2CWriteLength),
//set I2CMasterState = COMM_FINISHED_OK and begin an eventual read operation
else {

//if I2CReadLength!=0, then send a REPEATED START condition in order to
//start a read operation
if ( I2CReadLength != 0 ) {
temporary[11]=temporary[11]+1;

//send a REPEATED START condition by setting bit STA in I2C0CONSET
I2C0CONSET = I2CONSET_STA;

//set I2CMasterState = I2C_REPEATED_START
I2CMasterState = I2C_REPEATED_START;
}
else {
I2CMasterState = COMM_FINISHED_OK;
}

}
}

//if there are no more bytes to transmit:
else {
//if I2CReadLength!=0, then send a REPEATED START condition in order to
//start a read operation
if ( I2CReadLength != 0 ) {
temporary[10]=temporary[10]+1;

//send a REPEATED START condition by setting bit STA in I2C0CONSET
I2C0CONSET = I2CONSET_STA;

//set I2CMasterState = I2C_REPEATED_START
I2CMasterState = I2C_REPEATED_START;
}
//if there is no need to start a read operation, then
//set I2CMasterState = COMM_FINISHED_OK
else {
I2CMasterState = COMM_FINISHED_OK;
}
}
//clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;
temporary[3]=temporary[3]+1;
break;

//LPC2368 had sent the Slave address with Bit0=1 and the slave sent back ACK
//(as part of a read command in a read operation)
//There is no need to do anything here because the slave begins sending data
//that is to be read
case 0x40:    /* Master Receive, SLA_R has been sent */

//if we need to receive only one byte, then we do not need to generate an ACK
//at the end
if (I2CReadLength!=1) {

//generate an ACK to show the slave that the byte has been received
//I write bit 2 (AA) now, before a byte is received, to tell LPC2368 to
//generate the ACK after this byte is received. If I set bit 2(AA) after the
//byte is received, that is when I2C0STAT=0x50, the ACK is generated after
//the next byte is received.
I2C0CONSET = I2CONSET_AA;    /* assert ACK after data is received */
}

//clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;
temporary[4]=temporary[4]+1;
break;

//the slave begins sending data and the master must acknowledge it and then
//store it into I2CMasterBuffer beginning index=3
case 0x50:
case 0x58:

//store received bytes into I2CMasterBuffer
I2CMasterBuffer[3+RdIndex] = I2C0DAT;
RdIndex++;

//if we still have to receive bytes, keep I2CMasterState=DATA_ACK (set at case 0x40)
//else, set I2CMasterState = COMM_FINISHED_OK and clear RdIndex to 0
if ( RdIndex < I2CReadLength ) {

I2CMasterState = DATA_ACK;

//if the next byte that will be received is the last one, then we
//do not need to generate an ACK
if (RdIndex==(I2CReadLength-1)) {
//clear the ACK bit, so no ACKs will be generated in the future
I2C0CONCLR = I2CONCLR_AAC;
}

}
else  {
RdIndex = 0;
I2CMasterState = COMM_FINISHED_OK;
}

//clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;
temporary[5]=temporary[5]+1;
break;

//both 0x20, 0x30 and 0x48 represent NACK conditions that may appear after
//slave address or other bytes have been sent. In this case, the
//communication has to be restarted from scratch
case 0x20:        /* regardless, it’s a NACK */
case 0x30:
case 0x48:

//if a NACK event occured, then clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;

//set I2CMasterState = DATA_NACK
I2CMasterState = DATA_NACK;
temporary[6]=temporary[6]+1;
break;

//in the LPC2368-ADE78xx communication, there are no other master devices,
//so this error cannot occur
case 0x38:        /* Arbitration lost, in this example, we don’t
deal with multiple master situation */

//clear interrupt status bit SIC in I2C0CONCLR
I2C0CONCLR = I2CONCLR_SIC;
temporary[12]=temporary[12]+1;
//set I2CMasterState = DATA_NACK
I2CMasterState = DATA_NACK;
break;

//if I2C0STAT does not have one of the values above, then execute default
default:
//clear interrupt status bit SIC in I2C0CONCLR
//        I2C0CONCLR = I2CONCLR_SIC;

//set I2CMasterState = DATA_NACK
//        I2CMasterState = DATA_NACK;
//temporary[7]=temporary[7]+1;
break;
}

//jika ada NACK, STOP, 1 Frame komplit
if (I2CMasterState==DATA_NACK) {
I2CStop();
retVal = FALSE;
break;
}
//jika OK, STOP
if (I2CMasterState==COMM_FINISHED_OK) {
I2CStop();
retVal = TRUE;
break;
}

}

return (retVal);
}

Advertisements

~ by den-wam on December 18, 2016.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: