分享

[转]用LPC2103的I2C实现EEPROM?24C01的读写

 liuzp001 2013-05-28

[原创]用LPC2103的I2C实现EEPROM 24C01的读写

 (2007-11-15 14:35:00)
标签: LPC2000  LPC2103  I2C  24C01  24C02 

以前习惯用SPI的器件,现在I2C的器件越来越多,不得不学习一下来充充电了。

写了一个24C01的读写代码,开发环境是IAR的EWARM,MCU是LPC2103,大家可以对照24C01的时序图来写程序。

本来想用LPC2000的I2C中断的,不知道怎么回事,中断老是开不起来,只好死等了。

/*
程序功能:24C01读写程序
晶振12M,I2C0,100K
*/
#include <iolpc2103.h>
#include <intrinsics.h>

#define MEMWRITE 0XA0 //写命令
#define MEMREAD 0XA1 //读命令
#define STA (1<<5) //起始位
#define I2CEN (1<<6) //允许位
#define STO (1<<4)  //停止位
#define SI (1<<3) // 中断标志
#define AA (1<<2) // 响应标志

#define LASTBYTE 1 //最后字节标志
//i2c_buf1为发送缓冲区,i2c_buf2为接收缓冲区
unsigned char i2c_buf1[10]={1,2,3,4,5,6,7,8,9,10},i2c_buf2[10];

void i2cInit(void);//I2C初始化程序
void i2cStart(void);//I2C发送起始位
void i2cStop(void);//I2C发送停止位
void writeByte(unsigned char data);//写一个字节的数据到总线上
void writeAddr(unsigned char mode);//写 地址和方向标志 到总线上
void writeData(unsigned char data);//完整的写数据,包括开始,清除标志等操作
unsigned char readByte(unsigned char last);//读字节数据,返回读到的值
void writeMem(int page_start,int count_byte,unsigned char *message_out);//写存储器的整体操作
void readMem(int page_start,int count_byte,unsigned char *message_in);//读存储器的整体操作
void delayMs(int dly);//延时

 

int main(void)
{
i2cInit();//I2C初始化
writeMem(0,8,i2c_buf1);//从存储器的0地址开始写8个字节的数据
delayMs(1000);
readMem(7,10,i2c_buf2);//读存储器的1地址开始写5个字节的数据
  while(1);
}

void i2cInit(void)
{
  PINSEL0    = 0x50;  //Switch GPIO to I2C pins
  I2C0SCLH   =15; //Set bit rate 12Mhz/VPBDIV+SCLH+SCLL = 12/4/(15+15) = 100Khz
  I2C0SCLL   =15;
  I2C0CONCLR  = 0XFF;
  I2C0CONSET  = I2CEN;
}

//I2C发送起始位
void i2cStart(void)
{
  I2C0CONSET=STA;
  do{}while(I2C0STAT!=0x08);//等待起始条件发送完成
  I2C0CONCLR=STA; 
}

//I2C发送停止位
void i2cStop(void)
{
  I2C0CONSET=STO;//启动发送stop位,STO位是自动清除的,不必判断是否结束
  I2C0CONCLR=SI; //只能清除SI,如果同时清除STO会导致返回到初始化状态
}

//写一个字节的数据到I2CDAT中
void writeByte(unsigned char data)
{
  I2C0DAT=data;
  I2C0CONCLR=SI;//启动发送
}

//发送控制字,其中mode为 MEMWRITE 或 MEMREAD
void writeAddr(unsigned char mode)
{
  writeByte(mode);
  if(mode==MEMREAD)do{}while(I2C0STAT!=0x40);//如果发送的是读控制字(地址),等待从机响应
  else
    do{}while(I2C0STAT!=0x18);//如果发送的是写控制字(地址),等待从机响应
}

//写数据
void writeData(unsigned char data)
{
  writeByte(data);
  do{}while(I2C0STAT!=0x28);//0x28——已发送I2CDAT中的字节,已经接受ACK
}

//读数据
unsigned char readByte(unsigned char last)
{
  if(last)//如果读的是最后一个字节,不需要发送应答位
  {
    I2C0CONCLR=AA;
    I2C0CONCLR=SI;
    do{}while(I2C0STAT!=0x58);//等待接收数据直接和非ACK
  }
  else
  {  I2C0CONSET=AA;//发送一个应答位
     I2C0CONCLR=SI;
    do{}while(I2C0STAT!=0x50);//等待接收数据直接和ACK
  }
  return (I2C0DAT);
}

/*
写24C01
入口: page_start——起始地址,count_byte——需要写的字节数,
message_out——需要写入的数据缓冲区头指针
*/
void writeMem(int page_start,int count_byte,unsigned char *message_out)
{
  int i;
  i2cStart();//发送起始位
  writeAddr(MEMWRITE);//发送写控制字
  writeData(page_start);//发送写的起始地址
  for(i=0;i<count_byte;i++,message_out++)//写数据
    writeData(*message_out);
  i2cStop();//发送停止位
}
/*
读24C01,模式——顺序读(SEQUENTIAL READ)
入口:page_start——读起始地址,count_byte——需要读的字节数,
message_in——读缓冲区头指针
出口:
*/
void readMem(int page_start,int count_byte,unsigned char *message_in)
{
    int i;
   //设置读指针
  i2cStart();//发送起始位
  writeAddr(MEMWRITE);//发送写控制字
  writeData(page_start);//发送读的起始地址
  i2cStop();//发送停止位
 
  //开始读数据
  i2cStart();//发送起始位
  writeAddr(MEMREAD);//发送读控制字
  for(i=0;i<count_byte;i++,message_in++)//接收数据
    *message_in=readByte(!LASTBYTE);
  *message_in=readByte(LASTBYTE);
  i2cStop();//发送停止位
}

void delayMs(int dly)
{
  int i;
  for(;dly>0;dly--)
    for(i=0;i<1000;i++);
 
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多