源:硬件和软件兼容i2c协议的24Cxx系列EEPROM存储器

硬件上由于24c01的A0A1A2管脚不允许悬空,故暂时的想法是兼容24c02 ---24c16

使用一个dip8封装的芯片插座,A0 A1 A2管脚都悬空即可,换芯片方便

软件上24c02地址只有8位,而其他型号是大于8位的,故地址参数使用16位

256个字节作为一个大页,即largePage,测试芯片24c04空间有512字节

上代码,求测试和讨论

  1. #include "MY51.H"
  2. //转载请注明:http://xouou.iteye.com 求测试讨论
  3. //stc89c52rc,11.0592MHz晶振
  4. sbit sda=P2^; //总线连接口定义
  5. sbit scl=P2^; //总线连接口定义
  6.  
  7. void delayus() //需要4个机器周期,大概4.34us
  8. {
  9. ; //晶振频率11.0592M,机器周期为1.085微秒
  10. }
  11.  
  12. void iic_start() //启动信号
  13. {
  14. sda=;
  15. scl=;
  16. delayus(); //sda和scl同为高电平保持4.7us以上
  17. _nop_(); //1.085us,共5.78us
  18. sda=; //下降沿
  19. delayus(); //sda低电平保持4us以上 ,这里是4.34us满足要求
  20. }
  21.  
  22. void iic_stop() //停止信号
  23. {
  24. sda=;_nop_(); //准备状态
  25. scl=;
  26. delayus(); //该状态稳定时间要求保持4us以上
  27. sda=; //scl高电平期间,sda来一个上升沿
  28. delayus(); //sda保持4.7us以上,4.34加上函数返回时间大于4.7us
  29. //注:此时scl和sda都为1
  30. }
  31.  
  32. void iic_sendByte(u8 byteData) //mcu发送一个字节
  33. {
  34. u8 i;
  35. u8 temp=byteData;
  36. for(i=;i<;i++)
  37. {
  38. temp=temp<<; //移动后最高位到了PSW寄存器的CY位中
  39. scl=; //准备
  40. _nop_(); //稳定一下
  41. sda=CY; //将待发送的数据一位位的放到sda上
  42. _nop_();
  43. scl=; //每一个高电平期间,ic器件都会将数据取走
  44. _nop_();
  45. }
  46.  
  47. scl=; //如果写成scl=1;sda=1就是停止信号,不能这么写
  48. _nop_();
  49. sda=; //释放总线,数据总线不用时要释放
  50. _nop_();
  51. }
  52.  
  53. u8 iic_readByte() //读一个字节
  54. {
  55. u8 i,temp;
  56. scl=; //准备读数据
  57. _nop_();
  58. sda=; //释放总线
  59. _nop_();
  60.  
  61. for(i=;i<;i++)
  62. {
  63. scl=; //mcu开始取数据
  64. delayus(); //scl为高电平后,ic器件就会将1位数据送到sda上
  65. //总共用时不会大于4.34us,然后就可以让mcu读sda了
  66. temp=(temp<<)|sda; //读一位保存到temp中
  67. scl=;
  68. delayus();
  69. }
  70. return temp;
  71. }
  72.  
  73. bool iic_checkACK() //处理应答信号
  74. {
  75. u8 errCounts=; //定义超时量为255次
  76. scl=;
  77. _nop_();
  78.  
  79. while(sda) //在一段时间内检测到sda=0的话认为是应答信号
  80. {
  81. if(==errCounts)
  82. {
  83. scl=; //钳住总线
  84. _nop_();
  85. return FALSE; //没有应答信号
  86. }
  87. errCounts--;
  88. }
  89.  
  90. scl=; //钳住总线,为下1次通信做准备
  91. _nop_();
  92. return TRUE; //成功处理应答信号
  93. }
  94.  
  95. void iic_init() //总线初始化
  96. {
  97. scl=;
  98. sda=;
  99. delayus();
  100. }
  101.  
  102. void iic_sendACK(bool b_ACK) //发送应答或非应答信号
  103. {
  104. scl=; //准备
  105. _nop_();
  106.  
  107. if(b_ACK) //ACK 发送应该信号
  108. {
  109. sda=;
  110. }
  111. else //unACK 发送非应答信号
  112. {
  113. sda=;
  114. }
  115.  
  116. _nop_();
  117. scl=;
  118. delayus(); //大于4us的延时
  119. scl=; //钳住scl,以便继续接收数据
  120. _nop_();
  121. }
  122.  
  123. void AT24Cxx_writeByte(u16 address,u8 dataByte)//向24cxx写一字节数据
  124. {
  125. u8 largePage = address/; //24c04是512字节(寻址范围0~511),largePage最大值是1
  126. u8 addressOffset = address%; //largePage=0的话地址范围是(0~255)
  127. iic_start();
  128. iic_sendByte(0xa0|(largePage<<));//控制字,前4位固定1010,后三位是器件地址,末位0是写
  129. iic_checkACK(); //mcu处理应答信号
  130. iic_sendByte(addressOffset); //指定要写入的器件内地址在 largePage块中的偏移
  131. iic_checkACK();
  132. iic_sendByte(dataByte); //写数据
  133. iic_checkACK();
  134. iic_stop();
  135. delayms();
  136. //按字节写入时,24cxx在接收到停止信号后将数据擦写到内部,这需要时间
  137. //并且在这段时间内不会响应总线上的任何请求,故让mcu有2毫秒以上的等待
  138. }
  139.  
  140. void AT24Cxx_writeData(u16 address,u8 numBytes,u8* buf)//写入任意长度数据(最大256字节)
  141. {
  142. while(numBytes--)
  143. {
  144. AT24Cxx_writeByte(address++,*buf++);
  145. }
  146. }
  147.  
  148. void AT24Cxx_readData(u16 beginAddr,u8 dataSize,u8* buf)//读取任意长度字节到缓冲区buf中
  149. {
  150. u8 largePage = beginAddr/; //计算largePage,256字节为一大页
  151. u8 addressOffset = beginAddr%; //计算相对于largePage的偏移
  152. iic_start(); //起始信号
  153. iic_sendByte(0xa0|(largePage<<)); //控制字,写
  154. iic_checkACK(); //处理应答信号
  155. iic_sendByte(addressOffset); //要读取的目标地址偏移
  156. iic_checkACK(); //处理应答信号
  157. iic_start(); //发送起始信号
  158. iic_sendByte(0xa1|(largePage<<)); //控制字,读
  159. iic_checkACK(); //处理应答信号
  160. while(dataSize--) //读取dataSize个字节,最大256个字节
  161. { //dataSize用u16类型会暴掉ram的
  162. *buf++=iic_readByte(); //读取一个个字节并保存到缓冲区buf中
  163. iic_sendACK(dataSize); //发送应答,当dataSize为0时mcu发送非应答
  164. }
  165. iic_stop(); //发送停止信号
  166. }
  167.  
  168. void main()//测试
  169. {
  170. u8 buf[]; //接受数据的缓冲区
  171. u8 arr[]={0x06,,,,,0x55,0x33}; //待写入的数据
  172.  
  173. iic_init(); //总线初始化
  174. AT24Cxx_writeData(0x00+,sizeof(arr),arr); //向指定地址处开始写入7字节的数据
  175.  
  176. P1=0xff; //调试代码,用P1口的led显示
  177. delayms(); //调试代码
  178.  
  179. AT24Cxx_readData(0x00+,sizeof(buf),buf); //从指定地址开始读3个字节
  180. P1=buf[]; //也就是2 //led灯显示数值
  181.  
  182. while()
  183. {
  184. P1=~P1;
  185. delayms();
  186. }
  187. }
  1. //my51.h中主要用到
  2. #include <reg52.h>
  3.  
  4. #include "mytype.h"
  5.  
  6. void delayms(u16 ms) //软延时函数
  7. {
  8. u16 i,j;
  9. for(i=ms;i>;i--)
  10. {
  11. for(j=;j>;j--)
  12. {}
  13. }
  14. }
  1. 对代码进行了改进
  2. 去掉了在写数据时的
  3. delayms();
  4. 这句软延时代码低效 ,而且没有保障
  5.  
  6. 改成加一个检测函数
  7. bool check_icWriteComplete() //检测eeprom是否对内部擦写完成
  8. {
  9. iic_start();
  10. iic_sendByte(0xa0);
  11. return iic_checkACK();
  12. }

硬件和软件兼容i2c协议的24Cxx系列EEPROM存储器(转)的更多相关文章

  1. 【转】24Cxx 系列EEPROM通用程序及应用

    关于I2C 学习的时候介绍得最多的就是24C02 这里存储EEPROM了,但学的时候基本只是讲讲简单的I2C 的总线数据传输而已,即使先gooogle上搜索也绝大部分这这样的文章,很少有说到如何在实际 ...

  2. STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  3. 安装 SQL Server 2012 的硬件和软件要求(官方全面)

    以下各节列出了安装和运行 SQL Server 2012 的最低硬件和软件要求. 有关 SharePoint 集成模式下 Analysis Services 的要求的详细信息,请参阅硬件和软件要求(S ...

  4. 安装 SQL Server 2005 的硬件和软件要求(官方全面)

    SQL Server 2005 安装要求 本主题介绍了安装 SQL Server 205 的硬件和软件要求,以及查看安装文档的说明. 硬件和软件要求(32 位和 64 位) 访问 SQL Server ...

  5. 安装 SQL Server 2008 R2 的硬件和软件要求(转)

    以下各部分列出了安装和运行 SQL Server 2008 R2 的最低硬件和软件要求.有关 SharePoint 集成模式下的 Analysis Services 的要求的详细信息,请参阅硬件和软件 ...

  6. (原创) 巩固理解I2C协议(MCU,经验)

        题外话:这几天天气突然转冷了.今天已是11月23日了,查查黄历,昨天(11月22日)刚好是小雪,一夜温度骤降,果然老祖先的经验有灵验!冬天来了,还是多加加衣服,注意保暖! 1.Abstract ...

  7. 软件模拟I2C通讯

    I2C协议概述,有相当详细的名词解释: 通信数量受限于地址空间和400Pf总线电容. 所有的数据传输过程中,SDA线的电平变化必须在SCL为低电平时进行,SDA线的电平在SCL线为高电平时要保持稳定. ...

  8. UART、SPI、I2C协议异同点

    I2C.SPI.UART都是常见的低速板级通信协议,目前主流的SoC都内置了这些通讯协议的控制器,同样,各种传感器.Touch控制器.指纹模块.蓝牙模块.WIFI模块也都兼容这三种通信方式的一种或几种 ...

  9. i2c 协议解析

    1.基本概念 主机            初始化发送,产生时钟信号和终止发送的器件 从机            被主机寻址的器件 发送器        发送数据到总线的器件 接收器        从总 ...

随机推荐

  1. 【转】VC6.0打开或者添加工程文件崩溃的解决方法

    很多学习编程的同学都遇到这样的问题,在Windows操作系统下使用Visual C++ 6.0编程时,如果点击菜单中的[打开]或者[添加],或者按快捷键,都会弹出下图的对话框,出现程序崩溃并退出的情况 ...

  2. OC 消息机制本质

    转载自:http://m.blog.csdn.net/blog/util_c/10287909 在Objective-C中,message与方法的真正实现是在执行阶段绑定的,而非编译阶段.编译器会将消 ...

  3. css 7.30

    1.外提到内联元素,我们会想到有个display的属性是display:inline;这个属性能够修复著名的IE双倍浮动边界(float时margin)问题 2.一般来说,可以为所有块级元素应用 te ...

  4. 8--UI 初步认识 简易计算器

    UI是App的根基:一个App应该是先有UI界面,然后在UI的基础上增加实用功能(2)UI相对简单易学:UI普遍是学习过程中最简单的一块,能快速拥有成就感和学习兴趣(3)UI至关重要:开发中的绝大部分 ...

  5. pur-ftpd在ubuntu上的安装

    1.安装 apt-get install pure-ftpd 2.建立ftp目录 /var/ftp/public 3.建立ftp用户组 groupadd ftpgroup 4.建立ftp非系统用户 u ...

  6. C#无边框窗体移动 将事件绑定到想实现的控件上

    [DllImport("user32.dll")] public static extern bool ReleaseCapture(); [DllImport("use ...

  7. Spring注解基本解读

    在一个类中使用Spring对象,办法如下: 使用注解的形式注入 从ApplicationContext中获取. T t = new ApplicationContext.getBean("x ...

  8. java监控函数执行时间

    java监控函数执行时间 http://blog.csdn.net/ycg01/article/details/1467542 java监控函数执行时间 标签: javathreadclassstri ...

  9. HBase的Shell命令

    1.HBase提供了一个shell的终端给用户交互 2.HBase Shell的DDL操作 (1)先进入HBase的 Shell命令行,即HBASE_HOME/bin/hbase shell …… & ...

  10. 用telnet命令,POP3接收邮件

    昨天已经成功利用telnet命令发送了邮件,今天接着来,只能发送不能接收多郁闷. 邮件的接收这里是基于pop3协议的,pop3协议共定义了12条与接收相关的邮件,如下面简单解释: 首先是与登陆验证相关 ...