新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > LPC23xx通过I2C接口读写AT24C64

LPC23xx通过I2C接口读写AT24C64

作者:时间:2016-11-10来源:网络收藏
网上关于philips的32位ARM微控制器通过I2C接口读写AT24C系列E2PROM的例子基本都是通过中断方式读写的,包括周立功的书上也是用中断方式的,用这种方式,要在中断服务程序中进行复杂的处理,程序比较难以理解,使用非中断方式编程比较方便,便于理解。以下程序本人在LPC2364上测试通过。程序中的一些常量做了简要说明,具体课查看LPC23xx系列微控制器的用户手册。

I2C.h

本文引用地址://m.amcfsurvey.com/article/201611/317227.htm

#define AT24C64NW 0xA0
#define AT24C64NR 0xA1

#define MAX_TIMEOUT0x00FFFFFF
#define I2CONSET_I2EN0x00000040 /* I2C Control Set Register */
#define I2CONSET_AA0x00000004
#define I2CONSET_SI0x00000008
#define I2CONSET_STO0x00000010
#define I2CONSET_STA0x00000020

#define I2CONCLR_AAC0x00000004 /* I2C Control clear Register */
#define I2CONCLR_SIC0x00000008
#define I2CONCLR_STAC0x00000020
#define I2CONCLR_I2ENC0x00000040

#define I2DAT_I2C0x00000000 /* I2C Data Reg */
#define I2ADR_I2C0x00000000 /* I2C Slave Address Reg */
#define I2SCLH_SCLH0x00000080 /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL0x00000080 /* I2C SCL Duty Cycle Low Reg */


#define SDA0 0x08000000 //p0.27
#define SCL0 0x10000000 //p0.28
#define SDA0CON 0x08000000
#define SCL0CON 0x10000000
extern DWORD I2CInit( UINT32 Fi2c );
extern DWORD I2CStart( void );
extern DWORD I2CStop( void );
extern DWORD I2CStartAgain( void );
extern DWORD I2C_ReadByte(BYTE ACK, BYTE *RcvData);
extern DWORD I2C_SendNByte(UINT16 SubAddr ,UINT8 *Data,UINT8 Length);
extern DWORD I2C_ReadNByte(UINT16 SubAddr ,UINT8 *Data,UINT8 Length);

I2C.c

DWORD I2CInit( UINT32 Fi2c )

{

if (Fi2c > 400000)

Fi2c = 400000;

PINSEL1 &= ~0x03C00000;

PINSEL1 |= 0x01400000;/* set PIO0.27 and PIO0.28 to I2C0 SDA and SCK */

I20SCLH = (Fpclk/Fi2c + 1) / 2;/*设定I2C时钟*/

I20SCLL = (Fpclk/Fi2c)/2;

I20CONCLR = 0x2C;// clear STA, SI,AA

I20CONSET = 0x40;// SET I2EN/*使能主I2C */

return( TRUE );

}

DWORD I2CStart( void )

{

DWORD timeout = 0;

DWORD returnValue = FALSE;

/*--- Issue a start condition ---*/

I20CONCLR=I2CONCLR_SIC|I2CONCLR_AAC|I2CONCLR_STAC;

I20CONSET=I2CONSET_STA|I2CONSET_I2EN;/* Set Start flag */

/*--- Wait until START transmitted ---*/

while( 1 )

{

if (I20STAT==0x08)

{

returnValue = TRUE;

break;

}

if ( timeout >= MAX_TIMEOUT )

{

returnValue = FALSE;

break;

}

timeout++;

}

return( returnValue );

}

DWORD I2CStartAgain( void )

{

DWORD timeout = 0;

DWORD returnValue = FALSE;

/*--- Issue a start condition ---*/

I20CONCLR = I2CONCLR_SIC|I2CONCLR_AAC|I2CONCLR_STAC;//发送重复起始条件前一定要清零SI

I20CONSET = I2CONSET_STA|I2CONSET_I2EN;/* Set Start flag */

/*--- Wait until START transmitted ---*/

while( 1 )

{

if ( I20STAT == 0x10 )

{

returnValue = TRUE;

break;

}

if ( timeout >= MAX_TIMEOUT )

{

returnValue = FALSE;

break;

}

timeout++;

}

return( returnValue );

}

DWORD I2CStop( void )

{

I20CONSET = I2CONSET_STO;/* Set Stop flag */

I20CONCLR = I2CONCLR_SIC|I2CONCLR_STAC|I2CONCLR_AAC;/* Clear SI flag */// modified

/*--- Wait for STOP detected ---*/

while( I20CONSET & I2CONSET_STO );

return TRUE;

}

void I2C_SendByte(UINT8 SData)

{

I20DAT=SData;

I20CONCLR =0x28;/*清零SI,STA */

while (!(I20CONSET&I2CONCLR_SIC));// wait interrupt flag ( waiting for SI==1)

}

DWORD I2C_SendNByte(UINT16 SubAddr ,UINT8 *Data,UINT8 Length)

{

BYTE i;

I2CStart();

if(I20STAT==0x08)/*已发送起始条件*/

{

I2C_SendByte(AT24C64NW);// Device Address

if(I20STAT==0x18) /*已发送SLA+W,已接收ACK */

{

I2C_SendByte((SubAddr>>8)&(0x00FF));

if(I20STAT==0x28)/*已发送SubAddr_H,已接收ACK */

{

I2C_SendByte(SubAddr&(0x00FF));

if(I20STAT==0x28) /*已发送SubAddr_L,已接收ACK */

{

for(i=0;i

{

do{

I2C_SendByte(Data[i]);

}while(I20STAT!=0x28);

}

if(I2CStop())

{

DelayNS(5);//10ms

return TRUE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

DWORD I2C_ReadByte(BYTE ACK, BYTE *RcvData)

{

if (ACK==1)//send ACK

{

I20CONSET=I2CONSET_AA;

}

else//sendNOACK

if(ACK==0)

{

I20CONCLR=I2CONCLR_AAC;

}

I20CONCLR=I2CONCLR_SIC|I2CONCLR_STAC;// clear SISAT

while (!(I20CONSET&I2CONCLR_SIC));// wait interrupt flag ( waiting for SI==1)

if(ACK==1)

{

if((I20STAT&0xF8)==0x50) //receive data and get ack

{

*RcvData=I20DAT;

return TRUE;

}

else

return FALSE ;

}

else

if(ACK==0)

{

if((I20STAT&0xF8)==0x58) //receive data and get NoAck (the last data you want to get)

{

*RcvData=I20DAT;

return TRUE;

}

else

return FALSE ;

}

return FALSE ;

}

DWORD I2C_ReadNByte(UINT16 SubAddr ,UINT8 *Data,UINT8 Length)

{

BYTEi;

if (!I2CStart())

{

return FALSE;

}

if(I20STAT==0x08)/*已发送起始条件*/

{

I2C_SendByte(AT24C64NW);// Device Address

if(I20STAT==0x18) /*已发送SLA+W,已接收ACK */

{

I2C_SendByte((SubAddr>>8)&(0x00FF));

if(I20STAT==0x28)/*已发送SubAddr_H,已接收ACK */

{

I2C_SendByte(SubAddr&(0x00FF));

if(I20STAT==0x28) /*已发送SubAddr_L,已接收ACK */

{

if (I2CStartAgain())//发送重复起始条件切换为主接受模式

{

I2C_SendByte(AT24C64NR);

if(I20STAT==0x40)/*已发送SLA+R,已接收ACK*/

{

for(i=0;i

{

if(!(I2C_ReadByte(1,&Data[i])))

{

return FALSE;

}

}

if( !( I2C_ReadByte(0, &Data[Length-1]) ) ) //读最后一个数据

{

return FALSE;

}

if (I2CStop())//发送停止条件

{

return TRUE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}

return FALSE;

}



评论


技术专区

关闭