EEPROM驱动详解

本文详细介绍了如何根据24LC16的数据手册编写单片机驱动,包括容量计算、地址空间理解以及写操作和读操作的时序分析。通过实例展示了写入和读取数据的函数实现,帮助开发者理解I2C通信协议在EEPROM驱动中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在单片机开发中,经常使用EEPROM作为存储设备保存数据,如何根据数据手册编写驱动,我们以24LC16为例进行分析。

一.分析数据手册

1.1容量的计算

The Microchip Technology Inc. 24AA16/24LC16B (24XX16*) is a 16 Kbit Electrically Erasable PROM,Organized as 8 blocks of 256 bytes (8 x 256 x 8)

解释:16 Kbit 是多少字节的容量 ,1K是1024 16*1024/8=16*128=2048字节。

所以:24C01 容量 1*128=128字节

24C02 容量 2*128=256字节 24C08 容量 8*128=1024字节

1.2 地址空间

24LC16有2048个字节的地址空间,用户在分配地址范围时,地址范围为0x0--0x7ff,手册中写到2048个字节被分成8个块,每个块256字节。那么地址范围中的(9-11位)0-7代表着8个块地址。

二.看写操作时序

开始->写控制字->ACK->写字节地址->ACK- >数据->ACK->结束

 1.开始位的时序

 根据上图可知:

 I2C开始条件:SCL高电平, SDA 由高变低

 I2C结束条件:SCL高电平, SDA 由低变高

void I2CStart()
{
    SDA_OUT_high();    
    SCL_high();
    I2CDelay();
    SDA_OUT_low();
    I2CDelay();
    SCL_low();
}

2.写控制字:告诉机是读操作,还是写操作,读写那个块地址

  用户编码地址范围(0-0x7ff)共2048个字节,那么地址0x700的地址,7就是块地址,写控制字时要将块地址写入从机。

 2.1 写函数

static unsigned char  I2C_WriteByte(unsigned char byte)
{
	unsigned char i;
	SDA_OUT(); 
    for(i=0;i<8;i++)
    {
		if(byte & 0x80)  
		{
		    SDA_OUT_high();
		}
		else
		{
			SDA_OUT_low();
		}
		I2CDelay();
		SCL_high();
		I2CDelay();
		SCL_LOW();           //scl=0  data change
		byte  <<= 1;
	} 
	SDA_in();    //SDA PORT input 
	I2CDelay();
	SCL_high();
	I2CDelay();
	if(I2C_SDA == 1)   //ACK  read SDA port 
	{
		SCL_high();     no ack
		return 0;
	}
	SCL_LOW();
	I2CDelay();
	return 1;
}

使用  I2C_WriteByte()函数 写入控制字I2C_WriteByte(addr);

3.ACK 应答位

当主机给从机写入地址后,要求从机在接收一个字节后产生一个应答,因此主机会产生一个时钟

在这个时钟期间,从机必须把SDA 拉低,并在SCL高电平期间保持住。如果SDA没有拉低就是没有ACK,即NOACK。

static void I2CACK(void)
{
	SDA_OUT();   //SDA置输出口
	SDA_OUT_low();
	I2CDelay(); 
	SCL_high();  
	I2CDelay(); 
	SCL_low(); 
	I2CDelay(); 
}
static void I2C_NOACK(void)
{
	SDA_OUT();   //SDA置输出口
	SDA_OUT_high();
	I2CDelay(); 
	SCL_high();  
	I2CDelay(); 
	SCL_low(); 
	I2CDelay(); 
}

4.写地址   将数据放在EE的地址,       I2C_WriteByte(data);

5.  I2结束

void I2CStop()
{
    SDA_OUT_low();    
    SCL_high();
    I2CDelay();
    SDA_OUT_hight();
    I2CDelay();
    SCL_low();
}

6.一个完整的写函数

static unsigned char write_eeprom(unsigned int addr,  void const *buf, unsigned int len)
{
	unsigned char w_wait,e2page,SlaveAddr;	
	unsigned char const *src=(unsigned char *)buf;
	e2page = 16;
	I2CDelay();
reStart:
	SlaveAddr = 0xA0 + (unsigned char)((addr & 0x0700)>>7);
	
	I2CStart();
	I2C_WriteByte(SlaveAddr);
		
	I2C_WriteByte((unsigned char)(addr%0x100))) 
	
	while(len--)
	{
		I2C_WriteByte(*src++)) 
		addr++;
		if((addr % e2page) == 0)
		{
		    break;
		}
	}	
	I2CStop();
	DelayMs(5);
	if(len != 0xffff)	
	{
	    goto reStart;
	}
	
	I2CDelay();
	SCL_low();
	retrun 1;
}

三.看读操作时序进行EE读操作

 读操作时,先写入芯片,要读的地址,然后在读,如上述标计:

1,2步写入写操作控制字及要读的地址;第3步是写入读控制字,数据就可以读出。

读函数代码:

static unsigned char  I2C_Recv_byte(void)
{
	unsigned char byte;
	unsigned char i = 0;
	SDA_IN();     //SDA 置输入口
	for(i=0;i<8;i++)
	{
		byte <<= 1;
		SCL_high(); 
		I2CDelay();
		if(SDA == 1) 
		{
		    byte |= 0x01;
		}
		SCL_LOW(); 
		I2CDelay();
	}
	return(byte);
}

static unsigned char read_eeprom(unsigned int addr, void *buf, unsigned int len)
{
	unsigned char w_wait,SlaveAddr;
	unsigned char *dest=(unsigned char *)buf;
	I2CDelay(); 	
	SlaveAddr = 0xA0 + (unsigned char)((addr & 0x0700)>>7);	
	
	I2CStart();
	I2C_WriteByte(SlaveAddr))
    I2C_WriteByte((unsigned char)(addr%0x100)))
	
	I2CStart();
	I2C_WriteByte((SlaveAddr+1))    //read
	
	while(len--)
	{
		*dest++	= I2C_Recv_byte();
		if(n != 0)
		{
			I2CACK();
		}
		addr++;
	}
	I2CNOACK();
	I2CStop();	
	DelayMs(1);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值