硬件和软件兼容i2c协议的24Cxx系列EEPROM存储器(转)
源:硬件和软件兼容i2c协议的24Cxx系列EEPROM存储器
硬件上由于24c01的A0A1A2管脚不允许悬空,故暂时的想法是兼容24c02 ---24c16
使用一个dip8封装的芯片插座,A0 A1 A2管脚都悬空即可,换芯片方便
软件上24c02地址只有8位,而其他型号是大于8位的,故地址参数使用16位
256个字节作为一个大页,即largePage,测试芯片24c04空间有512字节
上代码,求测试和讨论
- #include "MY51.H"
- //转载请注明:http://xouou.iteye.com 求测试讨论
- //stc89c52rc,11.0592MHz晶振
- sbit sda=P2^; //总线连接口定义
- sbit scl=P2^; //总线连接口定义
- void delayus() //需要4个机器周期,大概4.34us
- {
- ; //晶振频率11.0592M,机器周期为1.085微秒
- }
- void iic_start() //启动信号
- {
- sda=;
- scl=;
- delayus(); //sda和scl同为高电平保持4.7us以上
- _nop_(); //1.085us,共5.78us
- sda=; //下降沿
- delayus(); //sda低电平保持4us以上 ,这里是4.34us满足要求
- }
- void iic_stop() //停止信号
- {
- sda=;_nop_(); //准备状态
- scl=;
- delayus(); //该状态稳定时间要求保持4us以上
- sda=; //scl高电平期间,sda来一个上升沿
- delayus(); //sda保持4.7us以上,4.34加上函数返回时间大于4.7us
- //注:此时scl和sda都为1
- }
- void iic_sendByte(u8 byteData) //mcu发送一个字节
- {
- u8 i;
- u8 temp=byteData;
- for(i=;i<;i++)
- {
- temp=temp<<; //移动后最高位到了PSW寄存器的CY位中
- scl=; //准备
- _nop_(); //稳定一下
- sda=CY; //将待发送的数据一位位的放到sda上
- _nop_();
- scl=; //每一个高电平期间,ic器件都会将数据取走
- _nop_();
- }
- scl=; //如果写成scl=1;sda=1就是停止信号,不能这么写
- _nop_();
- sda=; //释放总线,数据总线不用时要释放
- _nop_();
- }
- u8 iic_readByte() //读一个字节
- {
- u8 i,temp;
- scl=; //准备读数据
- _nop_();
- sda=; //释放总线
- _nop_();
- for(i=;i<;i++)
- {
- scl=; //mcu开始取数据
- delayus(); //scl为高电平后,ic器件就会将1位数据送到sda上
- //总共用时不会大于4.34us,然后就可以让mcu读sda了
- temp=(temp<<)|sda; //读一位保存到temp中
- scl=;
- delayus();
- }
- return temp;
- }
- bool iic_checkACK() //处理应答信号
- {
- u8 errCounts=; //定义超时量为255次
- scl=;
- _nop_();
- while(sda) //在一段时间内检测到sda=0的话认为是应答信号
- {
- if(==errCounts)
- {
- scl=; //钳住总线
- _nop_();
- return FALSE; //没有应答信号
- }
- errCounts--;
- }
- scl=; //钳住总线,为下1次通信做准备
- _nop_();
- return TRUE; //成功处理应答信号
- }
- void iic_init() //总线初始化
- {
- scl=;
- sda=;
- delayus();
- }
- void iic_sendACK(bool b_ACK) //发送应答或非应答信号
- {
- scl=; //准备
- _nop_();
- if(b_ACK) //ACK 发送应该信号
- {
- sda=;
- }
- else //unACK 发送非应答信号
- {
- sda=;
- }
- _nop_();
- scl=;
- delayus(); //大于4us的延时
- scl=; //钳住scl,以便继续接收数据
- _nop_();
- }
- void AT24Cxx_writeByte(u16 address,u8 dataByte)//向24cxx写一字节数据
- {
- u8 largePage = address/; //24c04是512字节(寻址范围0~511),largePage最大值是1
- u8 addressOffset = address%; //largePage=0的话地址范围是(0~255)
- iic_start();
- iic_sendByte(0xa0|(largePage<<));//控制字,前4位固定1010,后三位是器件地址,末位0是写
- iic_checkACK(); //mcu处理应答信号
- iic_sendByte(addressOffset); //指定要写入的器件内地址在 largePage块中的偏移
- iic_checkACK();
- iic_sendByte(dataByte); //写数据
- iic_checkACK();
- iic_stop();
- delayms();
- //按字节写入时,24cxx在接收到停止信号后将数据擦写到内部,这需要时间
- //并且在这段时间内不会响应总线上的任何请求,故让mcu有2毫秒以上的等待
- }
- void AT24Cxx_writeData(u16 address,u8 numBytes,u8* buf)//写入任意长度数据(最大256字节)
- {
- while(numBytes--)
- {
- AT24Cxx_writeByte(address++,*buf++);
- }
- }
- void AT24Cxx_readData(u16 beginAddr,u8 dataSize,u8* buf)//读取任意长度字节到缓冲区buf中
- {
- u8 largePage = beginAddr/; //计算largePage,256字节为一大页
- u8 addressOffset = beginAddr%; //计算相对于largePage的偏移
- iic_start(); //起始信号
- iic_sendByte(0xa0|(largePage<<)); //控制字,写
- iic_checkACK(); //处理应答信号
- iic_sendByte(addressOffset); //要读取的目标地址偏移
- iic_checkACK(); //处理应答信号
- iic_start(); //发送起始信号
- iic_sendByte(0xa1|(largePage<<)); //控制字,读
- iic_checkACK(); //处理应答信号
- while(dataSize--) //读取dataSize个字节,最大256个字节
- { //dataSize用u16类型会暴掉ram的
- *buf++=iic_readByte(); //读取一个个字节并保存到缓冲区buf中
- iic_sendACK(dataSize); //发送应答,当dataSize为0时mcu发送非应答
- }
- iic_stop(); //发送停止信号
- }
- void main()//测试
- {
- u8 buf[]; //接受数据的缓冲区
- u8 arr[]={0x06,,,,,0x55,0x33}; //待写入的数据
- iic_init(); //总线初始化
- AT24Cxx_writeData(0x00+,sizeof(arr),arr); //向指定地址处开始写入7字节的数据
- P1=0xff; //调试代码,用P1口的led显示
- delayms(); //调试代码
- AT24Cxx_readData(0x00+,sizeof(buf),buf); //从指定地址开始读3个字节
- P1=buf[]; //也就是2 //led灯显示数值
- while()
- {
- P1=~P1;
- delayms();
- }
- }
- //my51.h中主要用到
- #include <reg52.h>
- #include "mytype.h"
- void delayms(u16 ms) //软延时函数
- {
- u16 i,j;
- for(i=ms;i>;i--)
- {
- for(j=;j>;j--)
- {}
- }
- }
- 对代码进行了改进
- 去掉了在写数据时的
- delayms();
- 这句软延时代码低效 ,而且没有保障
- 改成加一个检测函数
- bool check_icWriteComplete() //检测eeprom是否对内部擦写完成
- {
- iic_start();
- iic_sendByte(0xa0);
- return iic_checkACK();
- }
硬件和软件兼容i2c协议的24Cxx系列EEPROM存储器(转)的更多相关文章
- 【转】24Cxx 系列EEPROM通用程序及应用
关于I2C 学习的时候介绍得最多的就是24C02 这里存储EEPROM了,但学的时候基本只是讲讲简单的I2C 的总线数据传输而已,即使先gooogle上搜索也绝大部分这这样的文章,很少有说到如何在实际 ...
- STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- 安装 SQL Server 2012 的硬件和软件要求(官方全面)
以下各节列出了安装和运行 SQL Server 2012 的最低硬件和软件要求. 有关 SharePoint 集成模式下 Analysis Services 的要求的详细信息,请参阅硬件和软件要求(S ...
- 安装 SQL Server 2005 的硬件和软件要求(官方全面)
SQL Server 2005 安装要求 本主题介绍了安装 SQL Server 205 的硬件和软件要求,以及查看安装文档的说明. 硬件和软件要求(32 位和 64 位) 访问 SQL Server ...
- 安装 SQL Server 2008 R2 的硬件和软件要求(转)
以下各部分列出了安装和运行 SQL Server 2008 R2 的最低硬件和软件要求.有关 SharePoint 集成模式下的 Analysis Services 的要求的详细信息,请参阅硬件和软件 ...
- (原创) 巩固理解I2C协议(MCU,经验)
题外话:这几天天气突然转冷了.今天已是11月23日了,查查黄历,昨天(11月22日)刚好是小雪,一夜温度骤降,果然老祖先的经验有灵验!冬天来了,还是多加加衣服,注意保暖! 1.Abstract ...
- 软件模拟I2C通讯
I2C协议概述,有相当详细的名词解释: 通信数量受限于地址空间和400Pf总线电容. 所有的数据传输过程中,SDA线的电平变化必须在SCL为低电平时进行,SDA线的电平在SCL线为高电平时要保持稳定. ...
- UART、SPI、I2C协议异同点
I2C.SPI.UART都是常见的低速板级通信协议,目前主流的SoC都内置了这些通讯协议的控制器,同样,各种传感器.Touch控制器.指纹模块.蓝牙模块.WIFI模块也都兼容这三种通信方式的一种或几种 ...
- i2c 协议解析
1.基本概念 主机 初始化发送,产生时钟信号和终止发送的器件 从机 被主机寻址的器件 发送器 发送数据到总线的器件 接收器 从总 ...
随机推荐
- 【转】VC6.0打开或者添加工程文件崩溃的解决方法
很多学习编程的同学都遇到这样的问题,在Windows操作系统下使用Visual C++ 6.0编程时,如果点击菜单中的[打开]或者[添加],或者按快捷键,都会弹出下图的对话框,出现程序崩溃并退出的情况 ...
- OC 消息机制本质
转载自:http://m.blog.csdn.net/blog/util_c/10287909 在Objective-C中,message与方法的真正实现是在执行阶段绑定的,而非编译阶段.编译器会将消 ...
- css 7.30
1.外提到内联元素,我们会想到有个display的属性是display:inline;这个属性能够修复著名的IE双倍浮动边界(float时margin)问题 2.一般来说,可以为所有块级元素应用 te ...
- 8--UI 初步认识 简易计算器
UI是App的根基:一个App应该是先有UI界面,然后在UI的基础上增加实用功能(2)UI相对简单易学:UI普遍是学习过程中最简单的一块,能快速拥有成就感和学习兴趣(3)UI至关重要:开发中的绝大部分 ...
- pur-ftpd在ubuntu上的安装
1.安装 apt-get install pure-ftpd 2.建立ftp目录 /var/ftp/public 3.建立ftp用户组 groupadd ftpgroup 4.建立ftp非系统用户 u ...
- C#无边框窗体移动 将事件绑定到想实现的控件上
[DllImport("user32.dll")] public static extern bool ReleaseCapture(); [DllImport("use ...
- Spring注解基本解读
在一个类中使用Spring对象,办法如下: 使用注解的形式注入 从ApplicationContext中获取. T t = new ApplicationContext.getBean("x ...
- java监控函数执行时间
java监控函数执行时间 http://blog.csdn.net/ycg01/article/details/1467542 java监控函数执行时间 标签: javathreadclassstri ...
- HBase的Shell命令
1.HBase提供了一个shell的终端给用户交互 2.HBase Shell的DDL操作 (1)先进入HBase的 Shell命令行,即HBASE_HOME/bin/hbase shell …… & ...
- 用telnet命令,POP3接收邮件
昨天已经成功利用telnet命令发送了邮件,今天接着来,只能发送不能接收多郁闷. 邮件的接收这里是基于pop3协议的,pop3协议共定义了12条与接收相关的邮件,如下面简单解释: 首先是与登陆验证相关 ...