24c04读写程序详解

电子常识

2585人已加入

描述

  24c04读写程序详解

  SCL BIT P1.7;定义24C02的串行时钟线 ClimberWin 2005.8.4

  SDA BIT P1.6;定义24C02的串行数据线

  ORG 00H

  START:

  MOV R1,#20H ; 数据保存地址

  MOV R7,#120 ; 取数据的个数

  ;;**********************************

  CALL FIRST ;开始命令

  MOV A,#0A0H ;写器件地址

  CALL SUBS

  ;;**********************************

  MOV A,#00h ;所要读的器件的地址

  CALL SUBS

  ;;**********************************

  CALL FIRST ;开始命令

  MOV A,#0A1H ;开始读数据

  CALL SUBS

  ;;**********************************

  WIN: CALL SUBR

  MOV @R1,A

  INC R1

  DJNZ R7,WIN

  CLR SDA

  CALL DELAY

  SETB SCL

  CALL DELAY

  SETB SDA

  JMP $

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  SUBR: MOV R0,#08H

  LOOP2: SETB SCL

  CALL DELAY

  MOV C,SDA

  RLC A

  CLR SCL

  CALL DELAY

  DJNZ R0,LOOP2

  CJNE R7,#00h,LOW1 ;改

  SETB SDA

  JMP CLIMBER

  LOW1: CLR SDA

  CLIMBER:CALL DELAY

  SETB SCL

  CALL DELAY

  CLR SCL

  CALL DELAY

  SETB SDA

  RET

  SUBS: MOV R5,#08H

  LOOP: CLR SCL

  RLC A

  MOV SDA ,C

  NOP

  SETB SCL

  CALL DELAY

  DJNZ R5,LOOP

  CLR SCL

  CALL DELAY

  SETB SCL

  REP: MOV C, SDA

  JC REP

  CLR SCL

  RET

  DELAY: NOP

  NOP

  RET

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  FIRST: SETB SDA

  SETB SCL

  CALL DELAY

  CLR SDA

  CALL DELAY

  CLR SCL ;开始传数据

  RET

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  END

  先把下面的#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:;

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分