找回密码
 立即注册

QQ登录

只需一步,快速开始

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

24C02、24C16进行字节、页读取、页存取操作

[复制链接]
跳转到指定楼层
楼主
ID:372961 发表于 2019-9-26 12:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 Vence 于 2019-9-26 12:51 编辑

以下这篇文章是自己折腾了三天存储芯片后,并且能够成功进行字节操作、页操作的一篇应用型文章,不太想研究原理的可以直接采用本文的代码和注意事项。

在对24C02或者24C16进行字节、页读取、页存取前,我们需要弄清楚I2C协议、24C02/24C16存储空间、字节操作和页操作的时序
————————————————
版权声明:本文为CSDN博主「Pvence」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40814407/article/details/101228190

I2C协议:I2C是什么协议网上进行百度方可知道,以下只写使用代码

  1. void i2cStart(void)            //开始时序
  2. {
  3.   SDA=1;
  4.   SCL=1;
  5.   _delay(2);  //延时2μs
  6.   SDA=0;
  7.   _delay(2);
  8.   SCL=0;
  9. }

  10. void i2cStop(void)            //结束时序
  11. {
  12.   SDA=0;
  13.   _delay(2);
  14.   SCL=1;
  15.   _delay(2);
  16.   SDA=1;
  17. }

  18. void i2cAck_MCU(void)        //应答时序
  19. {
  20.   SDA=0;
  21.   _delay(2);
  22.   SCL=1;
  23.   _delay(2);
  24.   SCL=0;
  25.   _delay(2);
  26.   SDA=1;
  27.   _delay(4);
  28. }


  29. void i2cNoAck_MCU(void)      //非应答时序
  30. {
  31.   SDA=1;
  32.   _delay(2);
  33.   SCL=1;
  34.   _delay(2);
  35.   SCL=0;
  36.   _delay(2);
复制代码
24C02/24C16存储空间大小24C02就是有2Kbit = 2000/8 = 250个字节,24C16就是有16kbit  = 2000个字节,24C02一页最多可以写入8个字节,因此可以分成32页,24C16一页最多可以写入16个字节,因此可以分成128页。


字节写操作
  1. void WriteByte_24LC16B(unsigned char input)
  2. {
  3.   unsigned char bit_count;
  4.   for(bit_count=8;bit_count!=0;bit_count--)
  5.   {
  6.     _delay(2);
  7.     SDA=(_Bool)(input&0x80);
  8.     _delay(2);
  9.     SCL=1;
  10.     _delay(2);
  11.     SCL=0;
  12.     input=input<<1;
  13.     _delay(2);
  14.   }
  15.   SDA=1;
  16.   SDA_CTRL=1;        //这里需要看自己使用的芯片设置SDA的IO口为输入状态,我用的是HT45F67芯片,SDA端口设置为输入状态,用于判断SDA是否接到主机的应答信号
  17.   _delay(2);
  18.   SCL=1;
  19.   _delay(2);
  20.   if(SDA == 1)
  21.           ack = 0;
  22.   else
  23.     ack = 1;
  24.   SCL=0;
  25.   SDA_CTRL=0;    //此处根据自己所使用的芯片将SDA所在的Io口设置为输出状态
  26. }

  27. void Write_24LC16B(unsigned char Wdata,unsigned int RomAddress)
  28. {
  29.   unsigned char block;
  30.   WriteDeviceAddress=0B10100000;
  31.   block=RomAddress/256;
  32.   RomAddress=RomAddress%256;
  33.   WriteDeviceAddress=WriteDeviceAddress|(block<<1);
  34.   i2cStart();
  35.   WriteByte_24LC16B(WriteDeviceAddress);
  36.   WriteByte_24LC16B((unsigned char)RomAddress);
  37.   WriteByte_24LC16B(Wdata);
  38.   i2cStop();
  39.   _delay(5500);
  40. }
复制代码

字节读操作

  1. unsigned char ReadByte_24LC16B()
  2. {
  3.   unsigned char bit_count,rbyte=0;
  4.   SDA=1;
  5.   SDA_CTRL=1;
  6.   _delay(10);
  7.   for(bit_count=8;bit_count!=0;bit_count--)
  8.   {
  9.     rbyte=rbyte<<1;
  10.     _delay(2);
  11.     SCL=1;
  12.     rbyte=rbyte|((unsigned char)(SDA));
  13.     _delay(2);
  14.     SCL=0;
  15.     _delay(2);
  16.   }
  17.   SDA_CTRL=0;
  18.   return(rbyte);
  19. }


  20. unsigned char Read_24LC16B(unsigned int RomAddress)
  21. {
  22.   unsigned char output,block;
  23.   ReadDeviceAddress=0B10100001;
  24.   WriteDeviceAddress=0B10100000;
  25.   block=RomAddress/256;
  26.   RomAddress=RomAddress%256;
  27.   WriteDeviceAddress=WriteDeviceAddress|(block<<1);
  28.   ReadDeviceAddress=ReadDeviceAddress|(block<<1);
  29.   i2cStart();
  30.   WriteByte_24LC16B(WriteDeviceAddress);
  31.   WriteByte_24LC16B((unsigned char)RomAddress);
  32.   i2cStart();
  33.   WriteByte_24LC16B(ReadDeviceAddress);
  34.   output=ReadByte_24LC16B();
  35.   i2cNoAck_MCU();
  36.   i2cStop();
  37.   _delay(2000);
  38.   return(output);  
  39. }
复制代码

页写操作
  1. Wdata为输入数组的首地址,RomAddress为需要进行存储的地址,范围在0~2047之间,cnt为一次需要写入的字节个数,建议采用8的倍数的cnt,因为本函数不采用自动分页,不是8的倍数会在超出页写入最多的字节数之后覆盖掉原来的数。
  2. void WritePage_24LC16B(unsigned char *Wdata,unsigned int RomAddress,unsigned char cnt)
  3. {
  4.   unsigned char block;
  5.   WriteDeviceAddress=0B10100000;
  6.   block=RomAddress/256;
  7.   RomAddress=RomAddress%256;
  8.   WriteDeviceAddress=WriteDeviceAddress|(block<<1);
  9.   i2cStart();
  10.   WriteByte_24LC16B(WriteDeviceAddress);
  11.   WriteByte_24LC16B((unsigned char)RomAddress);
  12.   while(cnt--)
  13.   {
  14.           WriteByte_24LC16B(*Wdata++);
  15.   }
  16.   i2cStop();
  17. }

  18. 注意:连续进行多页写操作,需要在WritePage_24LC16B函数后添加150μs以上的延迟,这段时间,24C02内部需要将数据存储到芯片内部。
  19. 例子:
  20. D_buffer[8] = {1,2,3,4,5,6,7,8};
  21. WritePage_24LC16B(D_buffer,0,8);
  22. _delay(150);        //延迟150μs以及以上
  23. WritePage_24LC16B(D_buffer,8,8);
复制代码

页读操作
  1. void ReadPage_24LC16B(unsigned char *Rdata,unsigned int RomAddress,unsigned char cnt)
  2. {
  3.   unsigned char block;
  4.   ReadDeviceAddress=0B10100001;
  5.   WriteDeviceAddress=0B10100000;
  6.   block=RomAddress/256;
  7.   RomAddress=RomAddress%256;
  8.   WriteDeviceAddress=WriteDeviceAddress|(block<<1);
  9.   ReadDeviceAddress=ReadDeviceAddress|(block<<1);
  10.   i2cStart();
  11.   WriteByte_24LC16B(WriteDeviceAddress);
  12.   WriteByte_24LC16B((unsigned char)RomAddress);
  13.   i2cStart();
  14.   WriteByte_24LC16B(ReadDeviceAddress);
  15.   while(cnt>1)
  16.   {
  17.           *Rdata++ = ReadByte_24LC16B();
  18.           cnt--;
  19.           i2cAck_MCU();                        //发送完读地址后,需要应答一下
  20.   }
  21.   *Rdata = ReadByte_24LC16B();
  22.   i2cNoAck_MCU();                        //读取最后一个字节需要非应答
  23.   i2cStop();
  24.   _delay(2000);
  25. }
复制代码






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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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