這個程序我檢測過24C02,24C16,24C04,24C64,24C32,均未出錯。也沒有毀損器件內部數據的問題。可靠性比較好。在我的編程器中已經使用。此程序write by 萬致遠,在sdcc v3.1.0中無錯誤/warning編譯。死太慘89C52中通過。
上代碼:
/* FILE 24C.C Write by 萬致遠 */ #include <hwconfig.h> #include <type-def.h> #include <delay.h> #include <i2c.h> #include <24c.h> #define AT24C02_DeviceAdd_W 0xa0 //器件地址(寫) #define AT24C02_DeviceAdd_R 0xa1 //器件地址(讀) #define ADD_TYPE_8 0 #define ADD_TYPE_16 1 #define AT24C01 0 #define AT24C02 1 #define AT24C04 2 #define AT24C08 3 #define AT24C16 4 #define AT24C32 5 #define AT24C64 6 #define AT24C128 7 #define AT24C256 8 #define AT24C512 9 #define AT24C1024 10 #define SCAN_ERROR 0xFF ULONG __code Length_Chip[11]={ 0x7f,0xff,0x1ff,0x3ff,0xfff,0x7ff,0x1fff,0x3fff,0x7fff,0xffff,0x1ffff };//各類ROM的容量表~ BYTE __code TEST_DATA[2]={0xAA,0xBB}; //測試數據 #define W_DELAY 4 //4 ms DELAY //---------------------------------------------- //24C操作函數,頁寫。 //IIC_ADDR器件地址 //Address 16BIT地址 //TYPE 地址模式 //Data指針 //Len長度 //本函數不支持翻頁,請自行翻頁,控制IIC_Addr BOOL RW24(BYTE IIC_Addr,UINT Address,BOOL Type,BYTE *Data,BYTE Len) { BYTE i=0; //----------------------------選中芯片程序開始----------- I2C_Start(); // 啟動I2C總線 I2C_Write8Bit(IIC_Addr & 0xFE); // 發送器件地址(寫)1111 1110 if( I2C_Check_Ack() == 0 ) // 檢測從機應答 {I2C_Stop();return 0; } if (Type==ADD_TYPE_8) {//8位地址的話 I2C_Write8Bit(Address); // 發送將要處理的數據的地址,8位 } else {//16位地址的話 I2C_Write8Bit(((Address & 0xFF00)>>8)); //發送高八位地址 if( I2C_Check_Ack() == 0 ) // 檢測從機應答 {I2C_Stop();return 0; } I2C_Write8Bit((Address & 0xFF)); //低八位地址發送 } if( I2C_Check_Ack() == 0 ) // 檢測從機應答 {I2C_Stop();return 0; } //---------------------------------結束------------------- if((IIC_Addr & 0x01)==1) {//是讀操作 *Data=0xFF; //FF=NULL I2C_Start(); // 再次啟動IIC總線 I2C_Write8Bit(IIC_Addr); //發送讀出地址 if( I2C_Check_Ack() == 0 ) // 檢測從機應答 {I2C_Stop();return 0; } *Data = I2C_Read8Bit(); // 讀取第一個數據 Data++; for(i=1;i<Len;i++) { I2C_Send_Bit_0();//發送ACK *Data = I2C_Read8Bit(); //讀取數據 Data++;//指針加一 } I2C_Send_Bit_1(); // 產生NAK信號結束讀取數據 I2C_Stop(); return 1; } else {//是寫操作 for(i=0;i<Len;i++) { I2C_Write8Bit(*Data); //I2C_Write8Bit(0xff); if(I2C_Check_Ack()==0) {I2C_Stop();return 0;} Data++; } I2C_Stop(); Delay_ms(W_DELAY);//加延時啊……要不然寫不進……型號也會判斷錯誤……5~6MS return 1; } } //--------------------------------------------------------------------------------------- //測試24C系列8BIT地址的一頁,檢測24C02~24C16 BOOL Page_Test(BYTE Page) { BYTE tmp[3]; RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[0],1);//讀出原來數據 RW24(AT24C02_DeviceAdd_R|Page,0x00,ADD_TYPE_8,&tmp[1],1); RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&TEST_DATA[1],1);//修改數據寫入00單元1頁 RW24(AT24C02_DeviceAdd_W|Page,0x00,ADD_TYPE_8,&TEST_DATA[0],1);//修改數據寫入00單元2頁 RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[2],1);//讀入 RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫回數據 if(tmp[2]==0xAA) {//24C02 //RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫回數據 return TRUE; } //RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫回數據 RW24(AT24C02_DeviceAdd_W|Page,0x00,ADD_TYPE_8,&tmp[1],1); return FALSE; } //------------------------------------------------------------------------------------------------------ //--檢測24C32器件的地址溢出 //BOOL RW24(BYTE IIC_Addr,UINT Address,BOOL Type,BYTE *Data); //ADDRESS 2為猜測的最高地址 BOOL Write_Test(UINT Address2,BOOL Add_Type) { BYTE tmp[3]; RW24(AT24C02_DeviceAdd_R,0,Add_Type,&tmp[0],1);//讀出0x0000單元數據 RW24(AT24C02_DeviceAdd_R,Address2,Add_Type,&tmp[1],1);//讀出0x1000單元數據 RW24(AT24C02_DeviceAdd_W,0,Add_Type,&TEST_DATA[1],1);//改變原有數據,避免干擾 RW24(AT24C02_DeviceAdd_W,Address2,Add_Type,&TEST_DATA[0],1);//寫入0xAA到單元去,產生地址溢出 RW24(AT24C02_DeviceAdd_R,0,Add_Type,&tmp[2],1);//讀出0000單元內容 RW24(AT24C02_DeviceAdd_W,0,Add_Type,&tmp[0],1);//寫回數據 if(tmp[2]==0xAA)//先前改變的數據,如果產生溢出可以檢測到 { //RW24(AT24C02_DeviceAdd_W,0x0000,Add_Type,&tmp[0],1);//寫回被(1)步驟更改的數據 return TRUE;//返回正確 } //RW24(AT24C02_DeviceAdd_W,0x0000,ADD_TYPE_16,&tmp[0],1);//寫回數據 RW24(AT24C02_DeviceAdd_W,Address2,Add_Type,&tmp[1],1);//寫回數據 return FALSE; } //------------調用此函數返回芯片類型 BYTE Test24() {//測試24系列的容量 //24C16:Address=1010 P2 P1 P0 R/W BYTE tmp[3]; // // read: // 8 Bit series: |start|address_w|address|start|address_r|data|stop| // 16 bit series:|start|address_w|address|address|start|address_r|data|stop| // TEST: |START|address_w|address|start|address_r|data|stop| // write: // 8bit series: |start|address_w|address|data|stop| // 16bit series: |start|address_w|address|address|data|stop| // tmp[0]=0xff; if(RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[0],1)==TRUE)//讀出0單元 {//判斷是否是8bit series RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&TEST_DATA[1],1);//寫入AA RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[1],1);//再次讀出 if(tmp[1]==0xBB) {//8bit series無誤 //我發現我還是在實際上出錯了%……實際上寫頁還是寫的進可是只有一個頁…… RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫回數據,RW搞錯了 //測試是否24C01 //24C01的地址范圍從0~127(0~7F),OK,向80H讀出,然后寫一個數據 /*RW24(AT24C02_DeviceAdd_R,0x0000,ADD_TYPE_8,&tmp[0],1);//讀出0x0000單元數據【0】 RW24(AT24C02_DeviceAdd_R,0x0080,ADD_TYPE_8,&tmp[1],1);//讀出0x80單元數據【1】 RW24(AT24C02_DeviceAdd_W,0x0000,ADD_TYPE_8,&TEST_DATA[1],1);//寫入0000單元防止原來數據干擾 RW24(AT24C02_DeviceAdd_W,0x0080,ADD_TYPE_8,&TEST_DATA[0],1);//寫入0000單元防止原來數據干擾 RW24(AT24C02_DeviceAdd_R,0x0000,ADD_TYPE_8,&tmp[2],1);//寫入0000單元防止原來數據干擾 RW24(AT24C02_DeviceAdd_W,0x0000,ADD_TYPE_8,&tmp[0],1);//寫回0單元數據 if(tmp[2]==0xAA) {//24C01 return AT24C01; }*/ if(Write_Test(0x80,ADD_TYPE_8)) { return AT24C01; } //這應該是24C02 etc……絕對不可能是24C01,除非器件的80H單元正好壞了 //24C16:Address=1010 P2 P1 P0 R/W //RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫回原來的數據到0x80 //RW24(AT24C02_DeviceAdd_W,0x80,ADD_TYPE_8,&tmp[1],1);//寫回原來的數據0x00 //---------------------------------------------------------------- //MAX——PAGE 02 04 08 16 // 000 001 011 111 //-------TEST 24C02 if(Page_Test(0x02)) { return AT24C02; } if(Page_Test(0x06)) { return AT24C04; } if(Page_Test(0x0E)) { return AT24C08; } return AT24C16; } else {//AT24C32的地址范圍從0~4095(0xFFF) //AT24C64從0~8191(0x1FFF) //AT24C128從0~16383(0x3FFF) //AT24C256從0~32767(0x7FFF) //AT24C512從0~65535(0xFFFF) //AT24C1024從0~65535(0xFFFF),地址中多一個P1選擇位 //從小試到大 //測試24C1024 //1010 0010 = 0x02 //就是產生傳說中的地址溢出了…… //-----24C1024 if(RW24(AT24C02_DeviceAdd_R | 0x02,0xFFFF,ADD_TYPE_16,&tmp[0],1))//讀出第二頁的0xFFFE {//成功代表是24C1024 return AT24C1024; } //優化算法 //-----24C32 if(Write_Test(0x1000,ADD_TYPE_16)) { return AT24C32; } //24C64 if(Write_Test(0x2000,ADD_TYPE_16)) { return AT24C64; } //24C128 if(Write_Test(0x4000,ADD_TYPE_16)) { return AT24C128; } //24C256 if(Write_Test(0x8000,ADD_TYPE_16)) { return AT24C32; } //-------------24C512*/ return AT24C512; } } else { return SCAN_ERROR; } }
完整版本的代碼下載地址: http://www.zg4o1577.cn/f/dfd33.rar