Mikle2016 发表于 2016-5-5 12:18:43

(求助)用51读写AT24C256问题

1.我是新手,在网上找的个51读写AT24C256程序,现在用AT89C51或STC12C5A60S2,晶振:22.1184MHz。现将程序贴如下:

#include <reg51.h>
#include <INTRINS.H>
//#include <STC15F104E.h>
#defineERROR 10
sbit   SDA=P2^1;
sbit   SCL=P2^0;
enumeepromtype{AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};
enumeepromtype enumer;

//DataBuff为读写数据输入/输出缓冲地址
//ByteQuantity 为要读写数据的字节数量
//Address 为EEPROM片内地址
//ControlByte为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W)其中R/W=1,
//为读操作,R/W=0,为写操作,A2,A1,A0为EEPROM的页选或片选地址·;
//enume为枚举变量,需为AT2401至T24256中的一种,分别对应24C01ÖÁ24C256;
//ERROR为允许最大次数,若出现ERROR次操作失效后,则函数终止操作。
//SDA和SCL由用户自定义,这里P2^1和P2^0;
//其余的用户不用管,只要把子程序放在自己的程序中并调用就可以了;

/***********************************************************************************/
void   RW24xx(unsigned char *DataBuff,unsigned char ByteQuantity,unsigned int Address,
                     unsigned char ControlByte,enum eepromtype enumer)
{
         void Delay(unsigned char DelayCount);
         void IICStart(void);
         void IICStop(void);
         bitIICRecAck(void);
         void IICNoAck(void);
         void IICAck(void);
         unsigned char IICReceiveByte(void);
         void IICSendByte(unsigned char sendbyte);
         unsigned char data j,i;
         idata unsigned char m_page,m_cell_first,m_cell_last;
         bit   errorflag=1;
      if((64-Address%64)<ByteQuantity)
         {
            m_cell_first=64-Address%64;
         }
      else
         {
            m_cell_first=ByteQuantity;
         }

         m_page=(ByteQuantity-(64-Address%64))/64;
         m_cell_last=(ByteQuantity-(64-Address%64))%64;
         i=ERROR;
      while(i--)
         {
                IICStart();
                IICSendByte(ControlByte&0xfe);
                if(IICRecAck())
                   continue;
                if(enumer>AT2416)
               {
                     IICSendByte((unsigned char)(Address>>8));
                     if(IICRecAck())
                     continue;
               }
               IICSendByte((unsigned char)Address);
               if(IICRecAck())
               continue;
                if(!(ControlByte&0x01))
                  {
                             j=m_cell_first;                                     
                     errorflag=0;                      //********clr errorflag
                     while(j--)
                         {
                           IICSendByte(*DataBuff++);
                           if(!IICRecAck())                          
                           continue;
                           errorflag=1;                                   //发送成功不会经过此处
                           break;
                        }
                                      }
               else
                  {
                        IICStart();
                        IICSendByte(ControlByte);
                        if(IICRecAck())
                        continue;
                        while(--m_cell_first)
                           {
                           *DataBuff++=IICReceiveByte();
                              IICAck();
                           }
                     *DataBuff++=IICReceiveByte();      //read last byte data
                     IICNoAck();
                     errorflag=0;
                     break;
                     }               
         }

         IICStop();
         if(!(ControlByte&0x01))
             {
               Delay(255);
               Delay(255);
               Delay(255);
               Delay(255);
             }       
         Address+=(64-Address%64);

      while(m_page--)
            {
                           i=ERROR;
                           while(i--)
                           {
                                  IICStart();
                                  IICSendByte(ControlByte&0xfe);
                                  if(IICRecAck())
                      continue;
                              if(enumer>AT2416)
                                  {
                                       IICSendByte((unsigned char)(Address>>8));
                                       if(IICRecAck())
                                       continue;
                                  }
                            IICSendByte((unsigned char)Address);
                            if(IICRecAck())
                            continue;
                            if(!(ControlByte&0x01))
                               {
                                      j=64;                                     
                                  errorflag=0;                      //********clr errorflag
                                 while(j--)
                                    {
                                       IICSendByte(*DataBuff++);
                                       if(!IICRecAck())                          
                                       continue;
                                       errorflag=1;                                   //发送成功不会经过此处
                                       break;
                                     }
                                 if(errorflag==1)
                                 continue;
                                 break;
                              }
                           else
                              {
                                 IICStart();
                                 IICSendByte(ControlByte);
                                 if(IICRecAck())
                                 continue;
                                         j=64;
                                 while(--j)
                                    {
                                       *DataBuff++=IICReceiveByte();
                              IICAck();
                                    }
                                 *DataBuff++=IICReceiveByte();      //read last byte data
                                 IICNoAck();
                                 errorflag=0;
                                 break;
                                 }               
                       }

                IICStop();
                      if(!(ControlByte&0x01))
                         {
                            Delay(255);
                            Delay(255);
                            Delay(255);
                            Delay(255);
                         }       
               Address+=64;
         }
   i=ERROR;
   while(i--)
   {
          IICStart();
          IICSendByte(ControlByte&0xfe);
          if(IICRecAck())
          continue;
          if(enumer>AT2416)
             {
               IICSendByte((unsigned char)(Address>>8));
          if(IICRecAck())
          continue;
             }
          IICSendByte((unsigned char)Address);
          if(IICRecAck())
          continue;
          if(!(ControlByte&0x01))
            {
                      j=m_cell_last;                                     
                errorflag=0;                      //********clr errorflag
                while(j--)
                   {
                     IICSendByte(*DataBuff++);
                     if(!IICRecAck())                          
                     continue;
                     errorflag=1;                                   //发送成功不会经过此处
                     break;
                  }
          if(errorflag==1)
          continue;
          break;
               }
      else
      {
         IICStart();
         IICSendByte(ControlByte);
         if(IICRecAck())
         continue;
         while(--m_cell_last)
            {
                *DataBuff++=IICReceiveByte();
               IICAck();
            }
          *DataBuff=IICReceiveByte();      //read last byte data
          IICNoAck();
          errorflag=0;
          break;
      }               
   }
   IICStop();
   if(!(ControlByte&0x01))
      {
          Delay(255);
          Delay(255);
          Delay(255);
          Delay(255);
      }       

}

void delay10us(void)   //误差-0.053530092593us
{
    unsigned char a,b;
    for(b=1;b>0;b--)
      for(a=52;a>0;a--);
}


void delay4us(void)   //误差-0.042824074074us
{
    unsigned char a,b;
    for(b=17;b>0;b--)
      for(a=1;a>0;a--);
}
/****************以下对IIC总线操作子程序***/
/*****************启动总线**********************/
void IICStart(void)
{ SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平*/
SDA=1; /* 一个“开始”状态,该状态必须在其他命令之前执行 */
SCL=1;
delay10us();
delay10us();
SDA=0;
   delay10us();
   delay10us();
SCL=0;
SDA=1;   
}
/*****************停止总线****************/
void IICStop(void)
{ SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平*/
SDA=0; /*一个“停止”状态,该状态终止所有通讯 */
SCL=1;
   delay10us();
   delay10us();
SDA=1;
delay10us();
delay10us();
SCL=0;
}

/**************检查应答位*******************/
bit IICRecAck(void)
{ SCL=0;
SDA=1;
SCL=1;
   delay10us();
   delay10us();
CY=SDA;   /* 因返回值总是放在CY中 */
SCL=0;
return(CY);
}

/***************对IIC总线产生应答*******************/
void IICACK(void)
{ SDA=0; /* EEPROM通过在收到每个地址或数据之后 */
SCL=1; /*置SDA低电平的方式确认表示收到读SDA状态 */
   delay10us();
   delay10us();
SCL=0;
   delay4us();
   delay10us();
SDA=1;
}

/*****************不对IIC总线产生应答***************/
void IICNoAck(void)
{ SDA=1;
SCL=1;
delay10us();
delay10us();
SCL=0;
}


/*******************向IIC总线写数据*********************/
void IICSendByte(unsigned char sendbyte)
{ unsigned char data j=8;
for(;j>0;j--)
{ SCL=0;
    sendbyte <<= 1; /* 使CY=sendbyte^7; */
    SDA=CY; /* CY 进位标志位 */
    SCL=1;
}
SCL=0;
}
/**********************´从IIC总线上读数据子程序**********/
unsigned char IICReceiveByte(void)
{ register receivebyte,i=8;
SCL=0;
while(i--)
{ SCL=1;
    receivebyte = (receivebyte <<1 ) | SDA;
    SCL=0;
}
return(receivebyte);
}

/***************延迟程序************************/
void Delay(unsigned char DelayCount)
{
while(DelayCount--);
}

void main()
{
unsigned int addr;
unsigned char code buf2;
unsigned char code buf1={
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,41,42,43,44,
45,46,47,48,49,50,51,52,53,54,55,56,57,58,
59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80,81,82,83,84,85,86,
87,88,89,90,91,92,93,94,95,96,97,98,99
};

unsigned char *p1,*p2;
p1=buf1;
p2=buf2;
addr=0;
RW24xx(p1,100,addr,0xa0,AT24256);
delay10us();
delay10us();

addr=0;
RW24xx(p1,100,addr,0xa1,AT24256);
delay10us();
delay10us();
delay10us();
delay10us();
p1=buf2;
P3=buf2;
while(1);
}

2.现在问题是:
1)编译出现3警告:main2.c(346): warning C182: pointer to different objects 指向p1=buf1;p2=buf2;
2)原本是想将buf1中的数据写进AT24C256,因数据会在13K左右,(现在定义是buf1,想先看看),然后读出AT24C256中
   的数据以便应用。(现暂时想读入buf2中看看),然后读buf2中第5个数据给P3口驱动LED(低电平驱动)显示。
3)运行后,现在P3口全是低,软件仿真看到buf2里全是0x00,没有读出到数据,不知问题在那里?

3.请各位高手,帮新手看看问题所在,万分感激!!

Tliang 发表于 2016-5-5 15:43:53

buf1和buf2为数组,你这样给数据他给的是数组的地址,并不是数组中的数据。

Mikle2016 发表于 2016-5-5 17:20:14

就是在这里纠结起的,我也觉得不妥;但要怎样处理呢?谢了!

Mikle2016 发表于 2016-5-6 16:44:46

C语言基础还没学好,找到个例程。

void main(void)

{

//定义花样数据,数据存放在片内 CODE 区中

unsigned char code design[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,

0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,

0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,

0xE7,0xDB,0xBD,0x7E,0xFF};

unsigned int a; //定义循环用的变量

unsigned char b;

unsigned char code * dsi; //定义基于 CODE 区的指针



do{

dsi = &design; //取得数组第一个单元的地址

for (b=0; b<32; b++)

{



}

}while(1);

}

for(a=0; a<30000; a++); //延时一段时间

P1 = *dsi; //从指针指向的地址取数据到 P1 口

dsi++; //指针加一,

mon51 发表于 2016-5-6 20:09:52

它的可用程序20年前就有了。我是不想去找移动硬盘了。还有512的程庁,全却是页写入,自动连接上次尾部。

Mikle2016 发表于 2016-5-7 00:26:58

20年后也有新手呢,高手将代码共享下?

babysnail 发表于 2016-5-7 00:35:13

1. 复习 下C语言的const ,编译器的 code,xdata,idata 等用法.
2.24cxx 读写有问题主要还在时序,学会看时序图,学习根据mcu时钟和周期计算延时,复习i2c相关知识。

Mikle2016 发表于 2016-6-29 17:11:19

经过一段时间,现在可以连续读写了,但还不能页读写,将改动后的程序贴出,以便大家交流。
#include <reg52.h>
#include <INTRINS.H>
sbit   SDA=P2^1;
sbit   SCL=P2^0;

//enumeepromtype{AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};
//enumeepromtype enumer;
unsigned charACK_Error,Txmt_Success;
unsigned charbuf2;
unsigned charbuf1={
0xAA,0x49,0x46,0x46,0x98,0x33,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
0x12,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x40,0x1F,0x00,0x00,0x40,0x1F,0x00,0xAB,
        /*0x01,0x00,0x08,0x00,0x00,0x00,0x64,0x61,0x74,0x61,0x71,0x33,0x00,0x00,0x7F,0x7F,
        0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x80,0x7F,0x80,0x80,0x80,0x80,0x80,0x80,
        0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,*/
};




void delay10us(unsigned char i)
{
   unsigned char j;
do{
j = 40;
do{
   _nop_();
   }while(--j);
}while(--i);
}



/***************????????************************/
void Delay(unsigned char DelayCount)
{
while(DelayCount--);
}



/*****************ÒÔÏÂÊǶÔIIC×ÜÏߵIJÙ×÷×Ó³ÌÐò***/
/*****************Æô¶¯×ÜÏß**********************/
void IICStart(void)
{

SDA=1;               /* Ò»¸ö"¿ªÊ¼"״̬,¸Ã״̬±ØÐëÔÚÆäËûÃüÁî֮ǰִÐÐ*/
SCL=1;            /* SCL´¦Óڸߵçƽʱ,SDA´Ó¸ßµçƽתÏòµÍµçƽ±íʾ*/
delay10us(1);
SDA=0;            //scl need to hold on low
delay10us(1);
SCL=0;

}

/*****************Í£Ö¹IIC×ÜÏß****************/
void IICStop(void)
{

SDA=0;                      /*±íʾһ¸ö"Í£Ö¹"״̬,¸Ã״̬ÖÕÖ¹ËùÓÐͨѶ */
SCL=1;
        delay10us(2);
SDA=1;
delay10us(1);

}

/**************(Ö÷»ú)¼ì²éÓ¦´ðλ*******************/
bit IICRecAck(void)
{
unsigned char value;
SCL=1;
delay10us(1);
if(SDA==1)       
       value=1;
else
       value=0;
SCL=0;
delay10us(1);
return value;
}


/***************£¨Ö÷»ú£©¶ÔIIC×ÜÏß²úÉúÓ¦´ð*******************/
void IICACK(void)
{

SCL=0;                     /* EEPROMͨ¹ýÔÚÊÕµ½Ã¿¸öµØÖ·»òÊý¾ÝÖ®ºó*/
        delay10us(2);
        SDA=1;                     /* ÖÃSDAµÍµçƽµÄ·½Ê½È·ÈϱíʾÊÕµ½¶ÁSDA¿Ú״̬ */
        delay10us(1);
SCL=1;                     
delay10us(2);
delay10us(2);
SCL=0;
        delay10us(2);
       
}

/*****************²»¶ÔIIC×ÜÏß²úÉúÓ¦´ð**************/
void IICNoAck(void)
{
       
SDA=1;
SCL=1;
delay10us(2);
SCL=0;
        delay10us(1);
       

}


/*******************×Ö½ÚдÈë*********************/
void IICSendByte(unsigned char sendbyte)
{
unsigned char j;
       
        for(j=0;j<8;j++)
       {
       if(sendbyte&0x80)
               SDA=1;
       else
               SDA=0;
       sendbyte=sendbyte<<1; //ÒƳöÊý¾ÝµÄ×î¸ßλ
           SCL=1;
       delay10us(1);
       SCL=0;
       delay10us(1);
       }
               
       
}



/********************************×Ö½Ú¶Á³ö**************************************/      
unsigned char IICReceiveByte()
   {
       unsigned char i=8;
       unsigned char ddata=0;
       SDA=1;
       delay10us(1);
       SCL=0;               
       while(i--)
      {
                                        ddata=ddata<<1;
                                        SCL=1;
                                        delay10us(1);
          if(SDA==1)//if SDA=1
          {
                ddata |= 0x01;
          }
         SCL=0;
         delay10us(1);
                                }       
         return ddata;      
   }

/*******************µ¥¸öÊý¾ÝдÈë*********************/
/****************************µØַΪ0x0000-0x1fff*******************************/
voidIICWriteData(unsigned int Address,unsigned char Data)
   {
          unsigned char addr_MSB,addr_LSB;
         addr_MSB=Address>>8;
         addr_LSB=Address & 0x00ff;
         IICStart();
         IICSendByte(0xa0);
                     IICRecAck();
                     IICSendByte(addr_MSB);
                     IICRecAck();
                     IICSendByte(addr_LSB);
                     IICRecAck();
         IICSendByte(Data);
                     IICRecAck();
         IICStop();
         
       }
       

       
       
       /*******************************¶à×Ö½ÚдÈë***************************/
/****************************µØַΪ0x0000-0x1fff*******************************/
/**************************µØÖ·£¬³¤¶È(<255),дÈëÊý¾ÝÄÚÈÝ**********************      
voidFRAM_Multi_Data_Write(unsigned int Address,unsigned char Length,unsigned char *ptr)
   {
         unsigned char addr_MSB;
         unsigned char addr_LSB;
         unsigned char i;
         //CLI();
         Length=Length-1;
         addr_MSB=Address>>8;
         addr_LSB=Address & 0x00ff;
         IICStart();
         IICSendByte(0xa0);
         IICRecAck();
         IICSendByte(addr_MSB);
         IICRecAck();
         IICSendByte(addr_LSB);
         IICRecAck();
         for(i=0;i<Length;i++)
         {
                   IICSendByte(*ptr);
                   IICRecAck();
                   ptr++;
         }
         IICSendByte(*ptr);
         IICRecAck();
         IICStop();
         //SEI();
   } */



/****************************µ¥¸ö×Ö½ÚÊý¾Ý¶ÁÈ¡****************************/

unsigned char IICReadData(unsigned int Address)

   {
      unsigned char addr_MSB;
      unsigned char addr_LSB;
      unsigned char ch;
      //CLI();
      addr_MSB=Address>>8;
      addr_LSB=Address&0x00ff;
      IICStart();
                  IICSendByte(0xa0);
                  IICRecAck();
                  IICSendByte(addr_MSB);
                  IICRecAck();
                  IICSendByte(addr_LSB);
                  IICRecAck();
      IICStart();
              IICSendByte(0xa1);
              IICRecAck();
                  ch=IICReceiveByte();
                                //IICACK();
                  IICNoAck();
                  IICStop();
      return ch;
}
               
void IICWritePageData(unsigned int Address,unsigned int Length,unsigned char *p1)
{
unsigned char i;
        unsigned char addr_MSB;
unsigned char addr_LSB;
              Length=Length-1;
              addr_MSB=Address>>8;
      addr_LSB=Address&0x00ff;
              delay10us(1);
      IICStart();
                  IICSendByte(0xa0);
                  IICRecAck();
              delay10us(1);
                  IICSendByte(addr_MSB);
                  IICRecAck();
                  IICSendByte(addr_LSB);
                  IICRecAck();
              for(i=0;i<Length;i++)
             {
                                        IICSendByte(*p1);
                                        IICRecAck();
                                  p1++;
                               }
                               IICSendByte(*p1);
         IICRecAck();
                               IICStop();
}
/****************************Á¬ÐøÊý¾Ý¶Á³ö********************************/
/******************Èç¹û¶ÁÈ¡Ò»¸ö,Length¾ÍΪ1***********************************/
/***********************µØÖ·£¬¶ÁÈ¡×Ö½ÚÊý(<255),¶ÁÈ¡µÄÄÚÈÝ*********************/
void IICReadPageData(unsigned int Address,unsigned int Length,unsigned char *p)
   {
      unsigned char addr_MSB;
      unsigned char addr_LSB;
      unsigned int i;
      addr_MSB = Address>>8;
      addr_LSB = Address & 0x00ff;
                  delay10us(1);
      IICStart();
      IICSendByte(0xa0);
      IICRecAck();
                  delay10us(1);
      IICSendByte(addr_MSB);
      IICRecAck();
      IICSendByte(addr_LSB);
      IICRecAck();
      IICStart();
      IICSendByte(0xa1);
      IICRecAck();
      for(i=0;i<Length;i++)
      {   
                                       
         *p=IICReadData(Address);
                                       Address++;
                                       buf2=*p++;
                                       
                                          if(i==(Length-1))
                                                        IICNoAck();
                                                else
                                          IICACK();
                                }
      IICStop();
      
   }
       


void init()
{
      SDA=1;
      Delay(1);
      SCL=1;
      Delay(1);
}


void main()
{
       
unsigned int Address,Length;
unsigned char *p1;
unsigned char *p2;
init();
      
p1=buf1;
        p2=buf2;
Length=32;
Address=0;
IICWritePageData(Address,Length,p1);                  
               
Delay(255);
        Delay(255);
        Delay(255);
        Delay(255);
        Delay(255);
        Delay(255);
        Delay(255);
        Delay(255);


Length=32;
Address=0;

IICReadPageData(Address,Length,p2);

           P3=buf2;
               Delay(255);
   Delay(255);
               Delay(255);
   Delay(255);
       
}

Mikle2016 发表于 2016-6-29 17:13:54

桌面\2.jpg

gfy200866 发表于 2016-6-30 09:05:21

基本时序搞定,后面就问题不大了。先简后繁

Mikle2016 发表于 2016-7-1 09:32:55

Protues8仿真图片

本帖最后由 Mikle2016 于 2016-7-1 09:35 编辑

D\2.jpg

小李非刀 发表于 2016-7-1 15:06:18

写得这么复杂,I2C是简单协议,什么MCU只要按其时序写,无任何问题。

Mikle2016 发表于 2016-7-15 09:55:30

楼上只说不写,可否贴出页写的程序让大家学习下?

549646150 发表于 2016-7-15 14:46:42

这么一大啪啦程序,没人有耐心给你找毛病的。而且,22M的时钟,只有STC的增强系列才支持,并且时序与传统的51不一样,因为89c51的机器周期是STC12C5A的6倍,这个对软件延时的影响尤为明显

Mikle2016 发表于 2016-8-8 22:11:10

不会吧。最后贴的程序,在22.1184MHz已经可以读写一页了,只是还不能读写第二也,应该没什么难的了吧,只是判断下就可以了。
页: [1]
查看完整版本: (求助)用51读写AT24C256问题