歡迎您光臨本站 登入註冊首頁

AT24C01-AT24C256 的Keil C51讀寫程序

admin @ 2014-03-25 , reply:0

概述

/*以下為AT24C01~AT24C256的讀寫程序,各人可根據自己的需要應用。在buf1中填入需要寫入的內容,buf2的大小可根據需要定義。addr可根據使用的晶元選擇,可從任何位置讀寫,只要在該晶……

/* 以下為AT24C01~AT24C256的讀寫程序,各人可根據自己的需要應用。
在buf1中填入需要寫入的內容,buf2的大小可根據需要定義。
addr可根據使用的晶元選擇,可從任何位置讀寫,只要在該晶元的範圍內。
enumer=ATxxx,根據使用的晶元賦值。各函數中的形式參數不需改變。
本程序只要在調用的程序中定義實際參數即可,下述各子程序不必改動。*/

#include
#include
#define  ERROR 10     //允許ERROR的最大次數      
sbit     SDA=P3^0;
sbit     SCL=P3^1;
enum  eepromtype {AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};/*器件的型號*/
enum  eepromtype enumer;   //定義一個枚舉變數
unsigned char code buf1 []={1,3,5,7,9,10,11,12,13,15}; /* 發送緩衝區 */
unsigned char buf2 [10]; /* 接收緩衝區 */

/* 一個通用的24C01-24C256共9種EEPROM的位元組讀寫操作程序,
此程序有五個入口條件,分別為讀寫數據緩衝區指針,
進行讀寫的位元組數,EEPROM首址,EEPROM控制位元組,
以及EEPROM類型。此程序結構性良好,具有極好的容錯性,程序機器碼也不多:
DataBuff為讀寫數據輸入/輸出緩衝區的首址
Length 為要讀寫數據的位元組數量
Addr 為EEPROM的片內地址 AT24256為0~32767
Control 為EEPROM的控制位元組,具體形式為(1)(0)(1)(0)(A2)(A1)(A0)(R/W),其中R/W=1,
表示讀操作,R/W=0為寫操作,A2,A1,A0為EEPROM的頁選或片選地址;
enumer為枚舉變數,需為AT2401至AT24256中的一種,分別對應AT24C01至AT24C256;
函數返回值為一個位變數,若返回1表示此次操作失效,0表示操作成功;
ERROR為允許最大次數,若出現ERRORCOUNT次操作失效后,則函數中止操作,並返回1
SDA和SCL由用戶自定義,這裡暫定義為P3^0和P3^1; */
/*對於1K位,2K位,4K位,8K位,16K位晶元採用一個8位長的位元組地址碼,對於32K位以上
的採用2個8位長的位元組地址碼直接定址,而4K位,8K位,16K位配合頁面地址來定址*/

/* -----  AT24C01~AT24C256 的讀寫程序 ------ */
bit   RW24xx(unsigned char *DataBuff,unsigned char Length,unsigned int Addr,
                     unsigned char Control,enum eepromtype enumer)
{ void Delay(unsigned char DelayCount);  /*   延時   */
  void Start(void);  /*   啟動匯流排   */
  void Stop(void);   /*   停止IIC匯流排   */
  bit  RecAck(void); /*   檢查應答位   */
  void NoAck(void);  /*   不對IIC匯流排產生應答   */
  void Ack(void);    /*   對IIC匯流排產生應答   */
  unsigned char Receive(void); /*   從IIC匯流排上讀數據子程序  */
  void Send(unsigned char sendbyte); /*   向IIC匯流排寫數據   */
  unsigned char data j,i=ERROR;
  bit errorflag=1;  /*   出錯標誌   */
  while(i--)
  { Start();  /*   啟動匯流排   */
    Send(Control & 0xfe); /*   向IIC匯流排寫數據,器件地址 */
    if(RecAck()) continue; /*   如寫不正確結束本次循環   */
    if(enumer > AT2416)
    { Send((unsigned char)(Addr >> 8));//把整型數據轉換為字元型數據:棄高取低,只取低8位.如果容量大於32K位,使用16位地址定址,寫入高八位地址
      if(RecAck())  continue;
    }
    Send((unsigned char)Addr); /*   向IIC匯流排寫數據   */
    if(RecAck())  continue; /*   如寫正確結束本次循環   */
    if(!(Control & 0x01))   //判斷是讀器件還是寫器件
    { j=Length;
      errorflag=0;         /* 清錯誤特徵位 */
      while(j--)
      { Send(*DataBuff++); /*   向IIC匯流排寫數據   */
        if(!RecAck()) continue; /*   如寫正確結束本次循環   */
        errorflag=1;
        break;
      }
      if(errorflag==1) continue;
      break;
    }
    else
    { Start();  /*   啟動匯流排   */
      Send(Control); /*   向IIC匯流排寫數據   */
      if(RecAck()) continue;//器件沒應答結束本次本層循環
      while(--Length)  /*   位元組長為0結束   */
      { *DataBuff ++= Receive();
        Ack();   /*   對IIC匯流排產生應答   */
      }
      *DataBuff=Receive(); /* 讀最後一個位元組 */
      NoAck();  /*   不對IIC匯流排產生應答   */
      errorflag=0;
      break;
    }
  }
  Stop();  /*   停止IIC匯流排   */
  if(!(Control & 0x01))
  { Delay(255); Delay(255); Delay(255); Delay(255);
  }
  return(errorflag);
}

/* * * * * 以下是對IIC匯流排的操作子程序 * * * * */
/* * * * * * 啟動匯流排 * * * * */
void Start(void)
{ SCL=0; /* SCL處於高電平時,SDA從高電平轉向低電平表示 */
  SDA=1; /* 一個"開始"狀態,該狀態必須在其他命令之前執行 */
  SCL=1;
  _nop_(); _nop_(); _nop_();
  SDA=0;
  _nop_(); _nop_(); _nop_(); _nop_();
  SCL=0;
  SDA=1;    
}

/* * * * * 停止IIC匯流排 * * * * */
void Stop(void)
{ SCL=0; /*SCL處於高電平時,SDA從低電平轉向高電平 */
  SDA=0; /*表示一個"停止"狀態,該狀態終止所有通訊 */
  SCL=1;
  _nop_(); _nop_(); _nop_(); /* 空操作 */
  SDA=1;
  _nop_(); _nop_(); _nop_();
  SCL=0;
}

/* * * * * 檢查應答位 * * * * */
bit RecAck(void)
{ SCL=0;
  SDA=1;
  SCL=1;
  _nop_(); _nop_(); _nop_(); _nop_();
  CY=SDA;     /* 因為返回值總是放在CY中的 */
  SCL=0;
  return(CY);
}

/* * * * *對IIC匯流排產生應答 * * * * */
void Ack(void)
{ SDA=0; /* EEPROM通過在收到每個地址或數據之後, */
  SCL=1; /* 置SDA低電平的方式確認表示收到讀SDA口狀態 */
  _nop_(); _nop_(); _nop_(); _nop_();
  SCL=0;
  _nop_();
  SDA=1;
}

/* * * * * * * * * 不對IIC匯流排產生應答 * * * * */
void NoAck(void)
{ SDA=1;
  SCL=1;
  _nop_(); _nop_(); _nop_(); _nop_();
  SCL=0;
}

/* * * * * * * * * 向IIC匯流排寫數據 * * * * */
void Send(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 Receive(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--);
}

/* -----  AT24C01~AT24C256 的讀寫程序 ------ */
void main()
{ unsigned char Control,*p1,*p2;
  unsigned char Length;
  unsigned int addr ; /* 24Cxx片內地址 */
  p1=buf1;p2=buf2;
  addr=0; /* 片內地址 AT24C256為0~32767 */
  Length=8; /* 讀寫長度 */
  enumer=AT24256; /* 讀寫AT24C256 */
  Control=0xa0; /* 寫操作 */
  RW24xx(p1,Length,addr,Control,enumer); /* 寫 */
  Control=0xa1; /* 讀操作 */
  RW24xx(p2,Length,addr,Control,enumer); /* 讀 */
}


[admin via 研發互助社區 ] AT24C01-AT24C256 的Keil C51讀寫程序已經有4225次圍觀

http://cocdig.com/docs/show-post-42105.html