[原创] 如何判断IC[AT24Cxx]好的型号?

zhaojun_xf   2015-11-12 13:53 楼主
我们知道AT24Cxx系列有很多种型号,如:AT24C01/02/04/08/16/32/64/128/256等等,容量分别对应1K/2K/4K/8K/16K/32K/64K/128K/256K位。但不同的型号其缓冲页的大小和地址字节数的不同的,所以,其对应的程序也不是完全一样的。那么我们在做读卡器时,怎么才知道读卡器中插入的是那支卡片呢? 通过查找资料我们首先可以获得以下两个特点: 1. AT24C01有8字节的页写缓冲器,AT24C02/04/08/16有16字节的页写缓冲器,AT24C32/64有32字节的页写缓冲器,AT24C128/256有64字节的页写缓冲器。 2. AT24C01/02/04/08/16采用8位地址,AT24C32/64/128/256采用16位地址。 那么通过这些信息,我们是否可以判断出哪张卡是哪种型号呢? 下面对比以下单字节和双字节的读写时序:
1.png
AT24C02/04/08/16
2.png
AT24C32/64/128/256
从上面的写时序图可以看出,单字节和双字节地址的区别在与发送从机地址后,后面跟的芯片内部地址数不同。如果按照单字节写双字节芯片时,会导致单字节的数据变为双字节地址的第二字节地址,相反,则会把第二字节地址当成数据写入芯片中。所以,我们可以通过读取写入的数据来判断芯片究竟是单地址还是双字节,从而可以把芯片分为两大类。
其次,由于不同的芯片其地址范围不同,我们可以通过操作最大地址空间来判断究竟是哪一种芯片。为了快闪获取芯片型号,每一组中我们应该从最多的那个开始,例如:
//-------------------------------- AT24c04/08/16 -----------------------
for (i=AT24C16; i>AT24C02; i--) // AT24c04/08/16
{
ATC_ICType = i;
ATCReadByte(ATC_Par.MaxAddr, &tmpBuf[0]);
ATCWriteByte(ATC_Par.MaxAddr, 0xAA);
ATCReadByte(ATC_Par.MaxAddr, &tmpDat[0]);
ATCWriteByte(ATC_Par.MaxAddr, tmpBuf[0]);
if (tmpDat[0] == 0xAA)
{
return ;
}
}

通过这些方法我们就可以实现IC型号的判断了:

/**************************************************************************************

* FunctionName : ATC_ReadType()

* Description : 写器件型号

* EntryParameter : None

* ReturnValue : 返回卡片类型

**************************************************************************************/

void ATC_ReadType(void)

{

u8 i;

u8 tmpBuf[3] = {0};

u8 tmpDat[3] = {0};

ATC_ICType = AT24C32;

ATCReadNByte(0, tmpBuf, 1); // 读取双地址0的一字节暂存

ATC_ICType = AT24C16;

ATCReadNByte(0, &tmpBuf[1], 2); // 读取单地址0的二字节暂存

ATC_ICType = AT24C32;

ATCWriteNByte(0, "\xA5", 1); // 按照双地址格式写入一字节数据

ATCReadNByte(0, tmpDat, 1); // 按照双地址格式读取一字节数据

ATC_ICType = AT24C16;

ATCReadNByte(0, &tmpDat[1], 2); // 按照单地址格式读取二字节数据

if ((tmpDat[1] == 0x00) && (tmpDat[2] == 0xA5)) // 单地址芯片

{

ATCWriteNByte(0, &tmpBuf[1], 2); // 恢复数据

//-------------------------------- AT24c04/08/16 -----------------------

for (i=AT24C16; i>AT24C02; i--) // AT24c04/08/16

{

ATC_ICType = i;

ATCReadByte(ATC_Par.MaxAddr, &tmpBuf[0]);

ATCWriteByte(ATC_Par.MaxAddr, 0xAA);

ATCReadByte(ATC_Par.MaxAddr, &tmpDat[0]);

ATCWriteByte(ATC_Par.MaxAddr, tmpBuf[0]);

if (tmpDat[0] == 0xAA)

{

return ;

}

}

//-------------------------------- AT24c01/02 --------------------------

ATC_ICType = AT24C02;

ATCReadByte(0, &tmpBuf[0]);

ATCReadByte(128, &tmpBuf[1]);

ATCWriteByte(0, 0xAA);

ATCWriteByte(128, 0x55);

ATCReadByte(0, &tmpDat[0]);

ATCReadByte(128, &tmpDat[1]);

ATCWriteByte(0, tmpBuf[0]);

ATCWriteByte(128, tmpBuf[1]);

ATC_ICType = (tmpDat[0] == 0x55) ? AT24C01 : AT24C02;

return ;

}

else

{

if (tmpDat[0] == 0xA5) // 双地址芯片

{

ATC_ICType = AT24C256;

ATCWriteNByte(0, &tmpBuf[0], 1); // 恢复数据

//-------------------------------- AT24c32/64/128/256 --------------

for (i=AT24C256; i>AT24C16; i--)

{

ATC_ICType = i;

ATCReadByte(0, &tmpBuf[0]);

ATCReadByte(ATC_Par[i-1].Capacity, &tmpBuf[1]);

ATCWriteByte(0, 0xAA);

ATCWriteByte(ATC_Par[i-1].Capacity, 0x55);

ATCReadByte(0, &tmpDat[0]);

ATCReadByte(ATC_Par[i-1].Capacity, &tmpDat[1]);

ATCWriteByte(0, tmpBuf[0]);

ATCWriteByte(ATC_Par[i-1].Capacity, tmpBuf[1]);

if ((tmpDat[0] == 0xAA) && (tmpDat[1] == 0x55))

{

return ;

}

}

ATC_ICType = AT24C256;

return ;

}

else // 非AT系列芯片

{

ATC_ICType = ATC_TYP_MAX;

return ;

}

}

}

本帖最后由 zhaojun_xf 于 2015-11-12 15:32 编辑
我的博客

回复评论 (2)

楼主这个方法验证过嘛? 如果EEPROM存的数据量较大,这样子判断岂不是会造成已存的数据错误?
点赞  2016-3-10 15:35
引用: feng_mailx 发表于 2016-3-10 15:35
楼主这个方法验证过嘛? 如果EEPROM存的数据量较大,这样子判断岂不是会造成已存的数据错误?

你确定看懂了?
我的博客
点赞  2016-3-11 09:42
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复