51单片机——AT24C02(学习记录)

AT24C02介绍

AT24C02是一个2K位串行CMOS E2PROM, 内部含有**256个8位字节**。AT24C02有一个16字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。

功能描述:AT24C02支持总线数据传送协议I2C,协议规定任何将数据传送到总线的器件作为发送器,反之从总线接收的器件则为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件均可作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式,由于A0、A1和A2可以组成000~111八种情况,即通过器件地址输入端A0、A1和A2可以实现将最多8个AT24C02器件连接到总线上,通过进行不同的配置进行选择器件。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
WP高电平有效,这里直接接了GND,没有使用WP。

存储器的简单介绍

AT24C02就是一直存储器,在开始写代码之前先对存储器进行一个简单的了解。
RAM随机存储器,存储速度快,但掉电数据会丢失,ROM只读存储器,掉电不丢失但掉电存储数据不丢失。RAM主要分为SRAM(static ram,存储速度最快,容量较少,成本较高),DRAM(dynamic ram,成本更低,容量更大)两种。mask rom依靠电路存储数据,掉电不丢失,只能读不能写入数据。prom(可编程rom)只能写入一次数据。eprom(erasable programmable rom可擦除可编程rom),可编程也可擦除(需紫外线照射进行擦除)。e2prom(电可擦除可编程rom)。flash(闪存)。硬盘,靠磁介质存储数据。光盘用光信号存储数据。
在这里插入图片描述
在这里插入图片描述

I2C

由于该器件通过I2C总线接口进行操作,我们需要先了解一下I2C。
I2C,一种总线结构。单片机的品种规格有限,所以只能选用某种单片机来进行扩展。扩展的方法有两种:一种是并行总线,另一种是串行总线。由于串行总线的连线少,结构简单,往往不用专门的母板和插座而直接用导线连接各个设备。因此,采用串行线可大大简化系统的硬件设计。I2C串行总线则是一种高性能的串行总线。
硬件结构
I2C串行总线一般有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。
在这里插入图片描述
在这里插入图片描述
为避免总线信号的混乱,要求各设备连接到总线的输出端时必须是漏极开路(OD)输出或集电极开路(OC)输出。设备上的串行数据线SDA接口电路应该是双向的,输出电路用于向总线上发送数据输入电路用于接收总线上的数据。串行时钟线是双向的,作为控制总线数据传送的主机,要通过SCL输出电路发送时钟信号,还要检测总线上的SCL电平,以决定什么时候发送下一个时钟脉冲电平;作为接受主机命令的从机,要按总线上的SCL信号发出或接收SDA上的信号,也可以向SCL线发出低电平信号以延长总线时钟信号周期。总线空闲时,因各设备都是开漏输出,上拉电阻使SDA和SCL线都保持高电平。任一设备输出的低电平都将使相应的总线信号线变低。
主机是发出启动信号、发出时钟信号以及传送结束时发出停止信号的设备,通常都是微处理器。被主机寻访的设备称为从机。为进行通讯,每个接到I2C总线的设备都有一个唯一的地址,以便于主机寻访。

数据传输
在I2C总线传输过程中,将两种特定的情况定义为开始和停止条件(见图):当SCL保持“高”时,SDA由“高”变为“低”为开始条件;当SCL保持“高”且SDA由“低”变为“高”时为停止条件。开始和停止条件均由主机产生。
在这里插入图片描述
SDA线上的数据在时钟“高”期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,每次传输的字节不受限制,但每个字节必须要有一个应答ACK。如果一接收器件在完成其他功能(如一内部中断)前不能接收另一数据的完整字节时,它可以保持时钟线SCL为低,以促使发送器进入等待状态;当接收器准备好接受数据的其它字节并释放时钟SCL后,数据传输继续进行。I2C数据总线传送时序。
数据传送必须有应答。与应答对应的时钟脉冲由主控制器产生,发送器在应答期间必须下拉SDA线。当寻址的被控器件不能应答时,数据保持为高并使主控器产生停止条件而终止传输。在传输的过程中,在用到主控接收器的情况下,主控接收器必须发出一数据结束信号给被控发送器,从而使被控发送器释放数据线,以允许主控器产生停止条件。
在这里插入图片描述
在这里插入图片描述
主机在接收前需要释放SDA:主机和从机共享SDA线,如果主机不释放SDA线,从机无法操作总线。‌防止数据冲突‌:如果主机不释放SDA线,SDA线的电平状态不确定,可能会导致数据传输错误。在这里插入图片描述
I2C总线在开始条件后的首字节决定哪个被控器将被主控器选择。当主控器输出一地址时,系统中的每一器件都将开始条件后的前7位地址和自己的地址进行比较。若相同,该器件即认为自己被主控器寻址(被选中),R/W位决定是发送(读取)数据还是接收(写入)数据。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
固定地址是指AT24C02地址前4位固定,地址低4位的前三位是000,低4位的最后一位为读写标志位,所以从机写地址为0xA0或者0xA1

代码部分

代码分为3个板块,一个主函数,一个用来实现读写操作的模块,一个用来实现开始停止、发送和接收字节、应答。
main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "key.h"
#include "delay.h"
#include "AT24C02.h"

unsigned char keynum;
unsigned int num;

void main()
{
	LCD_Init();
	LCD_ShowNum(1,1,num,5);

	while(1)
	{
		keynum=key();
		if(keynum==1)//按键1实现加
		{
			num++;
			LCD_ShowNum(1,1,num,5);
		}
		if(keynum==2)//按键2实现减
		{
			num--;
			LCD_ShowNum(1,1,num,5);
		}
		if(keynum==3)//按键3实现写入数据
		{
			AT24C02_writebyte(0,num%256);//写入数据低8位(int占2个字节)
			delay(5);//每次写完必须延时5ms(写周期)
			AT24C02_writebyte(1,num/256);//写入数据高8位
			delay(5);
			LCD_ShowString(2,1,"write ok");
			delay(1000);
			LCD_ShowString(2,1,"        ");
		}
		if(keynum==4)//按键4实现读出数据
		{
			num=AT24C02_readbyte(0);//读出低8位数据
			num|=AT24C02_readbyte(1)<<8;//读出高8位数据并存取完整数据
			LCD_ShowNum(1,1,num,5);
			LCD_ShowString(2,1,"read ok");
			delay(1000);
			LCD_ShowString(2,1,"        ");
			
		}
	}
}

AT24C02.c

#include "I2C.h"
#include <REGX52.H>

#define AT24C02_address 0xA0//从机地址

void AT24C02_writebyte(unsigned char wordaddress,Data)
{
	I2C_start();
	I2C_sendbyte(AT24C02_address);//主机发送写的信号
	I2C_receiveack();//接收来自从机的应答
	I2C_sendbyte(wordaddress);//写入数据的地址
	I2C_receiveack();
	I2C_sendbyte(Data);//写入具体数据
	I2C_receiveack();
	I2C_stop();
}
unsigned char AT24C02_readbyte(unsigned char wordaddress)
{
	unsigned char Data;
		I2C_start();
	  I2C_sendbyte(AT24C02_address);//发送从机地址(谁)
	  I2C_receiveack();
	  I2C_sendbyte(wordaddress);//发送数据的地址(在哪)
	  I2C_receiveack();
	
	  I2C_start();
	  I2C_sendbyte(AT24C02_address|0x01);//发送读的信号(干什么)
	  I2C_receiveack();
	  Data=I2C_receivebyte();//读取c02数据
	  I2C_sendack(1);//不发送应答
	  I2C_stop();
	  return Data;
}

I2C.c

#include <REGX52.H>

sbit I2C_SCL=P2^1;//命名IO口
sbit I2C_SDA=P2^0;//命名IO口

void I2C_start(void)//开始信号
{
	I2C_SDA=1;//scl高电平期间sda由高变为低(开始信号)
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;//发出开始信号后将sda恢复到低电平
}

void I2C_stop(void)//结束信号
{
	I2C_SDA=0;//结束之前应答可能为1或0
	I2C_SCL=1;//scl高电平期间sda由0变为1
	I2C_SDA=1;
}

void I2C_sendbyte(unsigned char byte)//发送数据
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=byte&(0x80>>i);//scl低电平期间取出数据每一位放在sda上,高位在前
		I2C_SCL=1;//拉高scl读取数据位
		I2C_SCL=0;//拉低SCL方便后面数据放上SDA
	}
}

unsigned char I2C_receivebyte(void)//接收数据
{
	unsigned char i,byte=0x00;
	I2C_SDA=1;//释放SDA
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
	  if(I2C_SDA){byte|=(0x80>>i);}
	  I2C_SCL=0;
	}
	return byte;
}

void I2C_sendack(unsigned char ack)//发送应答
{
	I2C_SDA=ack;
	I2C_SCL=1;//读取ack
	I2C_SCL=0;
}

unsigned char I2C_receiveack(void)//接收应答
{
	unsigned char ack;
	I2C_SDA=1;//释放SDA
	I2C_SCL=1;//读取ack
	ack=I2C_SDA;//记录读取到的数据(应答)
	I2C_SCL=0;//拉低SCL方便后面数据放上SDA
	return ack;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值