单片机驱动AT24C02存储芯片
AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。
管脚名称
|
功能
|
A0 A1 A2
|
器件地址选择
|
SDA
|
串行数据/地址
|
SCL
|
串行时钟
|
WP
|
写保护
|
Vcc
|
+1.8V~ 6.0V 工作电压
|
Vss
|
地
|
了解了什么是AT24C02之后,我们具体要如何来操作它呢?
操作它之前,我们先来了解一下I2C总线,什么是I2C总线?
I2C总线(I2C
bus,Inter-IC bus)是一个双向的两线连续总线,提供集成电路(ICs)之间的通信线路。I2C总线是一种串行扩展技术,最早由Philips公司推出,广泛应用于电视,录像机和音频设备。I2C总线的意思是“完成集成电路或功能单元之间信息交换的规范或协议”。Philips公司推出的I2C总线采用一条数据线(SDA),加一条时钟线(SCL)来完成数据的传输及外围器件的扩展;对各个节点的寻址是软寻址方式,节省了片选线,标准的寻址字节SLAM为7位,可以寻址127个单元。
I2c总线的模拟方法:
SDA:数据线
SCL:时钟线
1、I2C起始信号:这里是SDA先开始,都为高电平
- SCL是高电平,而SDA是由低电平变为高电平,建立SDA保持的时间要>4.7us
-- 在SCL的时钟信号在高电平期间SDL信号产生一个下降沿。
起始之后的SDL和SCL都为0,同样保持时间也要>4.7us
2、I2C停止信号:这里是SDA先,SDA之前是低电平
SCL高电平期间,SDA线由低电平向高电平的变化表示终止信号
- 当SCL高电平的时候,SDA要产生一个上升沿,SDA产生上跳沿之前是低电平,
建立从低电平到高电平这个期间,时间间隔要大于4us
3、逻辑"1"和逻辑"0"表示:
逻辑"0"。注意在SCL跳变读取期间,要保持SDA的稳定
这是因为I2C总线读取数据SCL为高电平
如何发送一个字节:
1、首先发数据每次都是发一个字节,一个字节有8位的数据,所以我们需要定义一个8位的代表数据的变量,最可靠的就是unsigned char
发数据的时候是一位一位的发,所以需要有一个循环来发,发送数据发8位要从最高位开始,所以要将数据线偏移到最高的位置也就是
要右移7位,可以这么理解,看下图:
刚开始,dat表示:10000000
,dat表示1
现在要将dat偏移到最高位,那么dat要干掉所有的0,也就是要右移7位
10000000 >> 7 = 1;
接着再循环将dat重新一位一位的往左移,也就是从高位移到地位 1 << 7 = 10000000 for(dat = 0 ; dat < 8 ; dat++);
如何接受一个字节:
1、接受和发送其实是一样的,区别在于发送是写数据,而接受是读数据
接下来我们来看看AT24C02的操作方法.
AT24C02的操作方法:
1 、24C02的硬件连接方法:
引脚1、2、3、4接地线,7脚WE低电平有效
6脚是时钟线,5脚是数据线
2、写入过程:
1、发送器件地址
2、发送要写入24C02的内存地址
3、发送要写入的数据
发送器件地址的格式
__________________________________
| _ |
| 1 0 1 0 A2 A1 A0 R/W |
|_________________________________|
高四位1010是24CXX系列的固定器件地址,接下来是
A2、A1、A0是根据器件连接来决定的,我们的原理图
都接地所以是000,R/W为是选择读还是写,1的时候是读
0的时候是写,所以些的地址为0xA0
3、读出过程:
1、发送写入的器件地址(0xA0)
2、发送要读的24C02的内存地址
3、发送读出的器件地址(0xA1)
4、独取数据
当读取的时候,地址的最后一位R/W位是选择读,也就是该位为1,
所以读取的地址是0xA1
接下来用51单片机来写一个驱动程序:
/*-------------------------------------------------------------------------- I2C.H 这个头文件主要是模拟I2C总线的发送和接收还有AT24C02的使用, 因为51单片机本身不带有I2C的总线的功能。 本文件分为以下6个接口: 1、I2C总线的起始信号 2、I2C总线的结束信号 3、I2C总线发送数据 4、I2C总线接收数据 5、AT24C02写数据 6、AT24C02读数据 日期:2015年9月27日 开发者:杨源鑫 备注: 用户在使用该程序模块的时候只需调用最后两个函数即可,也就是AT24C02 的函数。 --------------------------------------------------------------------------*/ #ifndef __I2C_H #define __I2C_H #include <reg51.h> #include "i2c.h" sbit SCL=P2^1; //时钟线 sbit SDA=P2^0; //地址线 /** * 函数: void At24c02Write(unsigned char addr,unsigned char dat); * 函数功能:AT24C02写数据. * 使用方法:用户想要往里写数据的话就调用本函数,传入地址和数据即可 **/ void At24c02Write(unsigned char addr,unsigned char dat); /** * 函数: unsigned char At24c02Read(unsigned char addr); * 函数功能:AT24C02读数据. * 使用方法:用户想要读数据的话就调用本函数,传入地址即可 **/ unsigned char At24c02Read(unsigned char addr); /** * 函数: void I2C_Start_signal(void); * 函数功能:I2C总线的起始信号 **/ void I2C_Start_signal(void); /** * 函数: void I2C_Stop_signal(void); * 函数功能:I2C总线的结束信号 **/ void I2C_Stop_signal(void); /** * 函数: unsigned char I2C_SendByte(unsigned char dat, unsigned char ack); * 函数功能:I2C总线的写数据 **/ unsigned char I2C_SendByte(unsigned char dat, unsigned char ack); /** * 函数: unsigned char I2cReadByte(); * 函数功能:I2C总线的读数据 **/ unsigned char I2cReadByte(); /** * 函数: void Delay10us(); * 函数功能:10us延时 **/ void Delay10us(); #endif //__I2C_H
#include "i2c.h" /******************************************************************************* * 函数名 : Start_signal(void) * 函数功能 : I2C总线起始信号 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void I2C_Start_signal(void) { SDA = 1 ; Delay10us(); SCL = 1 ; Delay10us(); SDA = 0 ; Delay10us(); SCL = 0 ; Delay10us(); } /******************************************************************************* * 函数名 : Start_signal(void) * 函数功能 : I2C总线终止信号 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void I2C_Stop_signal(void) { SDA = 0 ; Delay10us(); SCL = 1 ; Delay10us(); Delay10us(); SDA=1; Delay10us(); } /******************************************************************************* * 函数名 : I2C_SendByte(unsigned char dat, unsigned char ack) * 函数功能 : I2C总线发送数据 * 输入 : dat,一个字节的数据 * 输出 : 发送成功返回1,发送失败返回0 * 备 注 : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0 *******************************************************************************/ unsigned char I2C_SendByte(unsigned char dat, unsigned char ack) { unsigned char a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。 Replay: b = 0 ; for(a=0; a<8; a++)//要发送8位,从最高位开始 { SDA = dat >> 7; //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号 dat = dat << 1; Delay10us(); SCL = 1; Delay10us();//建立时间>4.7us SCL = 0; Delay10us();//时间大于4us } SDA = 1; Delay10us(); SCL = 1; while(SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低 { b++; if(b > 200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束 { SCL = 0; Delay10us(); // return 0; goto Replay ; //如果超过200us没有应答则发送失败,或者为非应答,这时候系统启动重发机制 //使用goto语句返回到上面接着发 } } SCL = 0; Delay10us(); return 1; } /******************************************************************************* * 函数名 : I2cReadByte() * 函数功能 : I2C总线接收数据 * 输入 : 无 * 输出 : dat,数据 *******************************************************************************/ unsigned char I2cReadByte() { unsigned char a=0,dat=0; SDA=1; Delay10us(); for(a=0;a<8;a++)//接收8个字节 { SCL=1; Delay10us(); dat<<=1; dat|=SDA; Delay10us(); SCL=0; Delay10us(); } return dat; } /******************************************************************************* * 函数名 : Delay10us() * 函数功能 : 延时 * 输入 : 无 * 输出 : 无 *******************************************************************************/ void Delay10us() { unsigned char a,b; for(b=1;b>0;b--) for(a=2;a>0;a--); } /******************************************************************************* * 函 数 名 : void At24c02Write(unsigned char addr,unsigned char dat) * 函数功能 : 往24c02的一个地址写入一个数据 * 输 入 : 地址和数据 * 输 出 : 无 *******************************************************************************/ void At24c02Write(unsigned char addr,unsigned char dat) { I2C_Start_signal(); I2C_SendByte(0xa0, 1);//发送写器件地址 I2C_SendByte(addr, 1);//发送要写入内存地址 I2C_SendByte(dat, 0); //发送数据 I2C_Stop_signal(); } /******************************************************************************* * 函 数 名 : unsigned char At24c02Read(unsigned char addr) * 函数功能 : 读取24c02的一个地址的一个数据 * 输 入 : 无 * 输 出 : 无 *******************************************************************************/ unsigned char At24c02Read(unsigned char addr) { unsigned char num; I2C_Start_signal(); I2C_SendByte(0xa0, 1); //发送写器件地址 1010 0000 I2C_SendByte(addr, 1); //发送要读取的地址 I2C_Start_signal(); I2C_SendByte(0xa1, 1); //发送读器件地址 num=I2cReadByte(); //读取数据 I2C_Stop_signal(); return num; }
单片机驱动AT24C02存储芯片的更多相关文章
- LCD1602液晶显示模块的单片机驱动深入详解之软件篇(AVR)
LCD1602液晶显示模块的驱动虽然比七段数码管之类的显示要复杂一些,但实际上也并不是很难,最主要的还是初始化,为什么这么说呢?我们在调试一块新液晶屏的时候,都会先初始化看看有没有光标在闪,没有光标前 ...
- LCD1602液晶显示模块的单片机驱动深入详解之硬件篇
(本文以HD44780主控芯片的LCD1602为蓝本进行描述,其中的截图也来自HD44780数据手册,用户可自行搜索其datasheet,有部分整理网上的,但绝对要比你看到的要深入得多) 一.接口 L ...
- TMS320VC5509驱动AT24C02
1. 刚开始的波形不太对,比如如下代码 i2c_status = I2C_write( at24c02_write_buf, //pointer to data array , //length of ...
- [51单片机] EEPROM AT24c02 [存储\读取一个字节]
/*----------------------------------------------- 名称:IIC协议 EEPROM24c02 存数读取数据 内容:此程序用于检测EEPROM性能,测试方 ...
- 单片机IO口驱动能力
以STM32的IO口为例,最大的输出电流和灌入电流在芯片手册上都有说明.单个IO口一般都是十几mA到几十mA,同时总的VDD电流也有限制,大概为150mA.所以单片机驱动外设时,如果不是信号型而是功率 ...
- 51单片机 Keil C 延时程序的简单研究
应用单片机的时候,经常会遇到需要短时间延时的情况.需要的延时时间很短,一般都是几十到几百微妙(us).有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us以内,不然很 ...
- STM32 驱动1602液晶
利用STM32f103c8t6单片机驱动1602A液晶进行显示功能 上图即为写入信息后的效果图 本人用的是STM32的核心系统,无任何外设 库函数:3.5版本的库函数 驱动模式:采用4线驱动模式 供电 ...
- 基于basys2驱动LCDQC12864B的verilog设计图片显示
话不多说先上图 前言 在做这个实验的时候在网上找了许多资料,都是关于使用单片机驱动LCD显示,确实用单片机驱动是要简单不少,记得在FPGA学习交流群里问问题的时候,被前辈指教,说给我最好的指教便是别在 ...
- 实验1 单片机IO口应用及数码管显示
1. 单片机驱动蜂鸣器的实验: a) 说明:Lab51单片机实验板的蜂鸣器连接到单片机的P1.5 b) 基本要求:控制蜂鸣器每2秒响0.5秒. #include &l ...
随机推荐
- Java: How to resolve Access Restriction error
Issue: Access restriction: The constructor 'BASE64Decoder()' is not API (restriction on required lib ...
- Dynamics CRM2013 流程拷贝
在CRM中工作流是一个非常不错的功能,在实际业务场景中能满足各种业务需求.在我们设置一个工作流的时候,同一个实体一个逻辑功能可能需要多个工作流来实现,而多个工作流的不同之处可能只是启动时间或者是步骤中 ...
- iOS开发之Xcode常用调试(Debug)技巧总结
一.Xcode调试技巧之:NSLog 上面也提到了,在我们日常的开发过程中最常见的Debug方式就是打Log.而在OC语言中,打Log是采用NSLog方法.但是NSLog效率低下,具体原因可以看这篇博 ...
- 关于React Native项目在android上UI性能调试实践
我们尽最大的努力来争取使UI组件的性能如丝般顺滑,但有的时候这根本不可能做到.要知道,Android有超过一万种不同型号的手机,而在框架底层进行软件渲染的时候是统一处理的,这意味着你没办法像iOS那样 ...
- 【java多线程系列】java内存模型与指令重排序
在多线程编程中,需要处理两个最核心的问题,线程之间如何通信及线程之间如何同步,线程之间通信指的是线程之间通过何种机制交换信息,同步指的是如何控制不同线程之间操作发生的相对顺序.很多读者可能会说这还不简 ...
- 最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)
===================================================== 最简单的基于FFmpeg的视频编码器文章列表: 最简单的基于FFMPEG的视频编码器(YUV ...
- String&StringBuilder&StringBuffer总结
一.String的JVM内存分配测试与分析 String a="a"; String b="b"; String c="ab&qu ...
- 07_NoSQL数据库之Redis数据库:Redis的高级应用之事务处理、持久化操作、pub_sub、虚拟内存
事务处理 Redis对事务的支持目前还比较简单.Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令.当一个client在一个连接中发出mul ...
- 02-Git简单使用
Git安装(windows) https://code.google.com/p/msysgit/downloads/list 我们使用版本Git-1.7.9版本 百度网盘下载:链接:http://p ...
- Tapestry: Obtained resource by @Inject is NULL
Issue: When you inject some resources by @Inject Annotation in Tapestry Page or other components, yo ...