24C02

来源:互联网 发布:淘宝回收手机是真的吗 编辑:程序博客网 时间:2024/05/17 06:33
AT24C02内部设有一个8位控制寄存器,其每一位的含义如下: Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0  1    0    1    0    A2   A1   A0  R/W 其中前4位数据是芯片固定的标识,A2/A1/A0用于选择总线上待访问的I2C器件,R/W=1读操作,R/W=0写操作;I2C总线上最多可以扩展8片同样的2K容量EEPROM存储器,或者是44Kb的EEPROM,或者是2片容量为8Kb的EEPROM存储器。或者是1片容量为16Kb的EEPROM存储器(此时硬件就固定了,因为A2/A1/A0已经被P2P1P0占用),如果扩展82K以内容量的EEPROM存储器,每片存储器将对应一个地址,我们的实验板上的AT24C02的A2/A1/A0引脚全部接地,所以在实验中读写控制字分别为:0xa1/0xa0    #include       #include "MY51.H"      sbit sda=P2^0;      //总线连接口定义      sbit scl=P2^1;      //总线连接口定义      void delayus()  //需要4个机器周期,大概4.34us      {          ;                   //晶振频率11.0592M,机器周期为1.085微秒      }      void iic_start()  //启动信号      {          sda=1;          scl=1;          delayus();      //sda和scl同为高电平保持4.7us以上          _nop_();            //1.085us,共5.78us,下面sda=0是下降沿,不能计算在延时时间中          sda=0;          //下降沿          delayus();      //sda低电平保持4us以上 ,这里是4.34us满足要求      }      void iic_stop() //停止信号      {          sda=0;_nop_();  //准备状态          scl=1;          delayus();      //该状态稳定时间要求保持4us以上          sda=1;          //scl高电平期间,sda来一个上升沿          delayus();      //sda保持4.7us以上,4.34加上函数返回时间大于4.7us                              //注:此时scl和sda都为1          }      void iic_sendByte(uchar byteData) //mcu发送一个字节      {          uchar i;          uchar temp=byteData;          for(i=0;i<8;i++)          {              temp=temp<<1;   //移动后最高位到了PSW寄存器的CY位中              scl=0;           //准备              _nop_();            //稳定一下              sda=CY;          //将待发送的数据一位位的放到sda上              _nop_();              scl=1;           //每一个高电平期间,ic器件都会将数据取走              _nop_();                  }          scl=0;              //如果写成scl=1;sda=1就是停止信号,不能这么写          _nop_();                          sda=1;              //释放总线,数据总线不用时要释放          _nop_();      }          uchar iic_readByte() //读一个字节      {          uchar i,temp;          scl=0;              //准备读数据          _nop_();          sda=1;              //释放总线          _nop_();          for(i=0;i<8;i++)          {              scl=1;          //mcu开始取数据              delayus();      //scl为高电平后,ic器件就会将1位数据送到sda上                                  //总共用时不会大于4.34us的,然后就可以让mcu读sda了            temp=(temp<<1)|sda; //读一位保存到temp中              scl=0;              delayus();                }          return temp;      }      bool iic_checkACK()     //处理应答信号      {          uchar errCounts=255; //定义超时量为255次          scl=1;          _nop_();                    while(sda)          {   //在一段时间内检测到sda=0的话认为是应答信号              if(0==errCounts)              {                  scl=0;        //钳住总线                  _nop_();                  return false; //没有应答信号              }              errCounts--;          }                scl=0;            //钳住总线,为下1次通信做准备           _nop_();          return true;      //成功处理应答信号      }      void iic_init() //总线初始化      {          scl=1;          sda=1;          delayus();      }      void iic_sendACK(bool b_ACK)    //发送应答或非应答信号      {          scl=0;          //准备          _nop_();          if(b_ACK)       //ACK          {              sda=0;          }          else               //unACK          {              sda=1;          }          _nop_();          scl=1;          delayus();      //大于4us的延时          scl=0;              //钳住scl,以便继续接收数据              _nop_();      }      void AT24C02_writeByte(uchar address,uchar dataByte)//向24c02写一字节数据      {      iic_start();      iic_sendByte(0xa0);//mcu写控制字,前4位固定1010,后三位地址0,末位0是写      iic_checkACK();        //mcu处理应答信号      iic_sendByte(address);  //准备在指定地址处写入          iic_checkACK();      iic_sendByte(dataByte); //写数据      iic_checkACK();      iic_stop();      delayms(2);       //按字节写入时,24c02在接收到停止信号后将数据擦写到内部,这需要时间      //并且在这段时间内不会响应总线上的任何请求,故让mcu有2毫秒以上的等待     }  void AT24C02_writeData(uchar address,uchar numBytes,uchar* buf)//写入任意长度数据  {      while(numBytes--)      {          AT24C02_writeByte(address++,*buf++);      }  }  void AT24C02_readData(uchar beginAddr,uchar dataSize,uchar* buf)//读取任意长度字节  {      iic_start();                    //起始信号      iic_sendByte(0xa0);         //控制字,写      iic_checkACK();             //处理应答信号      iic_sendByte(beginAddr);    //发送地址      iic_checkACK();             //处理应答信号          iic_start();                //发送起始信号      iic_sendByte(0xa1);         //控制字,读      iic_checkACK();             //处理应答信号      while(dataSize--)               //读取dataSize个字节      {          *buf++=iic_readByte();  //读取一个个字节并保存到缓冲区buf中          iic_sendACK(dataSize);  //发送应答,当dataSize为0时发送非应答      }      iic_stop();                     //发送停止信号  }  void main()  {      uchar buf[2];                   //接受数据的缓冲区      uchar arr[34]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,               //0x00-0x0f                          16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,//0x10-0x1f    32,0x55};                                                   //0x20-0x21      iic_init();                                         //总线初始化      //AT24C02_writeByte(0x08,0x11);             //向指定地址处写入一个字节数据,代码测试      AT24C02_writeData(0x00,sizeof(arr),arr);    //向指定地址处开始写入34字节的数据      AT24C02_readData(0x20,sizeof(buf),buf);   //从指定地址开始读2个字节      P1=buf[1];  //buf中的第二个元素就是arr中的最后一个数据0x55      while(1){P1=~P1;delayms(500);} //将这个0x55用led灯显示出来10101010变化  }  
原创粉丝点击