51单片机——AT24C02_EEPROM驱动-模拟IIC通讯32页8字节缓存1.1版本

1、优化上节《51单片机——AT24C02_EEPROM驱动-模拟IIC通讯32页8字节缓存1.0》里的代码。

2、增添了读取AT24C02的状态、增添了有多少个AT24C02器件。

3、主要优化读、写,页读、页写,擦除里的代码,减少不必要的代码。

#ifndef __AT24C02_H__
#define	__AT24C02_H__

extern unsigned char Mount_DDR_AT24C02[8];//挂载的器件地址,若为0则表示没有器件
extern unsigned char page_data_AT24C02[8];//页读取出来的数据存放位置

//读AT24C02状态是否在忙是否存在此器件读取时间10ms最大
extern bit read_status_AT24C02(unsigned char DDR);
//检测挂载多少个AT24C02,并将挂载的器件地址下入Mount_DDR_AT24C02数组里面
extern unsigned char Mount_Several_AT24C02(void);

//向某个器件存入数据,字节写,ddr表示器件地址,a_datax表示要将数据准备写入eeprom哪个地方,datax表示要写入到eeprom里的数据
//函数返回1表示写入成功,0表示写入失败
extern bit write_1byte_at24c02(unsigned char DDR, unsigned char a_datax, unsigned char datax);

//向器件存入数据,页写,ddr表示器件地址,page表示要EEPROM那页,数组datax【8】表示要写入8个数据
//函数返回1表示写入成功,0表示写入失败
extern bit write_page_at24c02(unsigned char DDR, unsigned char page, unsigned char datax[8]);

//向器件读取数据,字节读
//函数返回0表示通讯失败,不为0则读取正常。
extern unsigned char read_1byte_at24c02(unsigned char DDR, unsigned char a_datax);

//向器件读取数据,页读,数据将会存放在page_data_AT24C02[]数组里
extern unsigned char read_page_at24c02(unsigned char DDR, unsigned char page);

//擦除器件数据 ddr为器件地址,本开发板器件地址为0xa0 (0xa0写  0xa1读)
//函数返回1表示擦除成功,0表示擦除失败,并且iic通讯异常
extern bit ERASE_at24c02(unsigned char DDR);

#endif // !__AT24C02_H__

//P2^1;//时钟连接P2.1口
//P2^0;//时钟连接P2.0口

//AT24C02具有8字节页写缓存器,之前我写的代码有问题
//at24c02芯片地址为0101 0 A2 A1 A0最后3位看原理图,在本单片机里芯片地址位0101 000
//at24c02芯片内部地址为256字节,一页8个字节,共计32页,0x00表示第0页,0x08表示第2页,0x10表示第3页后面依次类推
//页写:发送8个字节的数据,每发送一个字节,芯片响应一个应答信号,同时,寻址字节低位自动加1,而高位不变。
//字节写:写地址,写数据,接收应答,然后在写地址,再写数据,在接收应答。。。。。。。
#include "iic.h"

unsigned char Mount_DDR_AT24C02[8] = {0};
unsigned char page_data_AT24C02[8]={0};
static unsigned char datax;//读取芯片的数据


//读AT24C02状态是否在忙是否存在此器件,最大读取时间10ms
bit read_status_AT24C02(unsigned char DDR)
{
	unsigned char k = 0;
	do
	{
		k++;
		START_IIC();
		write_1_byte_IIC(DDR);
		if (!read_ACK_IIC())
		{
			STOP_IIC();
			return 1;//器件存在且不忙
		}
		STOP_IIC();
		delay_ms(1);//延迟1ms..............................................................
	} while (k<11);//最大10ms等待IIC器件,别的大佬说是这个器件最大等待时长就是10毫秒之内响应
	return 0;//器件不存在或通讯异常
}

//检测挂载多少个AT24C02
unsigned char Mount_Several_AT24C02(void)
{
	unsigned char i=0;//流水号
	unsigned char j=0;//挂载器件个数
	unsigned char DDR = 0x50;//首器件地址
	unsigned char DDRx;
	for (i = 0; i < 8; i++)
	{
		DDRx = DDR << 1;
		if (read_status_AT24C02(DDRx))
		{
			j++;
			Mount_DDR_AT24C02[i] = DDR;
		}
		else
		{
			Mount_DDR_AT24C02[i] = 0;
		}
		DDR++;
	}
	return j;
}

//向某个器件存入数据,字节写,ddr表示器件地址,a_datax表示要将数据准备写入eeprom哪个地方,datax表示要写入到eeprom里的数据
//函数返回1表示写入成功,0表示写入失败
bit write_1byte_at24c02(unsigned char DDR,unsigned char a_datax,unsigned char datax)
{
	DDR <<= 1;
	if (read_status_AT24C02(DDR))//读取DDR器件是否在忙或不存在此器件
	{
		START_IIC();
		write_1_byte_IIC(DDR);//器件
		if (!read_ACK_IIC())
		{
			write_1_byte_IIC(a_datax);//地址
			if (!read_ACK_IIC())
			{
				write_1_byte_IIC(datax);//数据
				if (!read_ACK_IIC())
				{
					STOP_IIC();
					if (read_status_AT24C02(DDR))//延迟一段时间让at24c02开始写数据进入eeprom里面
						return 1;//函数返回1,iic通讯正常
					else
						return 0;//函数返回0,iic通讯异常
				}
			}
		}
	}
	else
		return 0;//函数返回0,iic通讯异常
	STOP_IIC();
	return 0;//函数返回0,iic通讯异常
}

//向器件存入数据,页写,ddr表示器件地址,a_datax表示要EEPROM地址,数组datax【8】表示要写入8个数据
//函数返回1表示写入成功,0表示写入失败
bit write_page_at24c02(unsigned char DDR,unsigned char page, unsigned char datax[8])
{
	unsigned char i=0;//流水号
	DDR <<= 1;
	page <<= 3;//类似于page=page*8;
	if (read_status_AT24C02(DDR))//读取DDR器件是否在忙或不存在此器件
	{
		START_IIC();//iic通讯开始信号
		write_1_byte_IIC(DDR);//0xa0表示at24c02器件地址,0表示要向它接下来写入数据
		if (!read_ACK_IIC())//检测从器件ACK信号
		{
			write_1_byte_IIC(page);//第page页的0地址准备写入数据
			if (!read_ACK_IIC())//检测从器件ACK信号
			{
				for (i = 0;i < 8;i++)//共计写8个字节数据,每次写入一页
				{
					write_1_byte_IIC(datax[i]);//开始向eeprom写入数据
					if (!read_ACK_IIC());//读取ACK
					else
						goto look;
					if (i == 7)
					{
						STOP_IIC();//第page页写入完成
						if (read_status_AT24C02(DDR))//延迟一段时间让at24c02开始写数据进入eeprom里面
							return 1;//函数返回1,本次通讯结束
						else
							return 0;//函数返回0,iic通讯异常
					}
				}
			}
		}
	}
	else
		return 0;//函数返回0,iic通讯异常
look:
	STOP_IIC();
	return 0;//函数返回0,iic通讯异常
}

//选择地址从器件读取数据,字节读
//函数返回0表示通讯失败,不为0则读取正常。
unsigned char read_1byte_at24c02(unsigned char DDR, unsigned char a_datax)
{//先开始信号,空写器件,接收应答,发送空写eeprom地址,接收应答,发送开始信号,发送读器件,接收应答,接收发来的数据
	DDR << 1;
	DDR += 1;
	if (read_status_AT24C02(DDR))//读取DDR器件是否在忙或不存在此器件
	{
		START_IIC();//开始信号
		write_1_byte_IIC(DDR & 0xfe);//操作地址  空写
		if (!read_ACK_IIC())
		{
			write_1_byte_IIC(a_datax);//eeprom地址那页的第几个
			if (!read_ACK_IIC())
			{
				START_IIC();
				write_1_byte_IIC(DDR);//器件地址及准备读取数据
				if (!read_ACK_IIC())
				{
					datax = read_1_byte_IIC();
					write_ACK_IIC(1);//发送No ack
					STOP_IIC();//结束本次通讯
					return datax;//返回结果给函数
				}
			}	
		}	
	}
	else
		return 0;//函数返回0,iic通讯异常
	STOP_IIC();
	return 0;//函数返回0,iic通讯异常
}

//向器件读取数据,页读,数据将会存放在page_data_AT24C02[]数组里
unsigned char read_page_at24c02(unsigned char DDR, unsigned char page)
{
	unsigned char i=0;//流水号
	DDR <<= 1;
	DDR += 1;
	page<<=3;
	if (read_status_AT24C02(DDR))//读取DDR器件是否在忙或不存在此器件
	{
		START_IIC();
		write_1_byte_IIC(DDR);
		if (!read_ACK_IIC())
		{
			write_1_byte_IIC(page);
			if (!read_ACK_IIC())
			{
				for(i = 0;i < 8;i++)
				{
					page_data_AT24C02[i] = read_1_byte_IIC();
					if(i==7)
					{
						write_ACK_IIC(0);//发送NO应答
						STOP_IIC();
						return 1;//函数返回1,iic通讯正常
					}
					write_ACK_IIC(1);//发送应答信号,继续接收数据
				}
			}
			else
			{
				STOP_IIC();
				return 0;//函数返回0,iic通讯异常
			}	
		}
		else
		{
			STOP_IIC();
			return 0;//函数返回0,iic通讯异常
		}
		
	}
	return 0;//函数返回0,iic通讯异常
}

//擦除器件数据 ddr为器件地址,本开发板器件地址为0xa0 (0xa0写  0xa1读)
//函数返回1表示擦除成功,0表示擦除失败,并且iic通讯异常
bit ERASE_at24c02(unsigned char DDR)
{
	unsigned char i=0;//流水号
	unsigned char j=0;//流水号
	DDR << 1;
	if (read_status_AT24C02(DDR))//读取DDR器件是否在忙或不存在此器件
	{
		START_IIC();//iic通讯开始信号
		write_1_byte_IIC(DDR);//0xa0表示at24c02器件地址,0表示要向它接下来写入数据
		if (!read_ACK_IIC())//检测从器件ACK信号
		{
			for (i = 0;i < 32;i++)//循环32页
			{
				write_1_byte_IIC(i*8);//向i页,第0地址准备写入数据
				if (!read_ACK_IIC())//检测从器件ACK信号
				{
					for (j = 0;j < 8;j++)//共计写8个字节数据,每次擦除一页
					{
						write_1_byte_IIC(0xff);//开始写1即擦除eeprom
						if (!read_ACK_IIC());//读取ACK
						else
							goto look;
						if (j == 7)
						{
							STOP_IIC();//第i页写入完成
							if (read_status_AT24C02(DDR))//延迟一段时间让at24c02开始写数据进入eeprom里面
							{
								if (i == 31)//判断没有ack应答32页是否传送完了,若传送完了就结束通讯
									return 1;	//函数返回1表示本次擦除eeprom成功
							}
							else
								goto look;
						}
					}
				}
				else
					goto look;
			}
		}
	}
	else
		return 0;//函数返回0,iic通讯异常
look:
	STOP_IIC();
	return 0;//函数返回0,iic通讯异常
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金丝草

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值