I2C总线下的EEPROM24C02的多字节读

1 篇文章 0 订阅
1 篇文章 0 订阅

I2C总线下的EEPROM的多字节读,并不困难,基本是在一个字节读的基础上稍微做一些改变就可以了,所以我们先回顾一下读单个字节的函数并了解一下他每一步的意思。
这里所讲解的读取数据都是EEPROM24C02下的选择性读操作:时序如下


时许分析如下,第一步启动总线,第二步器件寻址,第三步发送一个应答信号,第四步子器件寻址,第五步发送一个应答信号,第六步读取数据,第七步发送停止信号

********************************************************************************
	函数名称:E2ReadByte()
	返回参数:返回在从机读取到的一个字节
	参数列表:第一个参数为器件地址I2C_Add提供地址进行器件寻址,
						第二个参数为器件子地址addr是,函数将要从这个地址开始读取数据
*********************************************************************************/
uchar E2ReadByte(uchar I2C_Add,uchar addr)
{
	uchar dat;
	
	I2C_Start();//启动总线
	I2C_WriteByte(I2C_Add<<1);//器件寻址,写操作
	I2C_WriteByte(addr);//子器件寻址,告诉器件要从那个地方开始读操作
	
	I2C_Start();//启动总线
	I2C_WriteByte((I2C_Add<<1)|(0x01));//子器件寻址,读操作
	dat=I2C_ReadByte();
	SendACK(1);//响应一个NOACK
	
	I2C_Stop();//结束信号
	return dat;
}

我们先来分析一下上面代码的意思
I2C总线每次写入数据器件都需要发送一个应答信号,所以我把接收ACK的函数封装在了I2C数据写入函数内部,后面我会把代码放出来.
这是读取单个字节的EEPROM24C02的代码函数,首先代码的步骤如下
1.调用I2C总线启动函数,启动总线。
2.调用I2C总线进行器件寻址,把器件的地址赋予函数,方向上是伪写操作,伪写的意义在于方便下面子器件的操作.
3.调用I2C总线进行子器件寻址,这一步的操作与第3步相联系,这个子器件寻址的意义在于告诉器件它需要从这个地址开始读,相当于把子器件地址写给器件。
4.接下来是读取数据,因为第3步是伪写操作,也就是写操作,接下读取数据时方向改变了,所以需要重启总线。
5.再次调用I2C读取数据函数,把子器件的地址告诉主机,方向是读.
6.读取完数据之后主机需要给与一个应答信号给从机器件,告诉器件我现在不需要读取数据,1为NO ACK,0为ACK.
7.结束总线操作完毕.

好了,接下来进入正途,I2C总线的EEPROM的多字节读

先放代码:

/********************************************************************************
	函数名称:E2nReadByte()
	返回参数:
	参数列表:第一个参数为器件地址I2C_Add提供地址进行器件寻址,
						第二个参数为器件子地址addr是,函数将要从这个地址开始读取数据
						第三个参数为一个指针接收数组Buf,用来存取读到的数据,第四个参数len代表需要读多少个字节
*********************************************************************************/
void E2nReadByte(uchar I2C_Add,uchar addr,uchar *buf,uint len)
{

	I2C_Start();//启动总线
	I2C_WriteByte(I2C_Add<<1);//器件寻址,执行写操作,从机应答在内部操作
	I2C_WriteByte(addr);//子器件寻址,告诉器件要从那个地方开始读操作
	
	I2C_Start();//启动总线
	I2C_WriteByte((I2C_Add<<1)|(0x01));//子器件寻址,方向是读操作
	while(len>1)
	{
		*buf++=I2C_ReadByte();//读取一个字节
		SendACK(0);//主机发送一个ACK,告诉从机我还需要读取数据
		len--;
	}
	*buf=I2C_ReadByte();//最后一个字节
	SendACK(1);//响应一个NOACK
	I2C_Stop();//结束信号
}

这里只是稍微做了一些小修改,增加了一个while循环,并且使用一个buf数组保存数据,因为是连续读取字节,所以每次读取完一个字节之后记得需要发送一个ACK应答信号给从机,告诉它我还需要再次读取数据。

下面是配套的I2C总线代码:

bit I2C_WriteByte(uchar dat)
{
	uchar temp;
	bit ack;
	for(temp=0x80;temp!=0;temp>>=1)//1010 0000
	{//0000 0000
		if( (temp&dat) ==0)//检查当前为是0还是1
			SDA=0;
		else 
			SDA=1;
		
		I2C_delay();//延时至少4.7us后拉高时钟线
		SCL=1;
		I2C_delay();//延时保持拉高至少4us
		SCL=0;//保持拉高至少4us之后拉低
		}
		ack=I2C_Ack();//接收一个ACK
		return ack;
}
bit I2C_Ack()
{
	bit ack;
	SDA=1;//主机主动释放SDA,为读ACK做准备
	I2C_delay();//为SCL低电平延时至少4.7us
	SCL=1;//延时之后拉高电平
	ack=SDA;//读取ACK
	I2C_delay();//为SCL高电平延时至少4us
	
	SCL=0;//拉低SCL,释放掉
	
	
	return ack;
}
//给器件发送一个ACK应答
void SendACK(bit ACk)
{
	SDA=ACk;//释放总线
	I2C_delay();//保持ACK拉低至少4.7us
	SCL=1;
	I2C_delay();
	SCL=0;
	
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值