24C02、24C16進行字節、頁讀取、頁存取操作

以下這篇文章是自己折騰了三天存儲芯片後,並且能夠成功進行字節操作、頁操作的一篇應用型文章,不太想研究原理的可以直接採用本文的代碼和注意事項。 

在對24C02或者24C16進行字節、頁讀取、頁存取前,我們需要弄清楚I²C協議、24C02/24C16存儲空間字節操作頁操作的時序

  • I²C協議:I²C是什麼協議網上進行百度方可知道,以下只寫使用代碼
void i2cStart(void)            //開始時序
{
  SDA=1;
  SCL=1;
  _delay(2);  //延時2μs
  SDA=0;
  _delay(2); 
  SCL=0;
}

void i2cStop(void)            //結束時序
{
  SDA=0;
  _delay(2);
  SCL=1;
  _delay(2);
  SDA=1;
}

void i2cAck_MCU(void)        //應答時序
{
  SDA=0;
  _delay(2);
  SCL=1;
  _delay(2);
  SCL=0;
  _delay(2);
  SDA=1;
  _delay(4);
}


void i2cNoAck_MCU(void)      //非應答時序
{
  SDA=1;
  _delay(2);
  SCL=1;
  _delay(2);
  SCL=0;
  _delay(2);
}
  • 24C02/24C16存儲空間大小

24C02就是有2Kbit = 2000/8 = 250個字節,24C16就是有16kbit  = 2000個字節,24C02一頁最多可以寫入8個字節,因此可以分成32頁,24C16一頁最多可以寫入16個字節,因此可以分成128頁。

  • 字節寫操作
    void WriteByte_24LC16B(unsigned char input)
    {
      unsigned char bit_count;
      for(bit_count=8;bit_count!=0;bit_count--)
      {
        _delay(2);
        SDA=(_Bool)(input&0x80);
        _delay(2);
        SCL=1;
        _delay(2);
        SCL=0;
        input=input<<1;
        _delay(2);
      }
      SDA=1;
      SDA_CTRL=1;	//這裏需要看自己使用的芯片設置SDA的IO口爲輸入狀態,我用的是HT45F67芯片,SDA端口設置爲輸入狀態,用於判斷SDA是否接到主機的應答信號
      _delay(2);
      SCL=1;
      _delay(2);
      if(SDA == 1)
      	ack = 0;
      else
        ack = 1;
      SCL=0;
      SDA_CTRL=0;    //此處根據自己所使用的芯片將SDA所在的Io口設置爲輸出狀態
    }
    
    void Write_24LC16B(unsigned char Wdata,unsigned int RomAddress)
    {
      unsigned char block;
      WriteDeviceAddress=0B10100000;
      block=RomAddress/256;
      RomAddress=RomAddress%256;
      WriteDeviceAddress=WriteDeviceAddress|(block<<1);
      i2cStart();
      WriteByte_24LC16B(WriteDeviceAddress);
      WriteByte_24LC16B((unsigned char)RomAddress);
      WriteByte_24LC16B(Wdata);
      i2cStop();
      _delay(5500);
    }

    字節讀操作

  • unsigned char ReadByte_24LC16B()
    {
      unsigned char bit_count,rbyte=0;
      SDA=1;
      SDA_CTRL=1;
      _delay(10);
      for(bit_count=8;bit_count!=0;bit_count--)
      {
        rbyte=rbyte<<1;
        _delay(2);
        SCL=1;
        rbyte=rbyte|((unsigned char)(SDA));
        _delay(2);
        SCL=0;
        _delay(2);
      }
      SDA_CTRL=0;
      return(rbyte);
    }
    
    
    unsigned char Read_24LC16B(unsigned int RomAddress)
    {
      unsigned char output,block;
      ReadDeviceAddress=0B10100001;
      WriteDeviceAddress=0B10100000;
      block=RomAddress/256;
      RomAddress=RomAddress%256;
      WriteDeviceAddress=WriteDeviceAddress|(block<<1);
      ReadDeviceAddress=ReadDeviceAddress|(block<<1);
      i2cStart();
      WriteByte_24LC16B(WriteDeviceAddress);
      WriteByte_24LC16B((unsigned char)RomAddress);
      i2cStart();
      WriteByte_24LC16B(ReadDeviceAddress);
      output=ReadByte_24LC16B();
      i2cNoAck_MCU();
      i2cStop();
      _delay(2000);
      return(output);  
    }

    頁寫操作

    Wdata爲輸入數組的首地址,RomAddress爲需要進行存儲的地址,範圍在0~2047之間,cnt爲一次需要寫入的字節個數,建議採用8的倍數的cnt,因爲本函數不採用自動分頁,不是8的倍數會在超出頁寫入最多的字節數之後覆蓋掉原來的數。
    void WritePage_24LC16B(unsigned char *Wdata,unsigned int RomAddress,unsigned char cnt)
    {
      unsigned char block;
      WriteDeviceAddress=0B10100000;
      block=RomAddress/256;
      RomAddress=RomAddress%256;
      WriteDeviceAddress=WriteDeviceAddress|(block<<1);
      i2cStart();
      WriteByte_24LC16B(WriteDeviceAddress);
      WriteByte_24LC16B((unsigned char)RomAddress);
      while(cnt--)
      {
      	WriteByte_24LC16B(*Wdata++);
      }
      i2cStop();
    }
    
    注意:連續進行多頁寫操作,需要在WritePage_24LC16B函數後添加150μs以上的延遲,這段時間,24C02內部需要將數據存儲到芯片內部。
    例子:
    D_buffer[8] = {1,2,3,4,5,6,7,8};
    WritePage_24LC16B(D_buffer,0,8);
    _delay(150);        //延遲150μs以及以上
    WritePage_24LC16B(D_buffer,8,8);
    

     

  • 頁讀操作

  • void ReadPage_24LC16B(unsigned char *Rdata,unsigned int RomAddress,unsigned char cnt)
    {
      unsigned char block;
      ReadDeviceAddress=0B10100001;
      WriteDeviceAddress=0B10100000;
      block=RomAddress/256;
      RomAddress=RomAddress%256;
      WriteDeviceAddress=WriteDeviceAddress|(block<<1);
      ReadDeviceAddress=ReadDeviceAddress|(block<<1);
      i2cStart();
      WriteByte_24LC16B(WriteDeviceAddress);
      WriteByte_24LC16B((unsigned char)RomAddress);
      i2cStart();
      WriteByte_24LC16B(ReadDeviceAddress);
      while(cnt>1)
      {
      	*Rdata++ = ReadByte_24LC16B();
      	cnt--;
      	i2cAck_MCU();			//發送完讀地址後,需要應答一下
      }
      *Rdata = ReadByte_24LC16B();
      i2cNoAck_MCU();			//讀取最後一個字節需要非應答
      i2cStop();
      _delay(2000);
    }

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章