51单片机学习笔记(九) - IIC通信之EEPROM


一、EEPROM模块-24C02介绍

1、描述

24C02是电可擦除PROM,采用256×8-bit的组织结构以及两线串行接口。电压可允许低至1.8V,待机电流和工作电流分别位1uA和1mA。24C02具有页写能力,每页为8字节。

  • 宽范围的工作电压1.8V~5.5V;
  • 2线串行接口,完全兼容I2C总线;
  • I2C 时钟频率为1MHz (5V), 400 kHz (1.8V, 2.5V, 2.7V);
  • 硬件数据写保护;
  • 擦写寿命:100万次;
  • 数据保持时间:100年;

2、引脚定义

在这里插入图片描述
在这里插入图片描述

3、芯片地址及存储结构

1、通过A0、A1、A2的硬件连接来确定芯片的地址
在这里插入图片描述
2、24C02的内存大小是2K字节,存储结构如下:
在这里插入图片描述

4、开发板原理图

在这里插入图片描述


二、IIC协议介绍

在以往的博客里,专门介绍过IIC的相关内容,地址如下:
IIC通讯详解

在此对IIC进行总结:
1、主CPU和其附属芯片之间最常用的接口,尤其是各种传感器,因此在物联网时代非常重要;
2、三根线:GND、SCL、SDA,串行、电平式;
3、总线式结构,可以一对多,总线上可以挂上百个器件,用从地址来区分;
4、主从式,由主设备来发起通信及总线仲裁(主设备决定哪个从设备工作),从设备被动响应;
5、通信速率比较低(kbps级别),不适合语音、视频等信息类型。


三、低层时序代码实现

1、起始条件

当时钟线(SCL)为高电平时,数据线(SDA)的下降沿(由高到低),叫做起始条件

在这里插入图片描述

代码如下:

void Iic_Start(void)
{
	IIC_SDA = 1;
	Iic_Delay_10us();
	IIC_SCL = 1;
	Iic_Delay_10us();
	IIC_SDA = 0;           //在SCL为高的时候,SDA产生一个下降沿
	Iic_Delay_10us();
	IIC_SCL = 0;           //拉低SCL,准备发送数据
	Iic_Delay_10us();
}

2、停止条件

当时钟线(SCL)为高电平时,数据线(SDA)的上升沿(由低到高),叫做停止条件

在这里插入图片描述

代码如下:

void Iic_Stop(void)
{
	IIC_SDA = 0;
	Iic_Delay_10us();
	IIC_SCL = 1;
	Iic_Delay_10us();
	IIC_SDA = 1;           //在SCL为高的时候,SDA产生一个上升沿
	Iic_Delay_10us();
}

3、应答和非应答

1、在第9个bit位时,时钟线(SCL)为高时,接收器拉低数据线(SDA)表示应答,并在应答脉冲期间保持稳定的低电平,没有拉低表示非应答。
2、当主器件作为接收器时,必须发出数据传输结束的信号给发送器,即它在最后一个字节之后的应答脉冲期间不会产生应答信号(拉低SDA)。这种情况下发送器必须释放SDA线作为高,以便主器件产生停止条件。

在这里插入图片描述

应答代码如下:

void Iic_Ack(void)
{
	IIC_SCL = 0;
	Iic_Delay_10us();
	IIC_SDA = 0;
	Iic_Delay_10us();
	IIC_SCL = 1;          
	Iic_Delay_10us();
	IIC_SCL = 0;
}

非应答代码如下:

void Iic_Nack(void)
{
	IIC_SCL = 0;
	Iic_Delay_10us();
	IIC_SDA = 1;
	Iic_Delay_10us();
	IIC_SCL = 1;          
	Iic_Delay_10us();
	IIC_SCL = 0;
}

4、应答等待

主机给从机发送数据后,会等待从机的应答

unsigned char Iic_Wait_Ack(void)
{
	unsigned char wait_time = 0;
	IIC_SCL = 0;
	Iic_Delay_10us();
	IIC_SDA = 1;
	Iic_Delay_10us();
	IIC_SCL = 1;
	while(IIC_SDA)                  //等待应答(SDA为低电平)
	{
		wait_time++;
		if(wait_time > 200)         //应答超时,停止等待,强制推出
		{
			Iic_Stop();
			return 0;
		}
	}
	IIC_SCL = 0;
	return 1;
}

5、写一个字节

主机向从机写一个字节

void Iic_Write_Byte(unsigned char dat)
{
	unsigned char i = 0;
	IIC_SCL = 0;
	Iic_Delay_10us();
	for(i = 0; i < 8; i++)
	{
		if((dat & 0x80) > 0)       //先写高字节
			IIC_SDA = 1;
		else
			IIC_SDA = 0;
		dat <<= 1;
		Iic_Delay_10us();
		IIC_SCL = 1;
		Iic_Delay_10us();
		IIC_SCL = 0;
		Iic_Delay_10us();
	}
}

6、读一个字节

主机向从机读一个字节

unsigned char Iic_Read_Byte(unsigned char ack)
{
	unsigned char i = 0, recive = 0;
	IIC_SCL = 0;
	Iic_Delay_10us();
	for(i = 0; i < 8; i++)
	{
		IIC_SCL = 1;
		Iic_Delay_10us();
		recive <<= 1;                   //注意此句代码的位置顺序
		recive |= IIC_SDA;              //先读高字节
		Iic_Delay_10us();
		IIC_SCL = 0;
		Iic_Delay_10us();
	}
	if(ack)
		Iic_Ack();
	else
		Iic_Nack();
	return recive;
}

四、AT24C02高层代码实现

1、在AT24C02指定地址写入一个数据

向指定地址写入数据时序图

在这里插入图片描述

向指定地址写入数据代码实现:

void At24c02_Write_One_Byte(unsigned char addr, unsigned char dat)
{
	Iic_Start();                               //第一步,起始条件
	Iic_Write_Byte(AT24C02_WRITE);             //第二步,器件地址,写
	if(Iic_Wait_Ack())                         //第三步,等待从机应答
	{
		Iic_Write_Byte(addr);                  //第四步,如果应答,则发送目标地址
		if(Iic_Wait_Ack())                     //第五步,等待从机应答
		{
			Iic_Write_Byte(dat);              //第六步,如果收到应答,则在相应的内存地址写入数据
			Iic_Wait_Ack();                   //第七步,等待从机应答
			Iic_Stop();                       //第八步,停止条件
		}
		else
			Iic_Stop();                      //如果没有收到从机的应答,则发送结束条件,让出总线
	}		
	else
		Iic_Stop();	                         //如果没有收到从机的应答,则发送结束条件,让出总线
}

2、向AT24C02指定地址读取一个数据

向指定地址读取数据时序图

在这里插入图片描述

向指定地址读取数据代码实现:

unsigned char At24c02_Read_One_Byte(unsigned char addr)
{
	unsigned char recive;
	Iic_Start();                                         //第一步,起始条件
	Iic_Write_Byte(AT24C02_WRITE);                       //第二步,器件地址,写
	if(Iic_Wait_Ack())                                   //第三步,等待从机应答
	{
		Iic_Write_Byte(addr);                           //第四步,如果应答,则发送目标地址
		if(Iic_Wait_Ack())                              //第五步,等待从机应答
		{
			Iic_Start();                               //第六步,如果收到应答,则再次发送起始条件
			Iic_Write_Byte(AT24C02_READ);              //第七步,器件地址,写
			if(Iic_Wait_Ack())                         //第八步,等待从机应答
			{
				recive = Iic_Read_Byte(0);             //第九步,如果收到应答,接收数据
				                                       //第十步,等待应答,也可以不等待
				Iic_Stop();                            //第十一步,停止条件
			}
			else
				Iic_Stop();                           //如果没有收到从机的应答,则发送结束条件,让出总线
		}
		else
			Iic_Stop();                               //如果没有收到从机的应答,则发送结束条件,让出总线
	}
	else
		Iic_Stop();                                   //如果没有收到从机的应答,则发送结束条件,让出总线
	return recive;
}

五、一些宏定义

#define AT24C02_READ     0xA1
#define AT24C02_WRITE    0xA0


sbit IIC_SCL = P2^1;         //SCL时钟线
sbit IIC_SDA = P2^0;         //SDA数据线

总结

1、本次介绍了IIC通信的相关知识以及实现代码;
2、本次介绍了AT24C02的操作时序;
3、该节的重点是看懂时序图,并用代码实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值