废话连天 https://passport2.21ic.com/?432761 [收藏] [复制] [RSS]

日志

I2C驱动24c04程序

已有 3447 次阅读2007-5-23 15:26 |系统分类:存储器

看到很多人在找24Cxx的程序,找了又用不了,干脆拿自己的分享算了。

以下代码功能极其强大,而且使用方便,基本上改几个参数,直接调用就行。至于原理说起来就太长了,只好自己消化吸收。

只能用24c01A~24c16A系列,容量超过的不行

 

/*
本程序可以一次读和写最多256个字节数据,超出会发生卷页,即从0xff回到0x00
继续写或者读,请注意
本子程序使用方法如下:
先把下面的#define numbyte 改为对应IC型号
调用Write_Flash()和Read_Flash()前,先把page07填好对应的页数,下面的
函数声明处有说明

需要在主程序处定义一些参数,如下:

 bit f_rom;      //eprom应答标志,=1不应答
 uchar xdata epromerr;   //用来统计写入出错的次数
 uint  xdata epadd;    //用来作为rom目标写入的首地址,要进行计算
 uchar xdata page07;    //每256个字节当一页,请注意不要写错页
 uchar xdata *ncon;    //用来处理写入或读入的缓存地址
 uchar xdata len1;    //rom第一段数据长度,看eprom.c
 uchar xdata len2;    //rom中间段数据页数,看eprom.c
 uchar xdata len3;     //rom末尾段数据长度,看eprom.c

如果不用外部存储器件,把关键字xdata去掉,然后再修改Write_Flash()
和Read_Flash()的声明部分参数
*/

//定义使用的IC,容量超过了这些IC就不能用了
#define  d_24c01a  8  //定义IC每一页的字节数
#define  d_24c02   8
#define  d_24c04   16
#define  d_24c08a  16
#define  d_24c16a  16

#define  numbyte_page d_24c16a

#define  WriteDeviceAddress 0xa0 //写驱动地址指令
#define  ReadDeviceAddress 0xa1  //读驱动地址指令

 

void nod2()
{unsigned char i;     //4.6us延时
 for (i=0;i<13;i++)
 _nop_();
}
/*-------------------------------------------------------------
功能:发起始信号
------------------------------------------------------------*/
void Start_Cond()
{
 SDA = 1;
    nod2();
 SCL = 1;
    nod2();
 SDA = 0;
 nod2();
 SCL = 0;
 nod2();
}

/*-------------------------------------------------------------
功能:发停止信号
------------------------------------------------------------*/
void Stop_Cond()
{
 SDA = 0;
 nod2();
 SCL = 1;
 nod2();
 SDA = 1;
 nod2();
 SCL = 0;
 nod2();
}

/*-------------------------------------------------------------
功能:发确认信号
------------------------------------------------------------*/
void Ack()
{
 SDA = 0;
 nod2();
 SCL = 1;
 nod2();
 SCL = 0;
 nod2();
 SDA = 1;
 nod2();
}

/*-------------------------------------------------------------
功能:发无确认信号
------------------------------------------------------------*/
void NoAck()
{
 SDA = 1;
 nod2();
 SCL = 1;
 nod2();
 SCL = 0;
 nod2();
 SDA = 0;
 nod2();
}

/*-------------------------------------------------------------
功能:读一个字节数据
------------------------------------------------------------*/
unsigned char Read8Bit()
{
 unsigned char temp,rbyte=0;
 for (temp = 0;temp<8;temp++)
 { SDA=1;
  nod2();
  SCL = 1;
  nod2();
  rbyte=(rbyte<<1)|SDA;
  SCL = 0;
        nod2();
 }
 return(rbyte);
}
/*-------------------------------------------------------------
功能:写一个字节数据
------------------------------------------------------------*/
Write8Bit(unsigned char input)
{
 unsigned char i;
 for (i=0;i<8;i++)
 { input <<= 1;
  SDA = CY;
  nod2();
  SCL = 1;
  nod2();
  SCL = 0;
  nod2();
  SDA = 0;
  nod2();
 }
 f_rom=0;  //chack
 SDA=1;
 nod2();
 nod2();
 SCL=1;
 nod2();
 nod2();
 f_rom=SDA;
 SCL=0;
 nod2();
 nod2(); 
}

/*------------------------------------------------------------
功能:从EEPROM中给定一个地址连续读NLEN个字节数据存放在以指针
nContent开头的往下内容。
写地址为0x000~0x7ff,用参数page07代表最高位的页数(0~7)
------------------------------------------------------------*/
Read_Flash ( unsigned char xdata *nContent, unsigned char nAddr, unsigned int nLen ) large reentrant
{
 unsigned char i,j;

 //例如目标首地址为5,要写入20个字节,用24c02(每页8个字节)
 //那么len1=8-5%8=3,第一页只能读3个字节
 //len3=(20-3)%8=1,最后页只能读1个字节
 //len2=(20-3-1)/8=2,中间能完整的读2页,刚好20个字节读完

 //目标rom首地址离一页末要读的字节数 
 len1=numbyte_page-nAddr%numbyte_page;

 //目标rom最后页读入的字节数
 len3=(nLen-len1)%numbyte_page;

 //目标rom中间能够完整读入的页数
 len2=(nLen-len1-len3)/numbyte_page;

 if(len1>nLen)  //假如读入长度不足把第一页写完,要更正参数
 { len1=nLen;
  len2=0;
  len3=0;
 }

 epromerr=0;
wrstart2:
 epromerr++;
 ncon=nContent;
 if(epromerr>200)
  goto errdo2;

 //===========================
 //读第一段数据
 //===========================
 Start_Cond();
 Write8Bit(WriteDeviceAddress+(page07<<1));  //写写控制字
 if(f_rom==1)
  goto wrstart2;

 Write8Bit(nAddr);     //写地址
 if(f_rom==1)
  goto wrstart2;

 Start_Cond();      
 Write8Bit(ReadDeviceAddress+(page07<<1));  //写读控制字
 if(f_rom==1)
  goto wrstart2;
  
 if(len1>1)       //读第一段数据
 { for(i=0;i<(len1-1);i++)
  { *ncon=Read8Bit();
   Ack();
   ncon++; 
  }
 }
 *ncon=Read8Bit();     //读1个数
 NoAck();
 ncon++;
 Stop_Cond();      //停止
 nod2();

 //===========================
 //读中间段数据
 //===========================
if(len2>0)
{ for(j=0;j<len2;j++)
 {
  epadd=nAddr+(numbyte_page)*j+len1; //修正写入目标偏移地址

  Start_Cond();
  Write8Bit(WriteDeviceAddress+(page07<<1));  //写写控制字
  if(f_rom==1)
   goto wrstart2; 
 
  Write8Bit(epadd);     //写地址
  if(f_rom==1)
   goto wrstart2;

  Start_Cond();      
  Write8Bit(ReadDeviceAddress+(page07<<1));  //写读控制字
  if(f_rom==1)
   goto wrstart2;

  for(i=0;i<(numbyte_page-1);i++)  //读numbyte_page-1个字节
  { *ncon=Read8Bit();
   Ack();
   ncon++; 
  }
  *ncon=Read8Bit();     //读1个字节
  NoAck();
  ncon++;
  Stop_Cond();      //停止
  nod2();
 }
}

 //===========================
 //读末尾段数据
 //===========================
if(len3>0)
{ epadd=nAddr+(numbyte_page)*len2+len1; //修正写入目标偏移地址

 Start_Cond();
 Write8Bit(WriteDeviceAddress+(page07<<1));  //写写控制字
 if(f_rom==1)
  goto wrstart2;

 Write8Bit(epadd);     //写地址
 if(f_rom==1)
  goto wrstart2;

 Start_Cond();      
 Write8Bit(ReadDeviceAddress+(page07<<1));  //写读控制字
 if(f_rom==1)
  goto wrstart2;
  
 if(len3>1)       //读末尾段数据
 { for(i=0;i<(len3-1);i++)
  { *ncon=Read8Bit();
   Ack();
   ncon++; 
  }
 }
 *ncon=Read8Bit();     //读1个数
 NoAck();
 ncon++;
 Stop_Cond();      //停止
 nod2();
}

 


/*

 j=0;
restart: j++;
     if (j==255)
   goto errdo2;

         Start_Cond();      //写开始信号
   Write8Bit(WriteDeviceAddress);  //写写控制字
   if(f_rom==1) goto restart;
   Write8Bit(nAddr);     //写地址
   if(f_rom==1) goto restart;
   Start_Cond();      //写开始信号
   Write8Bit(ReadDeviceAddress);  //写读控制字
   if(f_rom==1) goto restart;
  for(i=0;i<(nLen-1);i++)     //读7个数
  { *nContent=Read8Bit();
   Ack();
   nContent++;
  }
  *nContent=Read8Bit();     //读1个数
  NoAck();
  Stop_Cond();       //停止
  nod2();

  
*/
errdo2:;//////////////////////////////////////读数据超时处理
//outr:;
}

/*-------------------------------------------------------------
功能:从EEPROM中给定一个地址nAddr,连续写NLEN个字节数据存放在以指针
nContent开头的往下内容
写地址为0x000~0x7ff,用参数page07代表最高位的页数(0~7)
------------------------------------------------------------*/

Write_Flash ( unsigned char xdata *nContent,unsigned char nAddr, unsigned int nLen) large reentrant
{

 //unsigned char epromerr;   //用来统计写入出错的次数
 unsigned char i,j;     //for循坏用
 //unsigned char xdata epadd;  //用来作为rom目标地址,要进行计算
 //unsigned char xdata len1;   //rom第一段数据长度,看eprom.c
 //unsigned char xdata len2;   //rom中间段数据页数,看eprom.c
 //unsigned char xdata len3;   //rom末尾段数据长度,看eprom.c

 //例如目标首地址为5,要写入20个字节,用24c02(每页8个字节)
 //那么len1=8-5%8=3,第一页只能写3个字节
 //len2=(20-3)%8=1,最后页只能写1个字节
 //len3=(20-3-1)/8=2,中间能完整的写2页,刚好20个字节写完

 //目标rom首地址离一页末要写的字节数 
 len1=numbyte_page-nAddr%numbyte_page;

 //目标rom最后页写入的字节数
 len3=(nLen-len1)%numbyte_page;

 //目标rom中间能够完整写入的页数
 len2=(nLen-len1-len3)/numbyte_page;

 if(len1>nLen)  //假如写入长度不足把第一页写完,要更正参数
 { len1=nLen;
  len2=0;
  len3=0;
 }

 epromerr=0;
wrstart:
 ++epromerr;
 ncon=nContent;      //重新修正缓存对应地址
 if(epromerr>200)
  goto errdo1;
//===========================
//写第一段数据
//===========================
 Start_Cond();
 Write8Bit(WriteDeviceAddress+(page07<<1));  //写写控制字
 if(f_rom==1)
  goto wrstart;

 Write8Bit(nAddr);     //写地址
 if(f_rom==1)
  goto wrstart;

 for(i=0;i<len1;i++)     //写第一段数据
 {  Write8Bit(*ncon);
   if(f_rom==1)
    goto wrstart;
   ncon++;
 }
 Stop_Cond();      //首段写完

//===========================
//写中间的完整段数据
//===========================
if(len2>0)
{ for(j=0;j<len2;j++)      //写len2页
 { epadd=nAddr+(numbyte_page)*j+len1; //修正写入目标偏移地址

  Start_Cond();
  Write8Bit(WriteDeviceAddress+(page07<<1));  //写写控制字
  if(f_rom==1)
   goto wrstart;

  Write8Bit(epadd);     //写地址
  if(f_rom==1)
   goto wrstart;

  for(i=0;i<numbyte_page;i++)   //写完整的一页
  { Write8Bit(*ncon);
    if(f_rom==1)
     goto wrstart;
    ncon++;
  }

  Stop_Cond();      //一段写完

 }
}

//===========================
//写末尾段数据
//===========================
if(len3>0)
{ epadd=nAddr+(numbyte_page)*len2+len1; //修正写入目标偏移地址

 Start_Cond();
 Write8Bit(WriteDeviceAddress+(page07<<1));  //写写控制字
 if(f_rom==1)
  goto wrstart;

 Write8Bit(epadd);     //写地址
 if(f_rom==1)
  goto wrstart;

 for(i=0;i<len3;i++)     //写末尾段数据
 {  Write8Bit(*ncon);
   if(f_rom==1)
    goto wrstart;
   ncon++;
 }
 Stop_Cond();      //末尾段写完

}

 

errdo1:;
}

路过

鸡蛋

鲜花

握手

雷人

全部作者的其他最新日志

发表评论 评论 (1 个评论)

回复 sunny 2007-9-20 23:34
74595驱动数码管的汇编程序 可以麻烦你指导性的讲讲怎么写吗? 谢谢! EMAIL:sunnygwg@hotmail.com
回复 我是谁 2007-11-5 04:55
请问老大。有没有考虑eeprom写入数据的时候有一段不应期?
访客8CSf73 2008-4-19 10:25
不错呵!!!