×
单片机 > 单片机程序设计 > 详情

51单片机学习笔记,模拟iic总线连续读写24c02存储器

发布时间:2020-06-08 发布时间:
|

AT24C02A, 2K SERIAL EEPROM:

Internally organized with 32 pages of 8 bytes each,
the 2K requires an 8-bit data word address for random word addressing.

24c02有32个页,每页8字节,本帖中不讨论页写的方式

-------------------------------------------------------------------




 
 

AT24C02内部设有一个8位控制寄存器,其每一位的含义如下: 
Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 
 1      0     1    0    A2   A1   A0  R/W 
其中前4位数据是芯片固定的标识,
A2/A1/A0用于选择总线上待访问的I2C器件,R/W=1读操作,R/W=0写操作;
I2C总线上最多可以扩展8片同样的2K容量EEPROM存储器,
或者是4片4Kb的EEPROM,
或者是2片容量为8Kb的EEPROM存储器。
或者是1片容量为16Kb的EEPROM存储器(此时硬件就固定了,因为A2/A1/A0已经被P2P1P0占用),
如果扩展8片2K以内容量的EEPROM存储器,每片存储器将对应一个地址,
我们的实验板上的AT24C02的A2/A1/A0引脚全部接地,
所以在实验中读写控制字分别为:0xa1/0xa0

 

主芯片stc89c52rc,晶振11.0592M

 

C代码  

  1. #include   

  2. #include "MY51.H"  

  3.   

  4. sbit sda=P2^0;      //总线连接口定义  

  5. sbit scl=P2^1;      //总线连接口定义  

  6.   

  7. void delayus()  //需要4个机器周期,大概4.34us  

  8. {  

  9.     ;                   //晶振频率11.0592M,机器周期为1.085微秒  

  10. }  

  11.   

  12. void iic_start()  //启动信号  

  13. {  

  14.     sda=1;  

  15.     scl=1;  

  16.     delayus();      //sda和scl同为高电平保持4.7us以上  

  17.     _nop_();            //1.085us,共5.78us,下面sda=0是下降沿,不能计算在延时时间中  

  18.     sda=0;          //下降沿  

  19.     delayus();      //sda低电平保持4us以上 ,这里是4.34us满足要求  

  20. }  

  21.   

  22. void iic_stop() //停止信号  

  23. {  

  24.     sda=0;_nop_();  //准备状态  

  25.     scl=1;  

  26.     delayus();      //该状态稳定时间要求保持4us以上  

  27.     sda=1;          //scl高电平期间,sda来一个上升沿  

  28.     delayus();      //sda保持4.7us以上,4.34加上函数返回时间大于4.7us  

  29.                         //注:此时scl和sda都为1      

  30. }  

  31.   

  32. void iic_sendByte(uchar byteData) //mcu发送一个字节  

  33. {  

  34.     uchar i;  

  35.     uchar temp=byteData;  

  36.     for(i=0;i<8;i++)  

  37.     {  

  38.         temp=temp<<1;   //移动后最高位到了PSW寄存器的CY位中  

  39.         scl=0;           //准备  

  40.         _nop_();            //稳定一下  

  41.         sda=CY;          //将待发送的数据一位位的放到sda上  

  42.         _nop_();  

  43.         scl=1;           //每一个高电平期间,ic器件都会将数据取走  

  44.         _nop_();          

  45.     }  

  46.   

  47.     scl=0;              //如果写成scl=1;sda=1就是停止信号,不能这么写  

  48.     _nop_();                  

  49.     sda=1;              //释放总线,数据总线不用时要释放  

  50.     _nop_();  

  51. }  

  52.   

  53. uchar iic_readByte() //读一个字节  

  54. {  

  55.     uchar i,temp;  

  56.     scl=0;              //准备读数据  

  57.     _nop_();  

  58.     sda=1;              //释放总线  

  59.     _nop_();  

  60.   

  61.     for(i=0;i<8;i++)  

  62.     {  

  63.         scl=1;          //mcu开始取数据  

  64.         delayus();      //scl为高电平后,ic器件就会将1位数据送到sda上  

  65.                             //总共用时不会大于4.34us的,然后就可以让mcu读sda了  

  66.         temp=(temp<<1)|sda; //读一位保存到temp中  

  67.         scl=0;  

  68.         delayus();        

  69.     }  

  70.     return temp;  

  71. }  

  72.   

  73. bool iic_checkACK()     //处理应答信号  

  74. {  

  75.     uchar errCounts=255; //定义超时量为255次  

  76.     scl=1;  

  77.     _nop_();  

  78.       

  79.     while(sda)  

  80.     {   //在一段时间内检测到sda=0的话认为是应答信号  

  81.         if(0==errCounts)  

  82.         {  

  83.             scl=0;        //钳住总线  

  84.             _nop_();  

  85.             return false; //没有应答信号  

  86.         }  

  87.         errCounts--;  

  88.     }  

  89.   

  90.     scl=0;            //钳住总线,为下1次通信做准备   

  91.     _nop_();  

  92.     return true;      //成功处理应答信号  

  93. }  

  94.   

  95. void iic_init() //总线初始化  

  96. {  

  97.     scl=1;  

  98.     sda=1;  

  99.     delayus();  

  100. }  

  101.   

  102. void iic_sendACK(bool b_ACK)    //发送应答或非应答信号  

  103. {  

  104.     scl=0;          //准备  

  105.     _nop_();  

  106.   

  107.     if(b_ACK)       //ACK  

  108.     {  

  109.         sda=0;  

  110.     }  

  111.     else               //unACK  

  112.     {  

  113.         sda=1;  

  114.     }  

  115.   

  116.     _nop_();  

  117.     scl=1;  

  118.     delayus();      //大于4us的延时  

  119.     scl=0;              //钳住scl,以便继续接收数据      

  120.     _nop_();  

  121. }  

  122.   

  123.   

  124. void AT24C02_writeByte(uchar address,uchar dataByte)//向24c02写一字节数据  

  125. {  

  126.     iic_start();  

  127.     iic_sendByte(0xa0);//mcu写控制字,前4位固定1010,后三位地址0,末位0是写  

  128.     iic_checkACK();        //mcu处理应答信号  

  129.     iic_sendByte(address);  //准备在指定地址处写入      

  130.     iic_checkACK();  

  131.     iic_sendByte(dataByte); //写数据  

  132.     iic_checkACK();  

  133.     iic_stop();  

  134.     delayms(2);   

  135.     //按字节写入时,24c02在接收到停止信号后将数据擦写到内部,这需要时间  

  136.     //并且在这段时间内不会响应总线上的任何请求,故让mcu有2毫秒以上的等待     

  137. }  

  138.   

  139. void AT24C02_writeData(uchar address,uchar numBytes,uchar* buf)//写入任意长度数据  

  140. {  

  141.     while(numBytes--)  

  142.     {  

  143.         AT24C02_writeByte(address++,*buf++);  

  144.     }  

  145. }  

  146.   

  147. void AT24C02_readData(uchar beginAddr,uchar dataSize,uchar* buf)//读取任意长度字节  

  148. {  

  149.     iic_start();                    //起始信号  

  150.     iic_sendByte(0xa0);         //控制字,写  

  151.     iic_checkACK();             //处理应答信号  

  152.     iic_sendByte(beginAddr);    //发送地址  

  153.     iic_checkACK();             //处理应答信号      

  154.     iic_start();                //发送起始信号  

  155.     iic_sendByte(0xa1);         //控制字,读  

  156.     iic_checkACK();             //处理应答信号  

  157.     while(dataSize--)               //读取dataSize个字节  

  158.     {  

  159.         *buf++=iic_readByte();  //读取一个个字节并保存到缓冲区buf中  

  160.         iic_sendACK(dataSize);  //发送应答,当dataSize为0时发送非应答  

  161.     }  

  162.     iic_stop();                     //发送停止信号  

  163. }  

  164.   

  165. void main()  

  166. {  

  167.     uchar buf[2];                   //接受数据的缓冲区  

  168.     uchar arr[34]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,               //0x00-0x0f  

  169.                         16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,//0x10-0x1f  

  170.                         32,0x55};                                                   //0x20-0x21  

  171.     iic_init();                                         //总线初始化  

  172.     //AT24C02_writeByte(0x08,0x11);             //向指定地址处写入一个字节数据,代码测试  

  173.     AT24C02_writeData(0x00,sizeof(arr),arr);    //向指定地址处开始写入34字节的数据  

  174.     AT24C02_readData(0x20,sizeof(buf),buf);   //从指定地址开始读2个字节  

  175.     P1=buf[1];  //buf中的第二个元素就是arr中的最后一个数据0x55  

  176.                                               

  177.     while(1){P1=~P1;delayms(500);} //将这个0x55用led灯显示出来10101010变化  

  178. }  

 

C代码  

  1. my51.h头文件中主要用到  

  2. #include   

  3. typedef unsigned char  uchar ;  

  4.   

  5. void delayms(uint16 ms)  //软延时函数  

  6. {  

  7.     uint16 i,j;  

  8.     for(i=ms;i>0;i--)  

  9.     {  

  10.         for(j=113;j>0;j--)  

  11.         {}  

  12.     }  

  13. }  

  

 


关键字:51单片机  模拟iic总线  读写24c02存储器 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容