(给自己看)51单片机AT24C02

本文介绍了I2C通信协议的基本原理,包括其双线制特性、多设备连接、起始和停止信号、应答响应以及寻址方式。此外,还详细解析了AT24C02 EEPROM的读写操作,展示了如何通过I2C接口进行数据传输。通过示例代码,阐述了如何实现从机地址设置、数据写入和读取的过程。
摘要由CSDN通过智能技术生成

AT24C02.c文件

#include <regx52.h>
#include "I2C.h"

#define AT24C02_ADDRESS		0xA0
// 不需要初始化
//  将数据赋值给T的时候需要先把以前的数值提取出来,
//   不然会导致每次都重新写入计数



/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
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();
}

/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
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();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

IIC.c文件

#include <regx52.h>

sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte(void)
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck(void)
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;

先从AT24C02(EEPROM)开始: 

P21----- 时钟线SCL

P20-----数据线SDA

知道了这个时候需要先去了解IIC(I2C)

IIC是同步通信的一种特殊形式,具有接口线少,控制方式简单, 器件封装形式小,通信速率较高等优点。

具体表现在:I2C 总线只有两根双向信号线。一根是 数据线 SDA,另一根是时钟线 SCL

它的物理层有如下特点:

(1)它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在 一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通 讯从机。

(2)一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA),一 条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

(3)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址 进行不同设备之间的访问。

(4)总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而 当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。

(5)多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定 由哪个设备占用总线。 261

(6)具有三种传输模式:标准模式传输速率为 100kbit/s,快速模式为 400kbit/s,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模 式。

(7)连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制。 

常用术语:(拣我认为重要的)

主机:启动数据传送并产生时钟信号的设备;(单片机核心是主机)

从机:被主机寻址的器件;                             (AT24C02是从机)

发送器:发送数据到总线的器件;                          AT24C02

接收器:从总线接收数据的器件。                         单片机核心


 

 每次数据传输都以字节为单位,每次传输的字节数不受限制。

起始和停止信号

SCL 线为高电平期间,SDA 线由高电平向低电平的变化表示起始信号;

SCL 线为高电平期间,SDA 线由低电平向高电平的变化表示终止信号。

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空闲状态。

/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start(void)
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop(void)
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

应答响应:

每当发送器件传输完一个字节的数据后,后面必须紧跟一个校验位,这个校验位是接收端通过控制 SDA(数据线)来实现的,以提醒发送端数据我这边已经接收完成,数据传送可以继续进行。

这里发送器不是单单的单片机核心和AT24C02,因为所以这里的发送器两个都可能,一个发一个收,收完再发接收完成。(一来一回

校验位其实就是数据或地址传输过程中的响应。

响应包括“应答(ACK)”和“非应答(NACK)”两种信号。

主机的SDA由于发送的是0或1而变化,但是从机的SDA就是我们自己人为控制了。

在写程序的时候是要实时改变SDA是输入还是输出(通过从机地址来辨别)
 

从机不对寻址信号应答时(如从机正在进行实时性的处理 工作而无法接收总线上的数据),它必须将数据线置于高电平,而由主机产生一个终止信号以结束总线的数据传送。

如果从机对主机进行了应答(意思是继续),但在数据传送一段时间后无法继续接收更多的数据时,从机可以通过对无法接收的第一个数据字节的“非应答”(拒绝)通知主机,主机则应发出终止信号以结束数据的继续传送。

当主机接收数据时,它收到最后一个数据字节后,必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。然后,从机释放 SDA 线,以允许主机产生终止信号。

这些信号中,起始信号是必需的,结束信号和应答信号都可以不要。

 从想停,主发终

从有事,从非应答(拒绝),主发终

主接收最后一个数据,发结束信号给从(通过对从机非应答(拒绝)),从释放SDA,主终止

总线的寻址方式

I2C 总线寻址按照从机地址位数可分为两种,一种是 7 位,另一种是 10 位。采用 7 位的寻址字节(寻址字节是起始信号后的第一个字节)的位定义如下

 D7~D1 位组成从机的地址。

D0 位是数据传送方向位,为“ 0”时表示主机向从机写数据,为“1”时表示主机由从机读数据(从机发)。

用“0”表示主机发送(写)数据(W),“1”表示主机接收数据(R)。

当主机发送了一个地址后,总线上的每个器件都将头 7 位与它自己的地址比较,如果一样,器件会判定它被主机寻址,其他地址不同的器件将被忽略后面的数据信号。

至于是从机接收器还是从机发送器,都由 R/W 位决定的。

每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。

 此处对照AT24C02-------------------------------这里是地址

 开发板已经将芯片的 A0/A1/A2 连接到 GND,所以器件地址为 1010000

#define AT24C02_ADDRESS        0xA0

单片机核心发送给AT24C02(AT24C02里面存储数据)

 

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();                     //结束
}

AT24C02_WriteByte(1,2);在“1空间”存放“2”;

读取

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();
	I2C_SendAck(1);                //非应答
	I2C_Stop();
	return Data;
}

使用:t=AT24C02_ReadByte(1);读取“1空间”里面的数据。

引用大佬图:

脑子不行了,溜了溜了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值