关于24C02的头痛的问题,有哪位碰到过这些问题,请指点一下

2020-01-20 19:01发布

关于24C02迷惑的问题
  我想多次向24C02写入多个数据,源程序都写好,在送入数据时,如果每次写入4个数据,有时可以显示正常,有时不正常,如果每次写入6个数,则显示就出现不可预料的问题。请问单次向24C02写入数据个数有什么限制吗?附上源程序,测试过源程序没有什么问题,就是在一次向24C02写入数据个数上有问题,看了别人很多贴貌似是与24C02一页写入的数据个数限制有关,具体有什么关系,问题出在哪调试了好久都没有弄明白。请大侠帮忙看看,谢谢

这是24C02的读写程序,测试貌似没有问题,也许是这其中问题我没发现,请指导
/********************************************************************************************************************/
//*******************************************************************

//***IIC总线芯片为24C02,读写程序。
//*******************************************************************
#include "reg52.h"
#include<intrins.h>
#define  uchar unsigned char        
#define  uint  unsigned int
#define  nop  _nop_()       /* 定义空操作指令 */
sbit SCL=P3^4;                                /*24C01 CSL接脚=89C51 T0 P3.4*/
sbit SDA=P3^5;                                /*24C01 SDA接脚=89C51 T1 P3.5*/
bit TSendAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no); /* 向有子地址器件写入6字节数据函数 */
bit TRcvAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no);  /* 向有子地址器件读取6字节数据函数 */
bit acknow;                                 /* 应答标志位 acknow=1 表示正常响应 acknow=0 表示未响应 */

void delay (unsigned int value)                /*延时副程式*/
{
      while (value!=0) value--;                /*10US延时*/
}
                       



void Start();                           /* 起动总线函数 */
void Stop();                            /* 结束总线函数 */
void SendByte(uchar c);                 /* 8951发数据或地址给8583 字节数据发送函数 */
uchar RcvByte();                        /* 8951从24C01读数据字节数据接收函数 */
void Ack(bit a);                        /* 主机8951应答子函数 */




/*******************************************************************/
//   24C02芯片读写        起动总线函数               
//函数原型: void  Start();  
//功能:     启动总线,发送24c02启动条件.  
//==================================================================
void Start()
{//SDA=0;

  // SCL=0;
   SDA=1;           /*发送起始条件的数据信号*/
   nop;
   SCL=1;
   nop;            /*起始条件建立时间大于4.7us,延时*/
   nop;
   nop;
   nop;
   nop;   
   SDA=0;           /*发送起始信号*/
   nop;            /* 起始条件锁定时间大于4us*/
   nop;
   nop;
   nop;
   nop;      
   SCL=0;           /*钳住总线,准备发送或接收数据 */
   nop;
   nop;
  
}
//==================================================================
//                      结束总线函数               
//函数原型: void  Stop();  
//功能:     结束总线,发送24c02结束条件.  
//==================================================================
void Stop()
{
// SCL=0;
  SDA=0;          /*发送结束条件的数据信号*/
  nop;           /*发送结束条件的时钟信号*/
  SCL=1;          /*结束条件建立时间大于4us*/
  nop;
  nop;
  nop;
  nop;
  nop;
  SDA=1;          /*发送总线结束信号*/
  nop;
  nop;
  nop;
  nop;

}
//==================================================================
//                 89X52发数据或地址给24c02 字节数据发送函数               
//函数原型: void  SendByte(uchar c);
//功能:   将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
//        此状态位进行操作.(不应答或非应答都使acknow=0)     
//               发送数据正常,acknow=1; acknow=0表示被控器无应答或损坏。
//==================================================================
void  SendByte(uchar c)
{ uchar count;
for(count=0;count<8;count++)  /*要传送的数据长度为8位*/
    {if((c<<count)&0x80)
         SDA=1;                /*判断发送位*/
     else  
         SDA=0;               
     nop;
     SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/
      nop;
      nop;             /*保证时钟高电平周期大于4us*/
      nop;
      nop;
      nop;         
     SCL=0;
    }
    nop;
    nop;
    SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/
    nop;
    nop;   
    SCL=1;
    nop;
    nop;
    nop;
    if(SDA==1)
      acknow=0;        /* 24c02无应答 */     
    else
      acknow=1;        /* 发送数据正常 */
    SCL=0;
    nop;
    nop;
}
//==================================================================
//                 89X52从24c02读数据字节数据接收函数               
//函数原型: uchar  RcvByte();
//功能:            用来接收从器件传来的数据,并判断总线错误(不发应答信号),
//          发完后请用应答函数应答从机。  
//==================================================================
uchar  RcvByte()
{uchar retc=0;
uchar count;
SDA=1;                             /*置数据线为输入方式*/
for(count=0;count<8;count++)
   {    nop;           
        SCL=0;                  /*置时钟线为低,准备接收数据位*/
        nop;
        nop;                 /*时钟低电平周期大于4.7us*/
        nop;
        nop;
        nop;
        SCL=1;                  /*置时钟线为高使数据线上数据有效*/
        nop;
        nop;
        retc=retc<<1;
        if(SDA==1)
        retc=retc+1;  /*读数据位,接收的数据位放入retc中 */
        nop;
        nop;
  }
  SCL=0;   
  nop;
  nop;
  return(retc);
}
//==================================================================
//                     主机89X52应答子函数
//函数原型:  void Ack(bit a);
//功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
//==================================================================
void Ack(bit a)
{if(a==0)                  
     SDA=0;                  /*在此发出应答或非应答信号 */
  else                       /* 应答 a=0  非应答 a=1 */
     SDA=1;
  nop;
  nop;
  nop;      
  SCL=1;
  nop;
  nop;                    /*时钟低电平周期大于4us*/
  nop;
  nop;
  nop;  
  SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/
  nop;
  nop;   
}
//==================================================================
//                 用户接口函数                                   
// 有无子地址表示是否向芯片的特定地址写数据  
//          向有子地址器件写入6字节数据函数  对应数据资料中的写模式            
//函数原型: bit  TSendAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no);  
//功能:     从启动总线到发送从地址,子地址,数据,结束总线的全过程,从器件
//          地址slaaddress,子地址subaddress,发送内容是s指向的内容,no=字节数
//          如果返回1表示操作成功,否则操作有误。
//注意:    使用前必须已结束总线。
//==================================================================
bit TSendAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no) /* 向有子地址器件写入6字节数据函数 */
{uchar i;
   Start();                               /*启动总线*/
   SendByte(slaaddress);        /*发送器件地址*/
   if(acknow==0)
  return(0);
   SendByte(subaddress);        /*发送器件子地址*/
   if(acknow==0)
  return(0);
   for(i=0;i<no;i++)
   {
     SendByte(* s);
                            /*发送数据*/
        if(acknow==0)
    return(0);
        s++;
   }   
   Stop();                                  /*结束总线*/
   return(1);
}
//==================================================================
//                    向有子地址器件读取4字节数据函数               
//函数原型: bit  TRcvAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no);  
//功能:     从启动总线到发送从地址,子地址,读数据,结束总线的全过程,从器件
//          地址slaaddress,子地址subaddress,读出的内容放入s, no=字节数
//           如果返回1表示操作成功,否则操作有误。
//注意:    使用前必须已结束总线。
//==================================================================
bit TRcvAddress(uchar slaaddress,uchar subaddress,uchar * s,uchar no)
{ uchar i;
   Start();                             /*启动总线*/
   SendByte(slaaddress);                /*发送器件从地址*/
  // if(acknow==0)
  // return(0);
   SendByte(subaddress);               /*发送器件子地址*/
   if(acknow==0)
   return(0);
   Stop();                   /*结束总线*/
   Start();                         /*重新启动总线*/
   SendByte(slaaddress+1);
  // if(acknow==0)
  // return(0);
   for(i=0;i<no-1;i++)
    {* s=RcvByte();               /*接收数据*/
     Ack(0);                     /*发送应答位*/
     s++;
    }                  
     * s=RcvByte();               /*接收数据*/
     Ack(1);
     Stop();                   /*结束总线*/
     return(1);
}
//==================================================================

/********************************************************************/
void main()
{        
     uchar  k,f,stad=0;
     uchar out[6]={8,9,6,7,5,4};
     Lcminit();                /*液晶初始化*/
     delay_10ms(10);        /*延时100ms*/
     Lcmcls();                   /*全屏清零*/
     for(k=0;k<63;k++){
        stad=k*4;
        TSendAddress(0xa0,stad,&out,4);//连续存储每次存储四个字节
        delay_10ms(10);
     }
   
while(1){
   for(f=0;f<63;f++) {
           uchar st=f*4;
           TRcvAddress(0xa0,st,&out1,4);//读出四个字节
           delay_10ms(50);
           for(i=0;i<40;i++) print1();//显示读出的数据
          Lcmcls();
          for(i=0;i<50;i++)print2();//显示读出的数据
          Lcmcls();
   }
}
将写入和读出改为每次6个字节就不会出现预想的结果了。
路过的请指点一写入与读出数据个数是否有规定,如果没有请哪位有时间的帮忙看看程序是否有问题。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
16条回答
helloshi
2020-01-21 22:29
//连续写
uchar AT24CWrite(uchar *buf,uint addr,uint length)
{
  uint  address;
  uint  address_end;       //字结束地址
  uint  page_address_end;  //页结束位置
  uint  page,page_end;     //页号,跨器件

  address  = addr;
  address_end =  address+length;
  if((address_end)>EEPROM_SIZE_MAX)return 1; //超出最多芯片最大容量

  page              = address     / PAGE_SIZE;   //起始页
  page_end          = address_end / PAGE_SIZE;   //结束页

  while(page <= page_end)
  {
          IICStart();      //起始信号
          if(!IICWrite((uchar)DEVICE_ADDRESS(address)|WRITE)){IICStop();return 1;}//器件地址
          
    #if DEVICE >= 32 // AT24C32以上写高地址
          if(!IICWrite((uchar)(address % EEPROM_SIZE)>>8)){IICStop();return 1;}   //字高地址
    #endif
          if(!IICWrite((uchar)(address % EEPROM_SIZE))){IICStop();return 1;}      //字低地址

          
          if(page++ == page_end) page_address_end = address_end;  //最后一页
          else page_address_end = PAGE_SIZE*(page);           //完整一页
          
          while(address<page_address_end){  
      if(!IICWrite(*buf++)){IICStop(); return 1;}
                  address++;
          }
          IICStop();       //停止信号

          twr();//延时,等待页写完
  }
  return 0;
}

一周热门 更多>