專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

51一個(gè)24C讀寫(xiě)函數(shù),支持檢測(cè)器件型號(hào)

作者:萬(wàn)致遠(yuǎn)   來(lái)源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2012年09月09日   【字體:

    這個(gè)程序我檢測(cè)過(guò)24C02,24C16,24C04,24C64,24C32,均未出錯(cuò)。也沒(méi)有毀損器件內(nèi)部數(shù)據(jù)的問(wèn)題?煽啃员容^好。在我的編程器中已經(jīng)使用。此程序write by 萬(wàn)致遠(yuǎn),在sdcc v3.1.0中無(wú)錯(cuò)誤/warning編譯。死太慘89C52中通過(guò)。

上代碼:
 

/* FILE 24C.C
Write by 萬(wàn)致遠(yuǎn)
*/
#include <hwconfig.h>
#include <type-def.h>
#include <delay.h>
#include <i2c.h>
#include <24c.h>
#define AT24C02_DeviceAdd_W 0xa0	//器件地址(寫(xiě))
#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};	//測(cè)試數(shù)據(jù)
#define W_DELAY 4   //4 ms DELAY 		
//----------------------------------------------
//24C操作函數(shù),頁(yè)寫(xiě)。
//IIC_ADDR器件地址
//Address 16BIT地址
//TYPE	地址模式
//Data指針
//Len長(zhǎng)度
//本函數(shù)不支持翻頁(yè),請(qǐng)自行翻頁(yè),控制IIC_Addr
BOOL RW24(BYTE IIC_Addr,UINT Address,BOOL Type,BYTE *Data,BYTE Len)
{
	BYTE i=0;
	//----------------------------選中芯片程序開(kāi)始-----------
	I2C_Start();	// 啟動(dòng)I2C總線
	I2C_Write8Bit(IIC_Addr & 0xFE);					// 發(fā)送器件地址(寫(xiě))1111 1110
	if( I2C_Check_Ack() == 0 )                		// 檢測(cè)從機(jī)應(yīng)答
			{I2C_Stop();return 0;	  }
	if (Type==ADD_TYPE_8)
	{//8位地址的話
		I2C_Write8Bit(Address);   				// 發(fā)送將要處理的數(shù)據(jù)的地址,8位
	}
	else
	{//16位地址的話
		I2C_Write8Bit(((Address & 0xFF00)>>8));			//發(fā)送高八位地址
		if( I2C_Check_Ack() == 0 )                		// 檢測(cè)從機(jī)應(yīng)答
			{I2C_Stop();return 0;	  }
		I2C_Write8Bit((Address & 0xFF));	//低八位地址發(fā)送
	}
	if( I2C_Check_Ack() == 0 )                		// 檢測(cè)從機(jī)應(yīng)答
			{I2C_Stop();return 0;	  }
	//---------------------------------結(jié)束-------------------
	if((IIC_Addr & 0x01)==1)
	{//是讀操作
		*Data=0xFF;									//FF=NULL
		I2C_Start();				         		// 再次啟動(dòng)IIC總線
		I2C_Write8Bit(IIC_Addr);					//發(fā)送讀出地址
		if( I2C_Check_Ack() == 0 )                // 檢測(cè)從機(jī)應(yīng)答
			{I2C_Stop();return 0;	  }
		*Data = I2C_Read8Bit();		         	   // 讀取第一個(gè)數(shù)據(jù)
		Data++;
		for(i=1;i<Len;i++)
		{
			I2C_Send_Bit_0();//發(fā)送ACK
			*Data = I2C_Read8Bit();	//讀取數(shù)據(jù)
			Data++;//指針加一
		}	         	   
		I2C_Send_Bit_1();				 			// 產(chǎn)生NAK信號(hào)結(jié)束讀取數(shù)據(jù)			
		I2C_Stop();	
		return 1;
	}
	else
	{//是寫(xiě)操作
		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);//加延時(shí)啊……要不然寫(xiě)不進(jìn)……型號(hào)也會(huì)判斷錯(cuò)誤……5~6MS
		return 1;
	}
}
//---------------------------------------------------------------------------------------
//測(cè)試24C系列8BIT地址的一頁(yè),檢測(cè)24C02~24C16
BOOL Page_Test(BYTE Page)
{
	BYTE tmp[3];
	RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[0],1);//讀出原來(lái)數(shù)據(jù)
	RW24(AT24C02_DeviceAdd_R|Page,0x00,ADD_TYPE_8,&tmp[1],1);
	RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&TEST_DATA[1],1);//修改數(shù)據(jù)寫(xiě)入00單元1頁(yè)
	RW24(AT24C02_DeviceAdd_W|Page,0x00,ADD_TYPE_8,&TEST_DATA[0],1);//修改數(shù)據(jù)寫(xiě)入00單元2頁(yè)
	RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[2],1);//讀入
	RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫(xiě)回?cái)?shù)據(jù)
	if(tmp[2]==0xAA)
	{//24C02
		//RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫(xiě)回?cái)?shù)據(jù)
		return TRUE;
	}
				//RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫(xiě)回?cái)?shù)據(jù)
	RW24(AT24C02_DeviceAdd_W|Page,0x00,ADD_TYPE_8,&tmp[1],1);	
	return FALSE;
}
//------------------------------------------------------------------------------------------------------
//--檢測(cè)24C32器件的地址溢出
//BOOL RW24(BYTE IIC_Addr,UINT Address,BOOL Type,BYTE *Data);
//ADDRESS 2為猜測(cè)的最高地址
BOOL Write_Test(UINT Address2,BOOL Add_Type)
{
	BYTE tmp[3];
	RW24(AT24C02_DeviceAdd_R,0,Add_Type,&tmp[0],1);//讀出0x0000單元數(shù)據(jù)
	RW24(AT24C02_DeviceAdd_R,Address2,Add_Type,&tmp[1],1);//讀出0x1000單元數(shù)據(jù)
	RW24(AT24C02_DeviceAdd_W,0,Add_Type,&TEST_DATA[1],1);//改變?cè)袛?shù)據(jù),避免干擾
	RW24(AT24C02_DeviceAdd_W,Address2,Add_Type,&TEST_DATA[0],1);//寫(xiě)入0xAA到單元去,產(chǎn)生地址溢出
	RW24(AT24C02_DeviceAdd_R,0,Add_Type,&tmp[2],1);//讀出0000單元內(nèi)容
	RW24(AT24C02_DeviceAdd_W,0,Add_Type,&tmp[0],1);//寫(xiě)回?cái)?shù)據(jù)
	if(tmp[2]==0xAA)//先前改變的數(shù)據(jù),如果產(chǎn)生溢出可以檢測(cè)到
	{
				//RW24(AT24C02_DeviceAdd_W,0x0000,Add_Type,&tmp[0],1);//寫(xiě)回被(1)步驟更改的數(shù)據(jù)
				return TRUE;//返回正確
	}
			//RW24(AT24C02_DeviceAdd_W,0x0000,ADD_TYPE_16,&tmp[0],1);//寫(xiě)回?cái)?shù)據(jù)
	RW24(AT24C02_DeviceAdd_W,Address2,Add_Type,&tmp[1],1);//寫(xiě)回?cái)?shù)據(jù)
	return FALSE;
}
//------------調(diào)用此函數(shù)返回芯片類型
BYTE Test24()
{//測(cè)試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);//寫(xiě)入AA
		RW24(AT24C02_DeviceAdd_R,0x00,ADD_TYPE_8,&tmp[1],1);//再次讀出		
		if(tmp[1]==0xBB)
		{//8bit series無(wú)誤
		//我發(fā)現(xiàn)我還是在實(shí)際上出錯(cuò)了%……實(shí)際上寫(xiě)頁(yè)還是寫(xiě)的進(jìn)可是只有一個(gè)頁(yè)……
			RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫(xiě)回?cái)?shù)據(jù),RW搞錯(cuò)了
			//測(cè)試是否24C01
			//24C01的地址范圍從0~127(0~7F),OK,向80H讀出,然后寫(xiě)一個(gè)數(shù)據(jù)
			/*RW24(AT24C02_DeviceAdd_R,0x0000,ADD_TYPE_8,&tmp[0],1);//讀出0x0000單元數(shù)據(jù)【0】
			RW24(AT24C02_DeviceAdd_R,0x0080,ADD_TYPE_8,&tmp[1],1);//讀出0x80單元數(shù)據(jù)【1】
			RW24(AT24C02_DeviceAdd_W,0x0000,ADD_TYPE_8,&TEST_DATA[1],1);//寫(xiě)入0000單元防止原來(lái)數(shù)據(jù)干擾
			RW24(AT24C02_DeviceAdd_W,0x0080,ADD_TYPE_8,&TEST_DATA[0],1);//寫(xiě)入0000單元防止原來(lái)數(shù)據(jù)干擾
			RW24(AT24C02_DeviceAdd_R,0x0000,ADD_TYPE_8,&tmp[2],1);//寫(xiě)入0000單元防止原來(lái)數(shù)據(jù)干擾
			RW24(AT24C02_DeviceAdd_W,0x0000,ADD_TYPE_8,&tmp[0],1);//寫(xiě)回0單元數(shù)據(jù)
			if(tmp[2]==0xAA)
			{//24C01

				return AT24C01;
			}*/
			if(Write_Test(0x80,ADD_TYPE_8))
			{
				return AT24C01;
			}
				//這應(yīng)該是24C02 etc……絕對(duì)不可能是24C01,除非器件的80H單元正好壞了
				//24C16:Address=1010 P2 P1 P0 R/W
				//RW24(AT24C02_DeviceAdd_W,0x00,ADD_TYPE_8,&tmp[0],1);//寫(xiě)回原來(lái)的數(shù)據(jù)到0x80
				//RW24(AT24C02_DeviceAdd_W,0x80,ADD_TYPE_8,&tmp[1],1);//寫(xiě)回原來(lái)的數(shù)據(jù)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),地址中多一個(gè)P1選擇位
		//從小試到大
		//測(cè)試24C1024
		//1010 0010 = 0x02
		//就是產(chǎn)生傳說(shuō)中的地址溢出了……
		//-----24C1024
			if(RW24(AT24C02_DeviceAdd_R | 0x02,0xFFFF,ADD_TYPE_16,&tmp[0],1))//讀出第二頁(yè)的0xFFFE
			{//成功代表是24C1024
				return AT24C1024;
			}
		//優(yōu)化算法
		//-----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.torrancerestoration.com/f/dfd33.rar

關(guān)閉窗口

相關(guān)文章