|
#include <reg52.h> #include <intrins.h> #define ERROR 10 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}; /* 發(fā)送緩沖區(qū) */ unsigned char buf2 [10]; /* 接收緩沖區(qū) */
/* 一個通用的24C01-24C256共9種EEPROM的字節(jié)讀寫操作程序, 此程序有五個入口條件,分別為讀寫數(shù)據(jù)緩沖區(qū)指針, 進(jìn)行讀寫的字節(jié)數(shù),EEPROM首址,EEPROM控制字節(jié), 以及EEPROM類型。此程序結(jié)構(gòu)性良好,具有極好的容錯性,程序機(jī)器碼也不多: DataBuff為讀寫數(shù)據(jù)輸入/輸出緩沖區(qū)的首址 Length 為要讀寫數(shù)據(jù)的字節(jié)數(shù)量 Addr 為EEPROM的片內(nèi)地址 AT24256為0~32767 Control 為EEPROM的控制字節(jié),具體形式為(1)(0)(1)(0)(A2)(A1)(A0)(R/W),其中R/W=1, 表示讀操作,R/W=0為寫操作,A2,A1,A0為EEPROM的頁選或片選地址; enumer為枚舉變量,需為AT2401至AT24256中的一種,分別對應(yīng)AT24C01至AT24C256; 函數(shù)返回值為一個位變量,若返回1表示此次操作失效,0表示操作成功; ERROR為允許最大次數(shù),若出現(xiàn)ERRORCOUNT次操作失效后,則函數(shù)中止操作,并返回1 SDA和SCL由用戶自定義,這里暫定義為P3^0和P3^1; */
/* ----- 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); /* 檢查應(yīng)答位 */ void NoAck(void); /* 不對IIC總線產(chǎn)生應(yīng)答 */ void Ack(void); /* 對IIC總線產(chǎn)生應(yīng)答 */ unsigned char Receive(void); /* 從IIC總線上讀數(shù)據(jù)子程序 */ void Send(unsigned char sendbyte); /* 向IIC總線寫數(shù)據(jù) */ unsigned char data j,i=ERROR; bit errorflag=1; /* 出錯標(biāo)志 */ while(i--) { Start(); /* 啟動總線 */ Send(Control & 0xfe); /* 向IIC總線寫數(shù)據(jù) */ if(RecAck()) continue; /* 如寫正確結(jié)束本次循環(huán) */ if(enumer > AT2416) { Send((unsigned char)(Addr >> 8)); if(RecAck()) continue; } Send((unsigned char)Addr); /* 向IIC總線寫數(shù)據(jù) */ if(RecAck()) continue; /* 如寫正確結(jié)束本次循環(huán) */ if(!(Control & 0x01)) { j=Length; errorflag=0; /* 清錯誤特征位 */ while(j--) { Send(*DataBuff++); /* 向IIC總線寫數(shù)據(jù) */ if(!RecAck()) continue; /* 如寫正確結(jié)束本次循環(huán) */ errorflag=1; break; } if(errorflag==1) continue; break; } else { Start(); /* 啟動總線 */ Send(Control); /* 向IIC總線寫數(shù)據(jù) */ if(RecAck()) continue; while(--Length) /* 字節(jié)長為0結(jié)束 */ { *DataBuff ++= Receive(); Ack(); /* 對IIC總線產(chǎn)生應(yīng)答 */ } *DataBuff=Receive(); /* 讀最后一個字節(jié) */ NoAck(); /* 不對IIC總線產(chǎn)生應(yīng)答 */ 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從高電平轉(zhuǎn)向低電平表示 */ SDA=1; /* 一個"開始"狀態(tài),該狀態(tài)必須在其他命令之前執(zhí)行 */ SCL=1; _nop_(); _nop_(); _nop_(); SDA=0; _nop_(); _nop_(); _nop_(); _nop_(); SCL=0; SDA=1; }
/* * * * * 停止IIC總線 * * * * */ void Stop(void) { SCL=0; /*SCL處于高電平時,SDA從低電平轉(zhuǎn)向高電平 */ SDA=0; /*表示一個"停止"狀態(tài),該狀態(tài)終止所有通訊 */ SCL=1; _nop_(); _nop_(); _nop_(); /* 空操作 */ SDA=1; _nop_(); _nop_(); _nop_(); SCL=0; }
/* * * * * 檢查應(yīng)答位 * * * * */ bit RecAck(void) { SCL=0; SDA=1; SCL=1; _nop_(); _nop_(); _nop_(); _nop_(); CY=SDA; /* 因?yàn)榉祷刂悼偸欠旁贑Y中的 */ SCL=0; return(CY); }
/* * * * *對IIC總線產(chǎn)生應(yīng)答 * * * * */ void Ack(void) { SDA=0; /* EEPROM通過在收到每個地址或數(shù)據(jù)之后, */ SCL=1; /* 置SDA低電平的方式確認(rèn)表示收到讀SDA口狀態(tài) */ _nop_(); _nop_(); _nop_(); _nop_(); SCL=0; _nop_(); SDA=1; }
/* * * * * * * * * 不對IIC總線產(chǎn)生應(yīng)答 * * * * */ void NoAck(void) { SDA=1; SCL=1; _nop_(); _nop_(); _nop_(); _nop_(); SCL=0; }
/* * * * * * * * * 向IIC總線寫數(shù)據(jù) * * * * */ void Send(unsigned char sendbyte) { unsigned char data j=8; for(;j>0;j--) { SCL=0; sendbyte <<= 1; /* 使CY=sendbyte^7; */ SDA=CY; /* CY 進(jìn)位標(biāo)志位 */ SCL=1; } SCL=0; }
/* * * * * * * * * 從IIC總線上讀數(shù)據(jù)子程序 * * * * */ 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片內(nèi)地址 */ p1=buf1;p2=buf2; addr=0; /* 片內(nèi)地址 AT24C256為0~32767 */ Length=8; /* 讀寫長度 */ enumer=AT24256; /* 讀寫AT24C256 */ Control=0xa0; /* 寫操作 */ RW24xx(p1,Length,addr,Control,enumer); /* 寫 */ Control=0xa1; /* 讀操作 */ RW24xx(p2,Length,addr,Control,enumer); /* 讀 */ } /* 以上為AT24C01~AT24C256的讀寫程序,各人可根據(jù)自己的需要應(yīng)用。 在buf1中填入需要寫入的內(nèi)容,buf2的大小可根據(jù)需要定義。 addr可根據(jù)使用的芯片選擇,可從任何位置讀寫,只要在該芯片的范圍內(nèi)。 enumer=ATxxx,根據(jù)使用的芯片賦值。各函數(shù)中的形式參數(shù)不需改變。
|