浅谈如果通过程序读取AT24系列芯片型号

发布者:boyhxz最新更新时间:2016-07-14 来源: eefocus关键字:程序读取  AT24系列  芯片型号 手机看文章 扫描二维码
随时随地手机看文章
对于一般的AT24芯片来说,要获取型号并不复杂,那就是用眼睛看,这个是没有问题的。但是,如果我们用的是AT24系列的IC卡呢?如果我们用的是白卡呢?那么怎么来判断这张卡片究竟是什么型号的?

        对于以上问题,我们想大家都有不同的看法,但是,不知道您是否真正尝试过呢?能正确读取AT24C01到AT24C1024之间的各种型号吗?

        为了解决这个问题,本人思考了好几天,以通过多种实验去验证,今天终于获取结果了,不过本人先声明,我这里只有3中类型的卡(C02, C16, C64),每种类型有2张或以上,验证都是正确的。如果你有其他类型的卡不妨也试试,如果尝试了,请把结果告诉本人,在下先谢了。

       下面我们先谈谈这类芯片的一些基础知识,得到这些基础知识后,看您能否想出解决这个问题的方法,再看看方法是否和我一样的。
 
对于24C系列的IC卡来说,其读写操作完全和24C系列芯片的读写操作一致,所有,下面我们就以此系列芯片为基础进行介绍。对于这系列芯片的资料特别多而且也非常详细,下面我们就借《嵌入式实时操作系统Small RTOS51原理及应用》中的第20章 串行E2PROM芯片Cat24WCxx驱动程序的内容来描述。

       虽然这一章中讲的芯片不是ATMEL的,但是和这一系列完全兼容。

1. 参数表

[原创文章] 浅谈如果通过程序读取AT24系列芯片型号 - 我心永恒 - ARM嵌入式研发



2. 器件地址表

[原创文章] 浅谈如果通过程序读取AT24系列芯片型号 - 我心永恒 - ARM嵌入式研发


3. 数据地址表

[原创文章] 浅谈如果通过程序读取AT24系列芯片型号 - 我心永恒 - ARM嵌入式研发

3.png (92.89 KB, 下载次数: 0)

下载附件  保存到相册

2013-10-25 07:58 上传

 



4. 操作时序

[原创文章] 浅谈如果通过程序读取AT24系列芯片型号 - 我心永恒 - ARM嵌入式研发
从上面的表格和图我们可以获取以下信息:

1. 不同型号其容量不同;
2. 不同型号的页写入不同;
3. 不同型号的扩展数量不同。

      还可以看出,对于24C01/02/04/08/16的数据地址只有1字节,而24C32/64/128/256等的数据地址为两字节。我们仔细想想发现,1字节的数据地址对于24C01/02刚好够用,而对于24C04/08/16来说却不够用,所以,还必须配合器件地址实现读写操作。

     至此,您是否想出分别型号的方法?
想法1:通过访问器件的最高地址实现.

      我们知道AT24C01的最大容量为1Kbit,以就是128字节,如果我们读写128以后的地址不正确,我们就可以确定这个芯片的型号就为AT24C01了。如果用同样的方法,从大到小的访问,应该就可以区分这一系列芯片的不同型号了。
     
       有了想法,那我们不妨试试吧。。。。。。。

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



。。。


      通过验证我们可以获得结论:不管是什么型号的芯片都可以正确读写,根本无法分辨这一系列。24C01/02以及24C32/64/128/256无法通过24C04/08/16的程序,但其他程序都可以操作。而24C04/08/16可以通过全部型号的读写操作。

     也就是说:我们只能把这一系列芯片分为两大类,而无法分辨其型号。

奇怪,这个 问题是怎样产生的呢?

     查看芯片资料我们不难发现,如果读写操作超过芯片地址,它是不会返回错误的,而是地址回卷,又从最小的地址开始,所以,就是你写入地址超过芯片范围也无法获取错误。

       至于24C04/08/16能够通过各个型号芯片的读写程序,是以为,这三个芯片的地址有特殊性。在读写超过8位地址的地方是通过与页地址配合实现的,以就是说这三个芯片的地址是由:0xA* + 8Bit构成;而24C01/02的地址是由0xA0 + 8位地址构成;24C32/64/128/256的地址是由:0xA0 + 16位地址构成。

     由这三个地址可以看出,由于24C04/08/16支持0xA*地址,所以可以通过各种格式的读取,而其他两类不支持0xA0以外的地址,所以当通过24C04/08/16程序读写这两类芯片时就会出现错误。当然24C04/08/16这三个芯片的地址由有些区别,例如04的只有1位,08的有2位,16的有3位,我们可以通过程序进一步区分这三个型号。
 
想法2:通过页读写操作实现.

     我们知道,不同型号其页大小是有区别的,当操作超过页面时,芯片或滚动覆盖,我们可以通过写入最大页面数据,根据读取的数据可以知道其滚动状态,从而读取芯片页面大小。

     但是,AT24C01的页字节为8,AT24C02/04/08/16的页字节为16,AT24C32/64的页字节为32,AT24C128/256的页字节为64,所以我们只能分出这4类芯片,还是无法实现所有型号的判别。
 
通过上面的想法和实际可以得出,以上两种方法都很难实现对这一系列芯片的正确读取。下面我们通过连续写入多字节进行试验。

例如:同时在芯片的最后几个空间内同时写入4字节的数据:
  1.    u8 tmpBuf[] = {0x00, 0x00, 0x00, 0x00};
  2.     u8 tmpDat[] = {0xAA, 0x55, 0xFF, 0x00};
  3.     
  4.     ATReadDat(type, addr-3, tmpBuf, 4);                                         // 数据暂存
  5.     ATWriteDat(type, addr-3, tmpDat, 4);                                        // 写入验证数据
  6.    
  7.     memset(tmpDat, 0, 4);         
  8.     ATReadDat(type, addr-3, tmpDat, 4);                                         // 读取验证数据
  9.     ATWriteDat(type, addr-3, tmpBuf, 4);                                        // 恢复写入前
  10.   
  11.     return ((memcmp(tmpDat, "\xAA\x55\xFF\x00", 4) == 0) ? 0x00 : 0x01);  
复制代码
通过以上试验可以发现,读写24C02和24C16已经没有问题,完全可以争取的区分这两类芯片。但还是不能读取24C64之类的芯片。


进一步修改代码:


我们知道,由于芯片超地址时会出现覆盖写入,那么我们能不能把基础可能会出现覆盖的地方写入不同值了,如果发现覆盖就可以说明这个型号是错的,如果没有覆盖就说这个型号是对的:
  1.     u8 tmpBuf[] = {0x00, 0x00};
  2.     u8 tmpDat[] = {0xAA, 0x55};
  3.     
  4.     ATReadDat(type, ((addr+1)/2)-1, &tmpBuf[0], 1);                             // 数据暂存
  5.     ATReadDat(type, addr, &tmpBuf[1], 1);                            
  6.  
  7.     ATWriteDat(type, ((addr+1)/2)-1, &tmpDat[0], 1); 
  8.     ATWriteDat(type, addr, &tmpDat[1], 1);                                    // 写入验证数据
  9.    
  10.     memset(tmpDat, 0, 2);         
  11.     ATReadDat(type, ((addr+1)/2)-1, &tmpDat[0], 1);
  12.     ATReadDat(type, addr, &tmpDat[1], 1);                                     // 读取验证数据
  13.     
  14.     ATWriteDat(type, ((addr+1)/2)-1, &tmpBuf[0], 1);                            // 恢复写入前
  15.     ATWriteDat(type, addr, &tmpBuf[1], 1);
  16.   
  17.     return ((memcmp(tmpDat, "\xAA\x55", 2) == 0) ? 0x00 : 0x01);
复制代码
通过上面的代码验证获得,现在可以区别出24C64了,但却不能区别出24C02/16等。为什么会这样呢?连续的读写可以区别24C02/16但不能区别24C64,现在虽然能区别24C64了,可其他的反而不行了,能否把这种方法和连续写入多字节组合呢?
  1.     u8 tmpBuf[] = {0x00, 0x00, 0x00, 0x00};
  2.     u8 tmpDat[] = {0xAA, 0x55, 0xFF, 0x00};
  3.     
  4.     ATReadDat(type, ((addr+1)/2)-2, &tmpBuf[0], 2);                             // 数据暂存
  5.     ATReadDat(type, addr-1, &tmpBuf[2], 2);                            
  6.  
  7.     ATWriteDat(type, ((addr+1)/2)-2, &tmpDat[0], 2); 
  8.     ATWriteDat(type, addr-1, &tmpDat[2], 2);                                    // 写入验证数据
  9.    
  10.     memset(tmpDat, 0, 4);         
  11.     ATReadDat(type, ((addr+1)/2)-2, &tmpDat[0], 2);
  12.     ATReadDat(type, addr-1, &tmpDat[2], 2);                                     // 读取验证数据
  13.     
  14.     ATWriteDat(type, ((addr+1)/2)-2, &tmpBuf[0], 2);                            // 恢复写入前
  15.     ATWriteDat(type, addr-1, &tmpBuf[2], 2);
  16.   
  17.     return ((memcmp(tmpDat, "\xAA\x55\xFF\x00", 4) == 0) ? 0x00 : 0x01);
复制代码
通过上面的代码修改和试验,我们现在可以区别这三种型号了,通过我的推算应该是这种方法已经可以读取这一系列的各种型号,不过由于本人手里只有这3种卡片,其他的没有办法试验。

至于为什么这样写可以实现,本人也还没有一个完整的理论依据,大家不妨一起想想,如果你先想出来,请告诉我一下。
 
以上的程序却是能够实现型号辨别,但一个新的问题出现了。例如:向24C02等单地址卡片里边写入双地址数据时,由于时序的不同,芯片处理时,会把双地址的第2字节作为数据写入到单地址芯片中,由于我们的程序没有考虑这一点,所以,会导致其他地址的数据出现错误。

      下面我们举例说明:

       用上面的程序,我们判别型号的顺序是256->128->64->32->16->08->04->02->01,写入的地址是芯片的最大地址的最后两个字节和芯片最大地址的一半的最后两个字节,这样做的目的是试图通过数据覆盖来判断型号,例如,如果最大地址的最后两个字节覆盖了一半的最后两个字节,固然不是这个型号。

所以在按照24c256来想AT24C02写入数据是,我们是通过在地址:16382(0x3FFE)写入两个字节(0xAA, 0x55),再在地址32766(7FFE)写入两个字节(0xFF, 0x00),通过读取整片AT24C02芯片获得:

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

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

     通过仔细分析我们发现,芯片处理时,首先把地址16382(0x3FFE)分为2字节处理,高字节为地址即63(0x3F),低字节为数据0xFE,再加上AT24C02的页面大小为16字节,地址0x3F已经是页面的最高地址,后面再写入数据时就会发生页面翻转现象,而页面的起始地址正好是48(0x30),故而后面发生的两字节数据就写入了48和49.

     后面两个字节的数据也是完全一致的现象,所以,这个程序破坏来原始数据。
 
判断出卡片型号是必须的,但绝对不能破坏数据,为此我们还必须想办法解决这一问题:

下面我们谈谈另外一思路:通过页和地址来实现。

       我们知道AT24C01为8字节一页, AT24C02/04/08/16为16字节一页, AT24C32/64为32字节为一页, AT24C128/256为64字节为一页。我们完全可以通过写页数据,通过判断是否有数据被覆盖实现,过程如下:

      写入16字节数据->读写一致为AT24C02/04/08/16中一种,否则判断8字节是否一致,一致为AT24C01,否则为其他->通过写最大地址判断是否覆盖,来判断究竟是AT24C02/04/08/16中的那一致。其他型号过程一致,代码如下:
  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.     //--------------------------------- 单地址判断 -----------------------------
  9.     for (i=0; i<16; i++)                                                        // 初始化
  10.     {
  11.         tmpDat[i] = i;
  12.         cmpDat[i] = i;
  13.     }
  14.     
  15.     // AT24C01的页为8字节,AT24C02/04/08/16的页为16字节
  16.     // 通过读写16来判断页大小,从而区分AT24C01
  17.     ATCReadNByte(AT24C02, 0, tmpBuf, 16);                                       // 数据暂存
  18.     ATCWriteNByte(AT24C02, 0, tmpDat, 16);                                      // 写入验证数据  
  19.     memset(tmpDat, 0, 16);
  20.     ATCReadNByte(AT24C02, 0, tmpDat, 16);                                       // 读验证数据
  21.     
  22.     if (memcmp(tmpDat, cmpDat, 16) == 0)                                        // AT24C02/04/08/16
  23.     {
  24.         ATCWriteNByte(AT24C02, 0, tmpBuf, 16);                                  // 恢复数据
  25.         
  26.         // AT24C02/04/08/16中,通过页地址共同组成地址,故可以通过页区别型号
  27.         for (i=4; i>0; i--)                                                     
  28.         {
  29.             ATCReadByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, &tmpDat[0]);
  30.             ATCWriteByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, 0xAA);
  31.             ATCReadByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, &tmpDat[1]);
  32.             if (tmpDat[1] == 0xAA)
  33.             {
  34.                 ATCWriteByte((ATC_TYP)(i), ATC_Par[(ATC_TYP)(i)].MaxAddr, tmpDat[0]);
  35.                 return ((ATC_TYP)(i));
  36.             }
  37.         }
  38.     }
  39.     else
  40.     {
  41.         if (memcmp(&tmpDat[8], cmpDat, 8) == 0)                                 // AT24C01
  42.         {
  43.             ATCWriteNByte(AT24C01, 0, tmpBuf, 8);                               // 恢复数据
  44.             return AT24C01;
  45.         }
  46.     }
  47.  
  48.     //--------------------------------- 双地址判断 -----------------------------
  49.     for (i=0; i<64; i++)                                                        // 初始化
  50.     {
  51.         tmpDat[i] = i;
  52.         cmpDat[i] = i;
  53.     }
  54.     
  55.     ATCReadNByte(AT24C128, 0, tmpBuf, 64);                                      // 数据暂存
  56.     ATCWriteNByte(AT24C128, 0, tmpDat, 64);                                     // 写入验证数据  
  57.     memset(tmpDat, 0, 64);
  58.     ATCReadNByte(AT24C128, 0, tmpDat, 64);                                      // 读验证数据
  59.     
  60.     if (memcmp(tmpDat, cmpDat, 64) == 0)                                        // AT24C128/256
  61.     {
  62.         ATCWriteNByte(AT24C128, 0, tmpBuf, 64);                                 // 恢复数据
  63.         
  64.         ATCReadByte(AT24C256, 0, &tmpDat[0]);
  65.         ATCReadByte(AT24C256, ATC_Par[AT24C128].Capacity, &tmpDat[1]);
  66.         
  67.         ATCWriteByte(AT24C256, 0, 0xAA);
  68.         ATCWriteByte(AT24C256, ATC_Par[AT24C128].Capacity, 0x55);
  69.         
  70.         ATCReadByte(AT24C256, 0, &tmpDat[2]);
  71.         ATCReadByte(AT24C256, ATC_Par[AT24C128].Capacity, &tmpDat[3]);
  72.         if ((tmpDat[2] == 0xAA) && (tmpDat[3] == 0x55))
  73.         {
  74.             ATCWriteByte(AT24C256, 0, tmpDat[0]);
  75.             ATCWriteByte(AT24C256, ATC_Par[AT24C128].Capacity, tmpDat[1]);
  76.             return AT24C256;
  77.         }
  78.         else
  79.         {
  80.             ATCWriteByte(AT24C128, 0, tmpDat[0]);
  81.             return AT24C128;
  82.         }        
  83.     }
  84.     else                                                                        // AT24C128/256
  85.     {
  86.         if (memcmp(&tmpDat[32], cmpDat, 32) == 0) 
  87.         {
  88.             ATCWriteNByte(AT24C64, 0, tmpBuf, 32);
  89.             ATCReadByte(AT24C64, 0, &tmpDat[0]);
  90.             ATCReadByte(AT24C64, ATC_Par[AT24C32].Capacity, &tmpDat[1]);
  91.             
  92.             ATCWriteByte(AT24C64, 0, 0xAA);
  93.             ATCWriteByte(AT24C64, ATC_Par[AT24C32].Capacity, 0x55);
  94.             
  95.             ATCReadByte(AT24C64, 0, &tmpDat[2]);
  96.             ATCReadByte(AT24C64, ATC_Par[AT24C32].Capacity, &tmpDat[3]);
  97.             if ((tmpDat[2] == 0xAA) && (tmpDat[3] == 0x55))
  98.             {
  99.                 ATCWriteByte(AT24C64, 0, tmpDat[0]);
  100.                 ATCWriteByte(AT24C64, ATC_Par[AT24C32].Capacity, tmpDat[1]);
  101.                 return AT24C64;
  102.             }
  103.             else
  104.             {
  105.                 ATCWriteByte(AT24C32, 0, tmpDat[0]);
  106.                 return AT24C32;
  107.             }
  108.         }
  109.     }    
  110.  
  111.     return ATC_TYP_MAX;
  112. }
  113.  
复制代码
具体代码不再分析,代码确实能够实现型号识别,但是否破坏数据,暂时还没有发现,大家不妨试试,如果破坏了数据,我们再做进一步分析并改善。
 
下面我们再介绍一种比较简单,而且不会破坏数据的方法。

     我们知道从AT24C01~256之间,由于容量和地址的区别,我们可以把这一系列分为三大类:

    1. 单地址,直接8位地址操作:AT24C01/02
    2. 单地址,8位地址加3位页地址组合操作:AT24C04/08/16
    3. 双地址,直接16位地址操作:AT24C32/64/128/256

   由上面的三大类我们可以看出,要区别型号,可以通过先分类,再分别通过每一类中型号的差异进行进一步的区别。

       首先我们可以看出,从地址上来分可以把以上芯片分为单地址和双地址,从页面组合上来分我们可以把他们分为有组合和无组合两种,所以,我们可以通过这两种方法先把这系列芯片分为2类,之后再进行细分。例如:

       从地址上来分->单地址为AT24C01/02/04/08/16,双地址为AT24C32/64/128/256:
       
      1. 单地址5种芯片,有页组合的有3种,这三种中 AT24C16由3位组合,  AT24C08由2位组合,  AT24C04由一位组合,所以当我们读写0xAE地址正确时一定是AT24C16,如果不正确,读写0xA6正确时一定是  AT24C08,如果还不正确,读写0xA2正确时一定是  AT24C04,如果还不正确那,一定是  AT24C01/02中的一种,而对于  AT24C01/02来说,不同的只是地址范围,如果写地址0和地址128,如果数据覆盖,那一定是  AT24C01,如果没有覆盖那一定是  AT24C02.

      2. 双地址4种芯片,没有也组合,而不同的只有地址范围,这一定和  AT24C01/02是完全一致的,所以,由于区别的方法也和这两个芯片一样,通过覆盖可以轻松的判断出芯片型号。
  1. /************************************************************************************** 
  2. * FunctionName   : ATCReadType()
  3. * Description    : 写器件型号
  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.     
  13.     ATCReadNByte(AT24C32, 0, tmpBuf, 1);                                        // 读取双地址0的一字节暂存
  14.     ATCReadNByte(AT24C16, 0, &tmpBuf[1], 2);                                    // 读取单地址0的二字节暂存
  15.     
  16.     ATCWriteNByte(AT24C32, 0, "\xA5", 1);                                       // 按照双地址格式写入一字节数据
  17.     
  18.     ATCReadNByte(AT24C32, 0, tmpDat, 1);                                        // 按照双地址格式读取一字节数据
  19.     ATCReadNByte(AT24C16, 0, &tmpDat[1], 2);                                    // 按照单地址格式读取二字节数据
  20.     
  21.     if ((tmpDat[1] == 0x00) && (tmpDat[2] == 0xA5))                             // 单地址芯片             
  22.     {
  23.         ATCWriteNByte(AT24C16, 0, &tmpBuf[1], 2);                               // 恢复数据
  24.         
  25.         //-------------------------------- AT24c04/08/16 -----------------------
  26.         
  27.         for (i=AT24C16; i>AT24C02; i--)                                         // AT24c04/08/16
  28.         {
  29.             ATCReadByte(i, ATC_Par[i].MaxAddr, &tmpBuf[0]);
  30.             ATCWriteByte(i, ATC_Par[i].MaxAddr, 0xAA);
  31.             ATCReadByte(i, ATC_Par[i].MaxAddr, &tmpDat[0]);
  32.             ATCWriteByte(i, ATC_Par[i].MaxAddr, tmpBuf[0]);
  33.             
  34.             if (tmpDat[0] == 0xAA)
  35.             {
  36.                 return i;
  37.             }
  38.         }
  39.         
  40.         //-------------------------------- AT24c01/02 --------------------------
  41.         
  42.         ATCReadByte(AT24C02, 0, &tmpBuf[0]);
  43.         ATCReadByte(AT24C02, 128, &tmpBuf[1]);        
  44.         ATCWriteByte(AT24C02, 0, 0xAA);
  45.         ATCWriteByte(AT24C02, 128, 0x55);
  46.         
  47.         ATCReadByte(AT24C02, 0, &tmpDat[0]);
  48.         ATCReadByte(AT24C02, 128, &tmpDat[1]);
  49.         ATCWriteByte(AT24C02, 0, tmpBuf[0]);
  50.         ATCWriteByte(AT24C02, 128, tmpBuf[1]);
  51.         
  52.         return (tmpDat[0] == 0x55) ? AT24C01 : AT24C02;
  53.     }
  54.     else
  55.     {
  56.         if (tmpDat[0] == 0xA5)                                                  // 双地址芯片
  57.         {
  58.             ATCWriteNByte(AT24C256, 0, &tmpBuf[0], 1);                          // 恢复数据
  59.             
  60.             //-------------------------------- AT24c32/64/128/256 --------------
  61.             
  62.             for (i=AT24C256; i>AT24C16; i--)
  63.             {
  64.                 ATCReadByte(i, 0, &tmpBuf[0]);
  65.                 ATCReadByte(i, ATC_Par[i-1].Capacity, &tmpBuf[1]);
  66.                 
  67.                 ATCWriteByte(i, 0, 0xAA);
  68.                 ATCWriteByte(i, ATC_Par[i-1].Capacity, 0x55);
  69.                 
  70.                 ATCReadByte(i, 0, &tmpDat[0]);
  71.                 ATCReadByte(i, ATC_Par[i-1].Capacity, &tmpDat[1]);
  72.                 
  73.                 ATCWriteByte(i, 0, tmpBuf[0]);
  74.                 ATCWriteByte(i, ATC_Par[i-1].Capacity, tmpBuf[1]);
  75.                 
  76.                 if ((tmpDat[0] == 0xAA) && (tmpDat[1] == 0x55)) 
  77.                 {
  78.                     return i;
  79.                 }
  80.             }
  81.             
  82.             return AT24C256;
  83.         }
  84.         else                                                                    // 非AT系列芯片
  85.         {
  86.             return ATC_TYP_MAX;
  87.         }
  88.     }
  89. }
复制代码
 
对于上面的程序需要注意,我们的方法是通过写入数据之后读取进行判断的,所以在写入数据之前必须把要写入的地址数据暂存,完成判断后必须恢复,绝对不能破坏芯片类的数据。

       在单地址和双地址的判断中,我们按照两种方法进行数据暂存,因为我们刚开始并不知道卡片究竟是什么型号,所以,在判断出来后,按照单双地址分别恢复也保证数据的正确性。

      还有一点需要强调,我们在按照双地址方式,在地址0的地方写入0xA5数据,如果芯片确实是双地址,那么该数据一定写入地址0,数据数据为0xA5,但是如果该芯片为单地址,那么地址的低8为就被作为数据一起写入了,所以会导致,地址0开始写入两字节数据,一字节为0(地址的低8位被当做第一个数据了),一字节为0xA5(数据却作为第2字节数据写入了)。所以通过这两字节数据可以轻松的判断出究竟是单地址还是双地址。
关键字:程序读取  AT24系列  芯片型号 引用地址:浅谈如果通过程序读取AT24系列芯片型号

上一篇:单片机之串口数据处理
下一篇:IAR开发STM8字体异常问题解决

推荐阅读最新更新时间:2024-03-16 15:00

STM32芯片型号的命名规则
STM32平台的设计理念,开发人员通过选择产品可重新优化功能、存储器、性能和引脚数量,以最小的硬件变化来满足个性化的应用需求。 STM32型号的说明:以STM32F103RBT6这个型号的芯片为例,该型号的组成为7个部分,其命名规则如下: (1)STM32:STM32代表ARM Cortex-M3内核的32位微控制器。 (2)F:F代表芯片子系列。 (3)103:103代表增强型系列。 (4)R:R这一项代表引脚数,其中T代表36脚,C代表48脚,R代表64脚,V代表100脚,Z代表144脚。 (5)B:B这一项代表内嵌Flash容量,其中6代表32K字节Flash,8代表64K字节Flash,B代表128
[单片机]
AT24系列存储器数据串并转换接口的IP核设计
摘 要 AT24系列EEPROM芯片是基于I2C(Inter-Integrated Circuit)总线协议而设计的。该存储器与微处理器通信,需要把串行数据转换成并行数据,或把并行数据转换成串行数据后,通信过程才能进行。介绍用VHDL语言设计该存储器数据串并转换接口的IP核,从而通过硬件(FPGA或其他可编程芯片)实现AT24系列存储器与8位微处理器之间的并行通信。 关键词 I2C总线 AT24系列存储器 VHDL 串并转换 微处理器 1 I2C总线的基本概念 I2C总线协议是Philips公司推出的总线协议。它是多主机总线,通过2根线(SDA-aserial data line,SCL-a serial clock
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved