找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 11244|回复: 3
打印 上一主题 下一主题
收起左侧

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

[复制链接]
跳转到指定楼层
楼主
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

  1. #include<reg52.h>
  2. #include"MY51.H"

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

  5. void delayus()         //需要4个机器周期,大概4.34us
  6. {
  7.         ;                                        //晶振频率11.0592M,机器周期为1.085微秒
  8. }

  9. void iic_start()  //启动信号
  10. {
  11.         sda=1;
  12.         scl=1;
  13.         delayus();                //sda和scl同为高电平保持4.7us以上
  14.         _nop_();                        //1.085us,共5.78us,下面sda=0是下降沿,不能计算在延时时间中
  15.         sda=0;                         //下降沿
  16.         delayus();                //sda低电平保持4us以上        ,这里是4.34us满足要求
  17. }

  18. void iic_stop()        //停止信号
  19. {
  20.         sda=0;_nop_();        //准备状态
  21.         scl=1;
  22.         delayus();                //该状态稳定时间要求保持4us以上
  23.         sda=1;                        //scl高电平期间,sda来一个上升沿
  24.         delayus();                //sda保持4.7us以上,4.34加上函数返回时间大于4.7us
  25.                                                 //注:此时scl和sda都为1       
  26. }

  27. void iic_sendByte(uchar byteData) //mcu发送一个字节
  28. {
  29.         uchar i;
  30.         uchar temp=byteData;
  31.         for(i=0;i<8;i++)
  32.         {
  33.                 temp=temp<<1;   //移动后最高位到了PSW寄存器的CY位中
  34.                 scl=0;                         //准备
  35.                 _nop_();                    //稳定一下
  36.                 sda=CY;                         //将待发送的数据一位位的放到sda上
  37.                 _nop_();
  38.                 scl=1;                     //每一个高电平期间,ic器件都会将数据取走
  39.                 _nop_();               
  40.         }

  41.         scl=0;                                //如果写成scl=1;sda=1就是停止信号,不能这么写
  42.         _nop_();                               
  43.         sda=1;                                //释放总线,数据总线不用时要释放
  44.         _nop_();
  45. }

  46. uchar iic_readByte() //读一个字节
  47. {
  48.         uchar i,temp;
  49.         scl=0;                                //准备读数据
  50.         _nop_();
  51.         sda=1;                                //释放总线
  52.         _nop_();

  53.         for(i=0;i<8;i++)
  54.         {
  55.                 scl=1;                        //mcu开始取数据
  56.                 delayus();                //scl为高电平后,ic器件就会将1位数据送到sda上
  57.                                                         //总共用时不会大于4.34us的,然后就可以让mcu读sda了
  58.                 temp=(temp<<1)|sda; //读一位保存到temp中
  59.                 scl=0;
  60.                 delayus();               
  61.         }
  62.         return temp;
  63. }

  64. bool iic_checkACK()                //处理应答信号
  65. {
  66.         uchar errCounts=255; //定义超时量为255次
  67.         scl=1;
  68.         _nop_();
  69.        
  70.         while(sda)
  71.         {        //在一段时间内检测到sda=0的话认为是应答信号
  72.                 if(0==errCounts)
  73.                 {
  74.                         scl=0;                  //钳住总线
  75.                         _nop_();
  76.                         return false; //没有应答信号
  77.                 }
  78.                 errCounts--;
  79.         }

  80.         scl=0;                          //钳住总线,为下1次通信做准备
  81.         _nop_();
  82.         return true;          //成功处理应答信号
  83. }

  84. void iic_init()        //总线初始化
  85. {
  86.         scl=1;
  87.         sda=1;
  88.         delayus();
  89. }

  90. void iic_sendACK(bool b_ACK)        //发送应答或非应答信号
  91. {
  92.         scl=0;                        //准备
  93.         _nop_();

  94.         if(b_ACK)                //ACK
  95.         {
  96.                 sda=0;
  97.         }
  98.         else                           //unACK
  99.         {
  100.                 sda=1;
  101.         }

  102.         _nop_();
  103.         scl=1;
  104.         delayus();                 //大于4us的延时
  105.         scl=0;                            //钳住scl,以便继续接收数据       
  106.         _nop_();
  107. }


  108. void AT24C02_writeByte(uchar address,uchar dataByte)//向24c02写一字节数据
  109. {
  110.         iic_start();
  111.         iic_sendByte(0xa0);//mcu写控制字,前4位固定1010,后三位地址0,末位0是写
  112.         iic_checkACK();                   //mcu处理应答信号
  113.         iic_sendByte(address);  //准备在指定地址处写入       
  114.         iic_checkACK();
  115.         iic_sendByte(dataByte); //写数据
  116.         iic_checkACK();
  117.         iic_stop();
  118.         delayms(2);       
  119.         //按字节写入时,24c02在接收到停止信号后将数据擦写到内部,这需要时间
  120.         //并且在这段时间内不会响应总线上的任何请求,故让mcu有2毫秒以上的等待       
  121. }

  122. void AT24C02_writeData(uchar address,uchar numBytes,uchar* buf)//写入任意长度数据
  123. {
  124.         while(numBytes--)
  125.         {
  126.                 AT24C02_writeByte(address++,*buf++);
  127.         }
  128. }

  129. void AT24C02_readData(uchar beginAddr,uchar dataSize,uchar* buf)//读取任意长度字节
  130. {
  131.         iic_start();                                        //起始信号
  132.         iic_sendByte(0xa0);                        //控制字,写
  133.         iic_checkACK();                                //处理应答信号
  134.         iic_sendByte(beginAddr);        //发送地址
  135.         iic_checkACK();                                //处理应答信号       
  136.         iic_start();                                   //发送起始信号
  137.         iic_sendByte(0xa1);                        //控制字,读
  138.         iic_checkACK();                                //处理应答信号
  139.         while(dataSize--)                                //读取dataSize个字节
  140.         {
  141.                 *buf++=iic_readByte();        //读取一个个字节并保存到缓冲区buf中
  142.                 iic_sendACK(dataSize);  //发送应答,当dataSize为0时发送非应答
  143.         }
  144.         iic_stop();                                                //发送停止信号
  145. }

  146. void main()
  147. {
  148.         uchar buf[2];                                        //接受数据的缓冲区
  149.         uchar arr[34]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,                           //0x00-0x0f
  150.                                                 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,//0x10-0x1f
  151.                                                 32,0x55};                                                                                                        //0x20-0x21
  152.         iic_init();                                                                                        //总线初始化
  153.         //AT24C02_writeByte(0x08,0x11);                          //向指定地址处写入一个字节数据,代码测试
  154.         AT24C02_writeData(0x00,sizeof(arr),arr);        //向指定地址处开始写入34字节的数据
  155.         AT24C02_readData(0x20,sizeof(buf),buf);   //从指定地址开始读2个字节
  156.         P1=buf[1];        //buf中的第二个元素就是arr中的最后一个数据0x55
  157.                                                                                        
  158.         while(1){P1=~P1;delayms(500);} //将这个0x55用led灯显示出来10101010变化
  159. }
复制代码


  1. my51.h头文件中主要用到
  2. #include<intrins.h>
  3. typedef unsigned char  uchar ;

  4. void delayms(uint16 ms)  //软延时函数
  5. {
  6.         uint16 i,j;
  7.         for(i=ms;i>0;i--)
  8.         {
  9.         for(j=113;j>0;j--)
  10.         {}
  11.         }
  12. }
复制代码



评分

参与人数 1黑币 +12 收起 理由
YJGG + 12 很给力!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:23606 发表于 2017-1-15 10:39 | 只看该作者
讲的很详细,很到位
回复

使用道具 举报

板凳
ID:58730 发表于 2018-3-24 17:10 | 只看该作者
谢谢分享
回复

使用道具 举报

地板
ID:66862 发表于 2018-10-31 23:18 | 只看该作者
楼主可以分享一下工程文件吗?我正需要学习这方面。谢谢!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表