Wednesday, March 30, 2011

LPC2368_I2C_Interface



/****************************************************/
/* Examples Program For "CP-JR ARM7 LPC2368" */
/* Target MCU : Philips ARM7-LPC2368 */
/* : X-TAL : 12.00 MHz */
/* : PLL Setup = MSEL(12),NSEL(1) */
/* : CCLK = 4, USB = 2, PLCK0,1 = cclk/4*/
/* : SYSTEMcclk = 72MHz, USB = 36MHz */
/* : PLCK = 18MHz */
/* Keil Editor : uVision4 V4.14 */
/* Compiler : Keil Realview MDK V3.20 */
/* Create By : MAN */
/* Last Update : 30/March/2011 */
/* Function : Example Use I2C0 Interface 24LCxx */
/* : EEPROM in Master Mode */
/****************************************************/
/***** Header File *****/
#include < LPC23xx.H > // Header File LPC2368
#include < stdio.h > // Use sprintf



/***** Define Directive *****/
/////////////////// Address 24LCxx /////////////////////////////
#define I2C_SLA 0xA0 // Address Slave 24LC128
#define wait_write delay_ms(6) // >5 ms max write-cycle time

////////////////////// Standard I2C STATUS //////////////////////////////
/***** Master Mode *****/
/* A START condition has been transmitted */
#define I2C_START 0x08
/* A repeated START condition has been transmitted */
#define I2C_REP_START 0x10

/* Master Transmitter */
/* SLA+W has been transmitted; ACK has been received */
#define I2C_MT_SLA_ACK 0x18
/* SLA+W has been transmitted; NOT ACK has been received */
#define I2C_MT_SLA_NACK 0x20
/* Data byte in I2DAT has been transmitted; ACK has been received */
#define I2C_MT_DATA_ACK 0x28
/* Data byte in I2DAT has been transmitted; NOT ACK has been received */
#define I2C_MT_DATA_NACK 0x30
/*Arbitration lost in SLA+R/W or Data bytes */
#define I2C_MT_ARB_LOST 0x38

/* Master Receiver */
/* Arbitration lost in NOT ACK bit */
#define I2C_MR_ARB_LOST 0x38
/* SLA+R has been transmitted; ACK has been received */
#define I2C_MR_SLA_ACK 0x40
/* SLA+R has been transmitted; NOT ACK has been received */
#define I2C_MR_SLA_NACK 0x48
/* Data byte has been received; ACK has been returned */
#define I2C_MR_DATA_ACK 0x50
/*Data byte has been received; NOT ACK has been returned */
#define I2C_MR_DATA_NACK 0x58

/* Slave Transmitter */
/* Own SLA+R has been received; ACK has been returned */
#define I2C_ST_SLA_ACK 0xA8
/* Arbitration lost in SLA+R/W as master; Own SLA+R has been received, ACK has been returned */
#define I2C_ST_ARB_LOST_SLA_ACK 0xB0
/* Data byte in I2DAT has been transmitted; ACK has been received */
#define I2C_ST_DATA_ACK 0xB8
/*Data byte in I2DAT has been transmitted; NOT ACK has been received*/
#define I2C_ST_DATA_NACK 0xC0
/*Last data byte in I2DAT has been transmitted (AA = 0); ACK has been received*/
#define I2C_ST_LAST_DATA 0xC8

/* Slave Receiver */
/* Own SLA+W has been received; ACK has been returned */
#define I2C_SR_SLA_ACK 0x60
/* Arbitration lost in SLA+R/W as master; Own SLA+W has been received, ACK returned.*/
#define I2C_SR_ARB_LOST_SLA_ACK 0x68
/* General call address (0x00) has been received; ACK has been returned */
#define I2C_SR_GCALL_ACK 0x70
/* Arbitration lost in SLA+R/W as master; General call address has been received, ACK has been returned */
#define I2C_SR_ARB_LOST_GCALL_ACK 0x78
/* Previously addressed with own SLV address; DATA has been received; ACK has been returned */
#define I2C_SR_DATA_ACK 0x80
/* Previously addressed with own SLA; DATA byte has been received; NOT ACK has been returned.*/
#define I2C_SR_DATA_NACK 0x88
/* Previously addressed with General Call; DATA byte has been received; ACK has been returned */
#define I2C_SR_GCALL_DATA_ACK 0x90
/* Previously addressed with General Call; DATA byte has been received; NOT ACK has been returned */
#define I2C_SR_GCALL_DATA_NACK 0x98
/* A STOP condition or repeated START condition has been received while still addressed as SLV/REC or SLV/TRX. */
#define I2C_SR_STOP 0xA0

/* Miscellaneous States */
/* no relevant information is available */
#define I2C_NO_INFO 0xF8
/* a bus error has occurred during an I2C serial transfer */
#define I2C_BUS_ERROR 0x00

/* I2C_READ SLA+R address */
#define I2C_READ 1
/* I2C_WRITE SLA+W address */
#define I2C_WRITE 0
////////////////////////////////////////////////////////////////

/***** Global Variable *****/
// UART Buffer
char uart2_buf[]; // "sprint" UART[2] Buffer

/***** Prototype Function *****/
// Initil UART-2
void init_serial2 (void);
// Put and Get UART-2
void putchar2(int ch); // Put Char To UART-2
int getchar2(void); // Get Char From UART-2
void print_uart2(void); // Print String to UART2
// Delay Time
void delay_ms(unsigned long ms);

/////////////////// I2C Function ////////////////////////////
void Initial_I2C(void);
unsigned char I2C_Start(void);
void I2C_Stop(void);
unsigned char I2C_Write_send(unsigned char SLA_RW,unsigned char add_H,unsigned char add_L,unsigned char Data);
unsigned char I2C_Write_receive(unsigned char SLA_RW,unsigned char add_H,unsigned char add_L);
unsigned char I2C_Write_receive_DATA(unsigned char SLA_RW);

/////////////////// I2C EEPROM 24FC128 //////////////////////
unsigned char EEPROM_Read(unsigned int adr);
void EEPROM_Write(unsigned int adr,unsigned char dat);

/***** Sub Function *****/
/********************************/
/* Initial UART2 = 115200,N,8,1 */
/********************************/
void init_serial2 (void)
{
// xxxx xxxx 0101 xxxx xxxx xxxx xxxx xxxx
PINSEL0 &= 0xFF0FFFFF; // Reset P0.10,P0.11 Pin Config
PINSEL0 |= 0x00100000; // Select P0.10 = TxD(UART2)
PINSEL0 |= 0x00400000; // Select P0.11 = RxD(UART2)

// xxxx xxx1 xxxx xxxx xxxx xxxx xxxx xxxx
PCONP |= 0x01000000; // UART2 Power-ON

U2LCR = 0x83; // 8 bits, no Parity, 1 Stop bit
//U2DLM = DLL_Config >> 8;
U2DLL = 6; //DLL_Config // // Baud 115200BPS 18MHz PCLK Clock
U2FDR = 0x85; // Fractional Divider
U2LCR = 0x03; // DLAB = 0
}
/******************************/
/* Write Character To UART[2] */
/******************************/
void putchar2 (int ch)
{
if (ch == '\n')
{
while (!(U2LSR & 0x20)); // Wait TXD Buffer Empty
U2THR = 0x0D; // Write CR
}

while (!(U2LSR & 0x20)); // Wait TXD Buffer Empty
U2THR = ch;
}
/******************************/
/* Get character From UART[2] */
/******************************/
int getchar2()
{
while (!(U2LSR & 0x01)); // Wait RXD Receive Data Ready
return (U2RBR); // Get Receice Data & Return
}
/***************************/
/* Print String to UART[2] */
/***************************/
void print_uart2(void)
{
char *p; // Pointer Buffer
p = uart2_buf; // UART Buffer

do // Get char & Print Until null
{
putchar2(*p); // Write char to UART
p++; // Next char
}
while(*p != '\0'); // End of ASCII (null)

return;
}
/////////////////// Initial_I2C ////////////////////////////////////////
void Initial_I2C(void)
{
// I2C0 Power-ON
PCONP |= 0x00000080;

// Pin Selection
PINSEL1 &= 0xFC3FFFFF; // Clear P0[27 SDA0,28 SCL0]
PINSEL1 |= 0x01400000; // Select P0.27 SDA0 = 01, P0.28 SCL0 = 01

// Initial I2C Data Rate = PCLK/(I2C0SCLL + I2C0SCLH) = 1MHz or 400kHz
// 4.5MHz/(6 + 6) = 375kHz
I20SCLH = 6; // Clock High
I20SCLL = 6; // Clock Low
}

/***************************************************************** I2C Start */
unsigned char I2C_Start(void)
{
unsigned char status;

I20CONCLR = 0x6C; // Reset all I2C Status
I20CONSET |= 0x40; // Enable I2C Interface
I20CONSET |= 0x20; // Send Start Condition

// Wait Start Condition Complete
while((I20STAT)!= I2C_START)
{
// Wait Repeated Start Condition Complete
if ((I20STAT) == I2C_REP_START) return status;
}
return status; // return status
}

/****************************************************************** I2C Stop */
void I2C_Stop(void)
{
I20CONSET |= 0x10; // Send Stop Condition
I20CONCLR = 0x0C; // Clear Acknowledge Bit + Interrupt Flag
}
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////// EEPROM_Read /////////////////////////////////
unsigned char EEPROM_Read(unsigned int adr)
{
unsigned char dat;
// Start condition
I2C_Start();
// I2C Send SLA + Write Mode, Address High Byte, Address Low Byte
I2C_Write_receive(I2C_SLA+I2C_WRITE,adr>>8,adr);
// ReStart condition for 24LCxx)
I2C_Start();
// I2C Send SLA + Read Mode and Receive Data at adr
dat = I2C_Write_receive_DATA(I2C_SLA+I2C_READ);
// Stop condition
I2C_Stop();

return (dat);

}

////////////////////////////// EEPROM_Write //////////////////////////////////
void EEPROM_Write(unsigned int adr,unsigned char dat)
{
// Start condition
I2C_Start();
// I2C Send SLA + Write Mode, Address High Byte, Address Low Byte
I2C_Write_send(I2C_SLA+I2C_WRITE,adr>>8,adr,dat);
// Stop condition
I2C_Stop();
}
//////////////////////////// I2C Write send ///////////////////////////////////////
unsigned char I2C_Write_send(unsigned char SLA_RW,unsigned char add_H,unsigned char add_L,unsigned char Data)
{
I20DAT = SLA_RW; // Load SLA+[Read/Write]
I20CONCLR = 0x28; // Clear Start Bit and Interrupt
while((I20STAT) != I2C_MT_SLA_ACK); // Send SLA+W Complete

I20DAT = add_H; // Load Data
I20CONCLR = 0x0C; // Clear ACK Bit + Interrupt Flag
while((I20STAT) != I2C_MT_DATA_ACK); // Send DATA(Address High Byte)Complete

I20DAT = add_L; // Load Data
I20CONCLR = 0x0C; // Clear ACK Bit + Interrupt Flag
while((I20STAT) != I2C_MT_DATA_ACK); // Send DATA(Address Low Byte)Complete

I20DAT = Data; // Load Data
I20CONCLR = 0x0C; // Clear ACK Bit + Interrupt Flag
while((I20STAT) != I2C_MT_DATA_ACK); // Send DATA Complete

return 0; // Return Status
}
//////////////////////////// I2C Write befor receive ///////////////////////////////////////
unsigned char I2C_Write_receive(unsigned char SLA_RW,unsigned char add_H,unsigned char add_L)
{
I20DAT = SLA_RW; // Load SLA+[Read/Write]
I20CONCLR = 0x28; // Clear Start Bit and Interrupt
while((I20STAT) != I2C_MT_SLA_ACK); // Send SLA+W Complete

I20DAT = add_H; // Load Data
I20CONCLR = 0x0C; // Clear ACK Bit + Interrupt Flag
while((I20STAT) != I2C_MT_DATA_ACK); // Send DATA(Address High Byte)Complete

I20DAT = add_L; // Load Data
I20CONCLR = 0x0C; // Clear ACK Bit + Interrupt Flag
while((I20STAT) != I2C_MT_DATA_ACK); // Send DATA(Address Low Byte)Complete

return 0; // Return Status
}
//////////////////////////// I2C Write befor receive Data ///////////////////////////////////
unsigned char I2C_Write_receive_DATA(unsigned char SLA_RW)
{
I20DAT = SLA_RW; // Load SLA+[Read/Write]
I20CONCLR = 0x28; // Clear Start Bit and Interrupt
while((I20STAT) != I2C_MR_SLA_ACK); // Send SLA+Read Complete

I20CONCLR = 0x0C; // Clear ACK Bit + Interrupt Flag
while((I20STAT) != I2C_MR_DATA_NACK); //***** Get DATA Complete *****//

return(I20DAT); // Return DATA
}

// Delay Time Function
void delay_ms(unsigned long ms)
{
unsigned long i,j;
for(i=0;i for(j=0;j<5525;j++);
}
/////////////////////////// MAIN FUNCTION //////////////////////////
int main (void)
{
unsigned int ee_adr;
unsigned char dat=1;

// PIN SELECTION and Initial UART2
init_serial2();

// PIN SELECTION and Initial I2C Channal 0
Initial_I2C();

sprintf(uart2_buf,"\f24LCxx Serial EEPROM Write/Read");
print_uart2();

for (ee_adr=0x0000; ee_adr<=0x000F; ee_adr++)
{
// Write data
EEPROM_Write(ee_adr,dat++);
// Wait for write-cycle time
wait_write;
}

sprintf(uart2_buf,"\nWrite EEPROM Complete...");
print_uart2();

for (ee_adr=0x0000; ee_adr<=0x000F; ee_adr++)
{
sprintf( uart2_buf,"\nRead EEPROM @%X data: %d",ee_adr, EEPROM_Read(ee_adr) );
print_uart2();
}

//while loop
while(1)
{

}

}
/**********************************/
/******* Interupt Routine *********/
/**********************************/

2 comments:

  1. เป็นตัวอย่างการทดลองเขียน I2C0(Master Mode) ของ LPC2368 ติดต่อกับ ไอซี EEPROM 24LC128 ครับ โดยทำการเขียนข้อมูลไปเก็บที่ 24LC128 แล้วอ่านข้อมูลในหน่วยความจำของ 24LC128 ที่เราพึ่งเขียนไปเก็บไว้ มาแสดงผลที่Hyperterminal ครับ หลักการทำงานคือ
    1. สั่งให้ uc ติดต่อกับ 24LC128 เพื่อเขียนข้อมูลไปเก็บไว้ โดยเหตุการณ์ที่เกิดกับ uc คือ ส่งสัญญาณ start, ส่ง แอสเดรสของสลาฟ+คำสั่งเขียน, รอรับ ACK, ส่งแอสเดรส hi และ low ที่ต้องการเก็บข้อมูล , ส่งข้อมูล, รอรับ ACK, ส่งสัญญาณ stop
    2. สั่งให้ uc อ่านข้อมูลจาก 24LC128 โดย ส่งสัญญาณ start, ส่ง แอสเดรสของสลาฟ+คำสั่งเขียน , รับกับ ACK, ส่งตำแหน่งที่จะอ่าน ,รอรับ ACK , ส่ง startอีกรอบ , ส่ง แอสเดรสของสลาฟ+คำสั่งอ่าน , รอรับ ACK , รับรับ Data , ส่งสัญญาณ Stop

    อันนี้ลอง sim กับ lpc2138 ออกแล้วครับ แก้โค๊ดมาเป็น lpc2368 แล้วดังที่แสดง แต่ว่ายังไม่มีตัว 24LC128 เลยยังไม่ได้ลองครับ T_T

    ReplyDelete
  2. ลอง lpc2368 กับ 24lc128 แล้วครับ
    ปรากฎว่าทำงานได้ปกติ

    ReplyDelete