<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 淺談如果通過(guò)程序讀取AT24系列芯片型號

淺談如果通過(guò)程序讀取AT24系列芯片型號

作者: 時(shí)間:2016-11-10 來(lái)源:網(wǎng)絡(luò ) 收藏
對于一般的AT24芯片來(lái)說(shuō),要獲取型號并不復雜,那就是用眼睛看,這個(gè)是沒(méi)有問(wèn)題的。但是,如果我們用的是AT24系列的IC卡呢?如果我們用的是白卡呢?那么怎么來(lái)判斷這張卡片究竟是什么型號的?

對于以上問(wèn)題,我們想大家都有不同的看法,但是,不知道您是否真正嘗試過(guò)呢?能正確讀取AT24C01到AT24C1024之間的各種型號嗎?

為了解決這個(gè)問(wèn)題,本人思考了好幾天,以通過(guò)多種實(shí)驗去驗證,今天終于獲取結果了,不過(guò)本人先聲明,我這里只有3中類(lèi)型的卡(C02, C16, C64),每種類(lèi)型有2張或以上,驗證都是正確的。如果你有其他類(lèi)型的卡不妨也試試,如果嘗試了,請把結果告訴本人,在下先謝了。

下面我們先談?wù)勥@類(lèi)芯片的一些基礎知識,得到這些基礎知識后,看您能否想出解決這個(gè)問(wèn)題的方法,再看看方法是否和我一樣的。
對于24C系列的IC卡來(lái)說(shuō),其讀寫(xiě)操作完全和24C系列芯片的讀寫(xiě)操作一致,所有,下面我們就以此系列芯片為基礎進(jìn)行介紹。對于這系列芯片的資料特別多而且也非常詳細,下面我們就借《嵌入式實(shí)時(shí)操作系統Small RTOS51原理及應用》中的第20章串行E2PROM芯片Cat24WCxx驅動(dòng)程序的內容來(lái)描述。

雖然這一章中講的芯片不是ATMEL的,但是和這一系列完全兼容。

1. 參數表




2. 器件地址表



3. 數據地址表

3.png(92.89 KB, 下載次數: 0)

本文引用地址:http://dyxdggzs.com/article/201611/317396.htm

下載附件保存到相冊

2013-10-25 07:58 上傳




4. 操作時(shí)序

從上面的表格和圖我們可以獲取以下信息:

1. 不同型號其容量不同;
2. 不同型號的頁(yè)寫(xiě)入不同;
3. 不同型號的擴展數量不同。

還可以看出,對于24C01/02/04/08/16的數據地址只有1字節,而24C32/64/128/256等的數據地址為兩字節。我們仔細想想發(fā)現,1字節的數據地址對于24C01/02剛好夠用,而對于24C04/08/16來(lái)說(shuō)卻不夠用,所以,還必須配合器件地址實(shí)現讀寫(xiě)操作。

至此,您是否想出分別型號的方法?
想法1:通過(guò)訪(fǎng)問(wèn)器件的最高地址實(shí)現.

我們知道AT24C01的最大容量為1Kbit,以就是128字節,如果我們讀寫(xiě)128以后的地址不正確,我們就可以確定這個(gè)芯片的型號就為AT24C01了。如果用同樣的方法,從大到小的訪(fǎng)問(wèn),應該就可以區分這一系列芯片的不同型號了。

有了想法,那我們不妨試試吧。。。。。。。

結果如何呢?你是否猜到了?



。。。


通過(guò)驗證我們可以獲得結論:不管是什么型號的芯片都可以正確讀寫(xiě),根本無(wú)法分辨這一系列。24C01/02以及24C32/64/128/256無(wú)法通過(guò)24C04/08/16的程序,但其他程序都可以操作。而24C04/08/16可以通過(guò)全部型號的讀寫(xiě)操作。

也就是說(shuō):我們只能把這一系列芯片分為兩大類(lèi),而無(wú)法分辨其型號。

奇怪,這個(gè) 問(wèn)題是怎樣產(chǎn)生的呢?

查看芯片資料我們不難發(fā)現,如果讀寫(xiě)操作超過(guò)芯片地址,它是不會(huì )返回錯誤的,而是地址回卷,又從最小的地址開(kāi)始,所以,就是你寫(xiě)入地址超過(guò)芯片范圍也無(wú)法獲取錯誤。

至于24C04/08/16能夠通過(guò)各個(gè)型號芯片的讀寫(xiě)程序,是以為,這三個(gè)芯片的地址有特殊性。在讀寫(xiě)超過(guò)8位地址的地方是通過(guò)與頁(yè)地址配合實(shí)現的,以就是說(shuō)這三個(gè)芯片的地址是由:0xA* + 8Bit構成;而24C01/02的地址是由0xA0 + 8位地址構成;24C32/64/128/256的地址是由:0xA0 + 16位地址構成。

由這三個(gè)地址可以看出,由于24C04/08/16支持0xA*地址,所以可以通過(guò)各種格式的讀取,而其他兩類(lèi)不支持0xA0以外的地址,所以當通過(guò)24C04/08/16程序讀寫(xiě)這兩類(lèi)芯片時(shí)就會(huì )出現錯誤。當然24C04/08/16這三個(gè)芯片的地址由有些區別,例如04的只有1位,08的有2位,16的有3位,我們可以通過(guò)程序進(jìn)一步區分這三個(gè)型號。
想法2:通過(guò)頁(yè)讀寫(xiě)操作實(shí)現.

我們知道,不同型號其頁(yè)大小是有區別的,當操作超過(guò)頁(yè)面時(shí),芯片或滾動(dòng)覆蓋,我們可以通過(guò)寫(xiě)入最大頁(yè)面數據,根據讀取的數據可以知道其滾動(dòng)狀態(tài),從而讀取芯片頁(yè)面大小。

但是,AT24C01的頁(yè)字節為8,AT24C02/04/08/16的頁(yè)字節為16,AT24C32/64的頁(yè)字節為32,AT24C128/256的頁(yè)字節為64,所以我們只能分出這4類(lèi)芯片,還是無(wú)法實(shí)現所有型號的判別。
通過(guò)上面的想法和實(shí)際可以得出,以上兩種方法都很難實(shí)現對這一系列芯片的正確讀取。下面我們通過(guò)連續寫(xiě)入多字節進(jìn)行試驗。

例如:同時(shí)在芯片的最后幾個(gè)空間內同時(shí)寫(xiě)入4字節的數據:
  1. u8 tmpBuf[] = {0x00, 0x00, 0x00, 0x00};
  2. u8 tmpDat[] = {0xAA, 0x55, 0xFF, 0x00};
  3. ATReadDat(type, addr-3, tmpBuf, 4); // 數據暫存
  4. ATWriteDat(type, addr-3, tmpDat, 4); // 寫(xiě)入驗證數據
  5. memset(tmpDat, 0, 4);
  6. ATReadDat(type, addr-3, tmpDat, 4); // 讀取驗證數據
  7. ATWriteDat(type, addr-3, tmpBuf, 4); // 恢復寫(xiě)入前
  8. return ((memcmp(tmpDat, "xAAx55xFFx00", 4) == 0) ? 0x00 : 0x01);
復制代碼
通過(guò)以上試驗可以發(fā)現,讀寫(xiě)24C02和24C16已經(jīng)沒(méi)有問(wèn)題,完全可以爭取的區分這兩類(lèi)芯片。但還是不能讀取24C64之類(lèi)的芯片。


進(jìn)一步修改代碼:


我們知道,由于芯片超地址時(shí)會(huì )出現覆蓋寫(xiě)入,那么我們能不能把基礎可能會(huì )出現覆蓋的地方寫(xiě)入不同值了,如果發(fā)現覆蓋就可以說(shuō)明這個(gè)型號是錯的,如果沒(méi)有覆蓋就說(shuō)這個(gè)型號是對的:
  1. u8 tmpBuf[] = {0x00, 0x00};
  2. u8 tmpDat[] = {0xAA, 0x55};
  3. ATReadDat(type, ((addr+1)/2)-1, &tmpBuf[0], 1); // 數據暫存
  4. ATReadDat(type, addr, &tmpBuf[1], 1);
  5. ATWriteDat(type, ((addr+1)/2)-1, &tmpDat[0], 1);
  6. ATWriteDat(type, addr, &tmpDat[1], 1); // 寫(xiě)入驗證數據
  7. memset(tmpDat, 0, 2);
  8. ATReadDat(type, ((addr+1)/2)-1, &tmpDat[0], 1);
  9. ATReadDat(type, addr, &tmpDat[1], 1); // 讀取驗證數據
  10. ATWriteDat(type, ((addr+1)/2)-1, &tmpBuf[0], 1); // 恢復寫(xiě)入前
  11. ATWriteDat(type, addr, &tmpBuf[1], 1);
  12. return ((memcmp(tmpDat, "xAAx55", 2) == 0) ? 0x00 : 0x01);
復制代碼
通過(guò)上面的代碼驗證獲得,現在可以區別出24C64了,但卻不能區別出24C02/16等。為什么會(huì )這樣呢?連續的讀寫(xiě)可以區別24C02/16但不能區別24C64,現在雖然能區別24C64了,可其他的反而不行了,能否把這種方法和連續寫(xiě)入多字節組合呢?
  1. u8 tmpBuf[] = {0x00, 0x00, 0x00, 0x00};
  2. u8 tmpDat[] = {0xAA, 0x55, 0xFF, 0x00};
  3. ATReadDat(type, ((addr+1)/2)-2, &tmpBuf[0], 2); // 數據暫存
  4. ATReadDat(type, addr-1, &tmpBuf[2], 2);
  5. ATWriteDat(type, ((addr+1)/2)-2, &tmpDat[0], 2);
  6. ATWriteDat(type, addr-1, &tmpDat[2], 2); // 寫(xiě)入驗證數據
  7. memset(tmpDat, 0, 4);
  8. ATReadDat(type, ((addr+1)/2)-2, &tmpDat[0], 2);
  9. ATReadDat(type, addr-1, &tmpDat[2], 2); // 讀取驗證數據
  10. ATWriteDat(type, ((addr+1)/2)-2, &tmpBuf[0], 2); // 恢復寫(xiě)入前
  11. ATWriteDat(type, addr-1, &tmpBuf[2], 2);
  12. return ((memcmp(tmpDat, "xAAx55xFFx00", 4) == 0) ? 0x00 : 0x01);
復制代碼
通過(guò)上面的代碼修改和試驗,我們現在可以區別這三種型號了,通過(guò)我的推算應該是這種方法已經(jīng)可以讀取這一系列的各種型號,不過(guò)由于本人手里只有這3種卡片,其他的沒(méi)有辦法試驗。

至于為什么這樣寫(xiě)可以實(shí)現,本人也還沒(méi)有一個(gè)完整的理論依據,大家不妨一起想想,如果你先想出來(lái),請告訴我一下。
以上的程序卻是能夠實(shí)現型號辨別,但一個(gè)新的問(wèn)題出現了。例如:向24C02等單地址卡片里邊寫(xiě)入雙地址數據時(shí),由于時(shí)序的不同,芯片處理時(shí),會(huì )把雙地址的第2字節作為數據寫(xiě)入到單地址芯片中,由于我們的程序沒(méi)有考慮這一點(diǎn),所以,會(huì )導致其他地址的數據出現錯誤。

下面我們舉例說(shuō)明:

用上面的程序,我們判別型號的順序是256->128->64->32->16->08->04->02->01,寫(xiě)入的地址是芯片的最大地址的最后兩個(gè)字節和芯片最大地址的一半的最后兩個(gè)字節,這樣做的目的是試圖通過(guò)數據覆蓋來(lái)判斷型號,例如,如果最大地址的最后兩個(gè)字節覆蓋了一半的最后兩個(gè)字節,固然不是這個(gè)型號。

所以在按照24c256來(lái)想AT24C02寫(xiě)入數據是,我們是通過(guò)在地址:16382(0x3FFE)寫(xiě)入兩個(gè)字節(0xAA, 0x55),再在地址32766(7FFE)寫(xiě)入兩個(gè)字節(0xFF, 0x00),通過(guò)讀取整片AT24C02芯片獲得:

[48] = 0xAA,
[49] = 0x55,
[63] = 0xFE,

[112] = 0xFF,
[113] = 0x00,
[127] = 0xFE,

通過(guò)仔細分析我們發(fā)現,芯片處理時(shí),首先把地址16382(0x3FFE)分為2字節處理,高字節為地址即63(0x3F),低字節為數據0xFE,再加上AT24C02的頁(yè)面大小為16字節,地址0x3F已經(jīng)是頁(yè)面的最高地址,后面再寫(xiě)入數據時(shí)就會(huì )發(fā)生頁(yè)面翻轉現象,而頁(yè)面的起始地址正好是48(0x30),故而后面發(fā)生的兩字節數據就寫(xiě)入了48和49.

后面兩個(gè)字節的數據也是完全一致的現象,所以,這個(gè)程序破壞來(lái)原始數據。
判斷出卡片型號是必須的,但絕對不能破壞數據,為此我們還必須想辦法解決這一問(wèn)題:

下面我們談?wù)劻硗庖凰悸罚和ㄟ^(guò)頁(yè)和地址來(lái)實(shí)現。

我們知道AT24C01為8字節一頁(yè), AT24C02/04/08/16為16字節一頁(yè), AT24C32/64為32字節為一頁(yè), AT24C128/256為64字節為一頁(yè)。我們完全可以通過(guò)寫(xiě)頁(yè)數據,通過(guò)判斷是否有數據被覆蓋實(shí)現,過(guò)程如下:

寫(xiě)入16字節數據->讀寫(xiě)一致為AT24C02/04/08/16中一種,否則判斷8字節是否一致,一致為AT24C01,否則為其他->通過(guò)寫(xiě)最大地址判斷是否覆蓋,來(lái)判斷究竟是AT24C02/04/08/16中的那一致。其他型號過(guò)程一致,代碼如下:
  1. ATC_TYP ATCReadType(void)
  2. {
  3. u8 i;
  4. u8 tmpBuf[64] = {0};
  5. u8 tmpDat[64] = {0};
  6. u8 cmpDat[64] = {0};
  7. //--------------------------------- 單地址判斷 -----------------------------
  8. for (i=0; i<16; i++) // 初始化
  9. {
  10. tmpDat[i] = i;
  11. cmpDat[i] = i;
  12. }
  13. // AT24C01的頁(yè)為8字節,AT24C02/04/08/16的頁(yè)為16字節
  14. // 通過(guò)讀寫(xiě)16來(lái)判斷頁(yè)大小,從而區分AT24C01
  15. ATCReadNByte(AT24C02, 0, tmpBuf, 16); // 數據暫存
  16. ATCWriteNByte(AT24C02, 0, tmpDat, 16); // 寫(xiě)入驗證數據
  17. memset(tmpDat, 0, 16);
  18. ATCReadNByte(AT24C02, 0, tmpDat, 16); // 讀驗證數據
  19. if (memcmp(tmpDat, cmpDat, 16) == 0) // AT24C02/04/08/16
  20. {
  21. ATCWriteNByte(AT24C02, 0, tmpBuf, 16); // 恢復數據
  22. // AT24C02/04/08/16中,通過(guò)頁(yè)地址共同組成地址,故可以通過(guò)頁(yè)區別型號
  23. for (i=4; i>0; i--)
  24. {
  25. ATCReadByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, &tmpDat[0]);
  26. ATCWriteByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, 0xAA);
  27. ATCReadByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, &tmpDat[1]);
  28. if (tmpDat[1] == 0xAA)
  29. {
  30. ATCWriteByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, tmpDat[0]);
  31. return ((ATC_TYP)(i));
  32. }
  33. }
  34. }
  35. else
  36. {
  37. if (memcmp(&tmpDat[8], cmpDat, 8) == 0) // AT24C01
  38. {
  39. ATCWriteNByte(AT24C01, 0, tmpBuf, 8); // 恢復數據
  40. return AT24C01;
  41. }
  42. }
  43. //--------------------------------- 雙地址判斷 -----------------------------
  44. for (i=0; i<64; i++) // 初始化
  45. {
  46. tmpDat[i] = i;
  47. cmpDat[i] = i;
  48. }
  49. ATCReadNByte(AT24C128, 0, tmpBuf, 64); // 數據暫存
  50. ATCWriteNByte(AT24C128, 0, tmpDat, 64); // 寫(xiě)入驗證數據
  51. memset(tmpDat, 0, 64);
  52. ATCReadNByte(AT24C128, 0, tmpDat, 64); // 讀驗證數據
  53. if (memcmp(tmpDat, cmpDat, 64) == 0) // AT24C128/256
  54. {
  55. ATCWriteNByte(AT24C128, 0, tmpBuf, 64); // 恢復數據
  56. ATCReadByte(AT24C256, 0, &tmpDat[0]);
  57. ATCReadByte(AT24C256, ATC_Par[AT24C128].Capacity, &tmpDat[1]);
  58. ATCWriteByte(AT24C256, 0, 0xAA);
  59. ATCWriteByte(AT24C256, ATC_Par[AT24C128].Capacity, 0x55);
  60. ATCReadByte(AT24C256, 0, &tmpDat[2]);
  61. ATCReadByte(AT24C256, ATC_Par[AT24C128].Capacity, &tmpDat[3]);
  62. if ((tmpDat[2] == 0xAA) && (tmpDat[3] == 0x55))
  63. {
  64. ATCWriteByte(AT24C256, 0, tmpDat[0]);
  65. ATCWriteByte(AT24C256, ATC_Par[AT24C128].Capacity, tmpDat[1]);
  66. return AT24C256;
  67. }
  68. else
  69. {
  70. ATCWriteByte(AT24C128, 0, tmpDat[0]);
  71. return AT24C128;
  72. }
  73. }
  74. else // AT24C128/256
  75. {
  76. if (memcmp(&tmpDat[32], cmpDat, 32) == 0)
  77. {
  78. ATCWriteNByte(AT24C64, 0, tmpBuf, 32);
  79. ATCReadByte(AT24C64, 0, &tmpDat[0]);
  80. ATCReadByte(AT24C64, ATC_Par[AT24C32].Capacity, &tmpDat[1]);
  81. ATCWriteByte(AT24C64, 0, 0xAA);
  82. ATCWriteByte(AT24C64, ATC_Par[AT24C32].Capacity, 0x55);
  83. ATCReadByte(AT24C64, 0, &tmpDat[2]);
  84. ATCReadByte(AT24C64, ATC_Par[AT24C32].Capacity, &tmpDat[3]);
  85. if ((tmpDat[2] == 0xAA) && (tmpDat[3] == 0x55))
  86. {
  87. ATCWriteByte(AT24C64, 0, tmpDat[0]);
  88. ATCWriteByte(AT24C64, ATC_Par[AT24C32].Capacity, tmpDat[1]);
  89. return AT24C64;
  90. }
  91. else
  92. {
  93. ATCWriteByte(AT24C32, 0, tmpDat[0]);
  94. return AT24C32;
  95. }
  96. }
  97. }
  98. return ATC_TYP_MAX;
  99. }
復制代碼
具體代碼不再分析,代碼確實(shí)能夠實(shí)現型號識別,但是否破壞數據,暫時(shí)還沒(méi)有發(fā)現,大家不妨試試,如果破壞了數據,我們再做進(jìn)一步分析并改善。
下面我們再介紹一種比較簡(jiǎn)單,而且不會(huì )破壞數據的方法。

我們知道從AT24C01~256之間,由于容量和地址的區別,我們可以把這一系列分為三大類(lèi):

1. 單地址,直接8位地址操作:AT24C01/02
2. 單地址,8位地址加3位頁(yè)地址組合操作:AT24C04/08/16
3. 雙地址,直接16位地址操作:AT24C32/64/128/256

由上面的三大類(lèi)我們可以看出,要區別型號,可以通過(guò)先分類(lèi),再分別通過(guò)每一類(lèi)中型號的差異進(jìn)行進(jìn)一步的區別。

首先我們可以看出,從地址上來(lái)分可以把以上芯片分為單地址和雙地址,從頁(yè)面組合上來(lái)分我們可以把他們分為有組合和無(wú)組合兩種,所以,我們可以通過(guò)這兩種方法先把這系列芯片分為2類(lèi),之后再進(jìn)行細分。例如:

從地址上來(lái)分->單地址為AT24C01/02/04/08/16,雙地址為AT24C32/64/128/256:

1. 單地址5種芯片,有頁(yè)組合的有3種,這三種中 AT24C16由3位組合,AT24C08由2位組合,AT24C04由一位組合,所以當我們讀寫(xiě)0xAE地址正確時(shí)一定是AT24C16,如果不正確,讀寫(xiě)0xA6正確時(shí)一定是AT24C08,如果還不正確,讀寫(xiě)0xA2正確時(shí)一定是AT24C04,如果還不正確那,一定是AT24C01/02中的一種,而對于A(yíng)T24C01/02來(lái)說(shuō),不同的只是地址范圍,如果寫(xiě)地址0和地址128,如果數據覆蓋,那一定是AT24C01,如果沒(méi)有覆蓋那一定是AT24C02.

2. 雙地址4種芯片,沒(méi)有也組合,而不同的只有地址范圍,這一定和AT24C01/02是完全一致的,所以,由于區別的方法也和這兩個(gè)芯片一樣,通過(guò)覆蓋可以輕松的判斷出芯片型號。
  1. /**************************************************************************************
  2. * FunctionName : ATCReadType()
  3. * Description : 寫(xiě)器件型號
  4. * EntryParameter : None
  5. * ReturnValue : None
  6. **************************************************************************************/
  7. u8 ATCReadType(void)
  8. {
  9. u8 i;
  10. u8 tmpBuf[3] = {0};
  11. u8 tmpDat[3] = {0};
  12. ATCReadNByte(AT24C32, 0, tmpBuf, 1); // 讀取雙地址0的一字節暫存
  13. ATCReadNByte(AT24C16, 0, &tmpBuf[1], 2); // 讀取單地址0的二字節暫存
  14. ATCWriteNByte(AT24C32, 0, "xA5", 1); // 按照雙地址格式寫(xiě)入一字節數據
  15. ATCReadNByte(AT24C32, 0, tmpDat, 1); // 按照雙地址格式讀取一字節數據
  16. ATCReadNByte(AT24C16, 0, &tmpDat[1], 2); // 按照單地址格式讀取二字節數據
  17. if ((tmpDat[1] == 0x00) && (tmpDat[2] == 0xA5)) // 單地址芯片
  18. {
  19. ATCWriteNByte(AT24C16, 0, &tmpBuf[1], 2); // 恢復數據
  20. //-------------------------------- AT24c04/08/16 -----------------------
  21. for (i=AT24C16; i>AT24C02; i--) // AT24c04/08/16
  22. {
  23. ATCReadByte(i, ATC_Par[i].MaxAddr, &tmpBuf[0]);
  24. ATCWriteByte(i, ATC_Par[i].MaxAddr, 0xAA);
  25. ATCReadByte(i, ATC_Par[i].MaxAddr, &tmpDat[0]);
  26. ATCWriteByte(i, ATC_Par[i].MaxAddr, tmpBuf[0]);
  27. if (tmpDat[0] == 0xAA)
  28. {
  29. return i;
  30. }
  31. }
  32. //-------------------------------- AT24c01/02 --------------------------
  33. ATCReadByte(AT24C02, 0, &tmpBuf[0]);
  34. ATCReadByte(AT24C02, 128, &tmpBuf[1]);
  35. ATCWriteByte(AT24C02, 0, 0xAA);
  36. ATCWriteByte(AT24C02, 128, 0x55);
  37. ATCReadByte(AT24C02, 0, &tmpDat[0]);
  38. ATCReadByte(AT24C02, 128, &tmpDat[1]);
  39. ATCWriteByte(AT24C02, 0, tmpBuf[0]);
  40. ATCWriteByte(AT24C02, 128, tmpBuf[1]);
  41. return (tmpDat[0] == 0x55) ? AT24C01 : AT24C02;
  42. }
  43. else
  44. {
  45. if (tmpDat[0] == 0xA5) // 雙地址芯片
  46. {
  47. ATCWriteNByte(AT24C256, 0, &tmpBuf[0], 1); // 恢復數據
  48. //-------------------------------- AT24c32/64/128/256 --------------
  49. for (i=AT24C256; i>AT24C16; i--)
  50. {
  51. ATCReadByte(i, 0, &tmpBuf[0]);
  52. ATCReadByte(i, ATC_Par[i-1].Capacity, &tmpBuf[1]);
  53. ATCWriteByte(i, 0, 0xAA);
  54. ATCWriteByte(i, ATC_Par[i-1].Capacity, 0x55);
  55. ATCReadByte(i, 0, &tmpDat[0]);
  56. ATCReadByte(i, ATC_Par[i-1].Capacity, &tmpDat[1]);
  57. ATCWriteByte(i, 0, tmpBuf[0]);
  58. ATCWriteByte(i, ATC_Par[i-1].Capacity, tmpBuf[1]);
  59. if ((tmpDat[0] == 0xAA) && (tmpDat[1] == 0x55))
  60. {
  61. return i;
  62. }
  63. }
  64. return AT24C256;
  65. }
  66. else // 非AT系列芯片
  67. {
  68. return ATC_TYP_MAX;
  69. }
  70. }
  71. }
復制代碼
對于上面的程序需要注意,我們的方法是通過(guò)寫(xiě)入數據之后讀取進(jìn)行判斷的,所以在寫(xiě)入數據之前必須把要寫(xiě)入的地址數據暫存,完成判斷后必須恢復,絕對不能破壞芯片類(lèi)的數據。

在單地址和雙地址的判斷中,我們按照兩種方法進(jìn)行數據暫存,因為我們剛開(kāi)始并不知道卡片究竟是什么型號,所以,在判斷出來(lái)后,按照單雙地址分別恢復也保證數據的正確性。

還有一點(diǎn)需要強調,我們在按照雙地址方式,在地址0的地方寫(xiě)入0xA5數據,如果芯片確實(shí)是雙地址,那么該數據一定寫(xiě)入地址0,數據數據為0xA5,但是如果該芯片為單地址,那么地址的低8為就被作為數據一起寫(xiě)入了,所以會(huì )導致,地址0開(kāi)始寫(xiě)入兩字節數據,一字節為0(地址的低8位被當做第一個(gè)數據了),一字節為0xA5(數據卻作為第2字節數據寫(xiě)入了)。所以通過(guò)這兩字節數據可以輕松的判斷出究竟是單地址還是雙地址。


關(guān)鍵詞: 程序讀取AT24系列芯片型

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>