一個通用的24C01-24C256共9種EEPROM的位元組讀寫操作程式,此程式有五個允入準則,分別為讀寫資料緩衝區指標,進行讀寫的位元組數,EEPROM首址,EEPROM控制位元組,以及EEPROM類型。此程式結構性良好,具有極好的容錯性,程式機器碼也不多:DataBuff為讀寫資料輸入/輸出緩衝區的首址Length 為要讀寫資料的位元組數量Addr 為EEPROM的片內地址 AT24256為0~32767Control 為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由使用者自訂,對於1K位,2K位,4K位,8K位,16K位晶片採用一個8位長的位元組地址碼,對於32K位以上的採用2個8位長的位元組地址碼直接定址,而4K位,8K位,16K位配合頁面地址來定址。
#include <intrins.h>#define ERROR 10 //允許ERROR的最大次數 sbit SDA=P4^2;sbit SCL=P4^4;enum eepromtype {AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};/*器件的型號*/enum eepromtype enumer; //定義一個枚舉變數unsigned char buf1[]="aaaaaaaaaa"; /* 發送緩衝區 */unsigned char buf2 [12]; /* 接收緩衝區 */void senddd(unsigned d1);/* * * * * * * * 一個簡單延時程式 * * * * * * * * * * * * */void Delay(unsigned char DelayCount){ while(DelayCount--);}/* * * * * 以下是對IIC匯流排的操作子程式 * * * * *//* * * * * * 啟動匯流排 * * * * */void Start(void){ SCL=0; /* SCL處於高電平時,SDA從高電平轉向低電平表示 */ SDA=1; /* 一個"開始"狀態,該狀態必須在其他命令之前執行 */ Delay(1); SCL=1; Delay(1); SDA=0; Delay(1); SCL=0; SDA=1; Delay(1); }/* * * * * 停止IIC匯流排 * * * * */void Stop(void){ SCL=0; /*SCL處於高電平時,SDA從低電平轉向高電平 */ SDA=0; /*表示一個"停止"狀態,該狀態終止所有通訊 */ Delay(1); SCL=1; Delay(1); /* 空操作 */ SDA=1; Delay(1); SCL=0; Delay(1000);}/* * * * * 檢查應答位 * * * * */bit RecAck(void){ SCL=0; SDA=1; Delay(20); SCL=1; Delay(1); Delay(1); CY=SDA; /* 因為傳回值總是放在CY中的 */ SCL=0; Delay(20); return(CY);}/* * * * *對IIC匯流排產生應答 * * * * */void Ack(void){ SDA=0; /* EEPROM通過在收到每個地址或資料之後, */ SCL=1; /* 置SDA低電平的方式確認表示收到讀SDA口狀態 */ Delay(1); SCL=0; Delay(1); SDA=1;}/* * * * * * * * * 不對IIC匯流排產生應答 * * * * */void NoAck(void){ SDA=1; SCL=1; Delay(1); 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 進位標誌位 */Delay(1); SCL=1;Delay(20); } SCL=0; Delay(1);}/* * * * * * * * * 從IIC匯流排上讀資料子程式 * * * * */unsigned char Receive(void){ register receivebyte,i=8; SCL=0; while(i--) { SCL=1; receivebyte = (receivebyte <<1 ) | SDA;Delay(1); SCL=0;Delay(1); } return(receivebyte);}/* ----- AT24C01~AT24C256 的讀寫程式 ------ */bit RW24xx(unsigned char *DataBuff,unsigned char Length,unsigned int Addr, unsigned char Control,enum eepromtype enumer){ 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); } return(errorflag);}
下面是主函數:
#include <REG52.H>#include "24c256_1.h"#include<string.h>unsigned char temp[64];unsigned char rxnum;unsigned char flag2;void senddd(unsigned d1);void uart(void) interrupt 4// 串口中斷{unsigned char k = 0;if(RI) //接收{}else//發送{TI=0;}} //查詢方式發送單個字元void senddd(unsigned d1){ ES=0; //TE=1;TI=0;SBUF=d1;while(!TI);//TE=0;TI=0; ES=1; }//Send String Tor Uartvoid printu(char * str){ char *ct = str;while (*ct != '\0'){if (*ct == '\n'){SBUF = 13;while (!TI);TI = 0;}SBUF=*ct;while (!TI);TI = 0;ct++;}}//UART初始化void initUart(void){TMOD &=0x0f; TMOD |=0x20; SCON=0x50; IP = 0x10;//PCON|=0x80;TH1=0xf7; TL1=0xf7; //115200,normal//TH1=0xfa; TL1=0xfa; //倍速 TR1=1; ET1=0; RI=0; //AUXR = 0xA0;//TE=0; //允許接收 僅485時用。}void main(void){ unsigned char Control,*p1,*p2; unsigned char Length; unsigned int addr ,i; /* 24Cxx片內地址 */ P4SW|= 0x10; initUart();ES =1;ET1=0;EA =1;senddd('O');senddd('N'); printu(" starting...\r\n"); p1=buf1;p2=buf2; printu(p1); printu("\r\n"); addr=0; ////片內地址 AT24C256為0~32767///// Length=10; ////// 讀寫長度 ////// enumer=AT24256; /// 讀寫AT24C256//// Control=0xa0; /// 寫操作/// RW24xx(p1,Length,addr,Control,enumer); // 寫 // Control=0xa1; ///讀操作/// for(i=0;i<10000;i++); //要加入延時···才可正確的讀取資料! // Delay(1000);//1:6.18us; 2:8.36us 3:10.55us △=2.18us RW24xx(p2,Length,addr,Control,enumer);// 讀 printu(p2); printu("\r\n");}
下面是運行結果: