51单片机—IIC总线和AT24C02

一、IIC总线

1.1.IIC总线介绍

IIC(Inter-Integrated Circuit)总线是由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。IIC 总线只有两根双向信号线。一根是数据线 SDA,另一根是时钟线 SCL。由于其管脚少,硬件实现简单,可扩展性强等特点,因此被广泛的使用在各大集成芯片内。下面我们就从 IIC 的物理层与协议层来了解 IIC。

1.2.IIC总线物理层

I2C 通信设备常用的连接方式如下图所示:
在这里插入图片描述

  • 它是一个支持多设备的总线。“总线”指多个设备共用的信号线。在一个 IIC 通讯总线中,可连接多个 IIC 通讯设备,支持多个通讯主机及多个通讯从机。
  • 一个 IIC 总线只使用两条总线线路,一条双向串行数据线(SDA),一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
  • 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
  • 总线通过上拉电阻接到电源。当 IIC 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
  • 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
  • 具有三种传输模式:标准模式传输速率为 100kbit/s,快速模式为400kbit/s,高速模式下可达 3.4Mbit/s,但目前大多 IIC 设备尚不支持高速模式。
  • 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制。

1.3.IIC总线协议层

I2C 总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。

1.3.1.起始与停止的信号

起始信号终止信号,数据线都在时钟线为1时变化的,其他时候时钟线只有为0,数据线才能变化。

  • 起始条件:SCL高电平期间,SDA从高电平切换到低电平。
  • 终止条件:SCL高电平期间,SDA从低电平切换到高电平。
    如下图:
    在这里插入图片描述

1.3.2.发送一个字节

SCL低电平期间,主机将数据位依次放到SDA线上(高位在前),然后拉高SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。
在这里插入图片描述

1.3.3.接收一个字节

SCL低电平期间,从机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)。
在这里插入图片描述

1.3.4.发送应答和接收应答

  • 发送应答:在接收完一个字节之后,主机在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。
  • 接收应答:在发送完一个字节之后,主机在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)。
    在这里插入图片描述

1.4.发送一帧数据

一帧数据指的是:一次完整的数据传输单元,由特定格式的信号或数据段组成,包含起始、数据、校验、结束等部分,确保数据传输的有序性和可靠性。发送一帧数据是由主机发送给从机,显示主机发送一个起始信号,告诉各个IIC协议上的设备,主机要发送消息了。接着发送从机的地址码加写操作,意思是主机要写数据给从机,如果主机读到从机发送的应答信号,则继续下面操作,否则就没有该从机设备。继续下面操作之后,循环发送再接收应答,最后主机发起停止信号才停止。下图是发送一帧数据:
在这里插入图片描述

1.5.接收一帧数据

接收一帧数据是主机接收从机发来的一帧数据。首先由主机发起起始信号,再发出从机地址码加读操作,接着主机读到从机发出的应答信号,接下来SDA线就由从机操作,从机发出一字节数据,主机发出应答信号,循环以上操作,主机发出非应答信号,再发出停止信号,整个数据帧就停止了。下图是接收一帧数据:
在这里插入图片描述

1.6.字节写

例如:在WORD ADDRESS处写入数据DATA。主机第一次收到从机的应答信号后,主机就可以发出从机里寄存器的地址码,主机再收到一次从机应答信号,最后主机就可以进行写数据了。
在这里插入图片描述

1.7.随机读

例如:读出WORD ADDRESS处的数据,首先主机发起起始信号和从机地址码加写操作,从机发出应答信号,主机再发出WORD ADDRESS,从机再发出应答信号,接着主机重新发起起始信号,再发送从机地址码加读操作,从机发送应答信号,主机读出从机发出来的数据,主机最后发送非应答信号和停止信号。下图是随机读操作:
在这里插入图片描述

1.8.IIC软件设计

利用P2_1和P2_0来模拟IIC的SCL和SDA两根线。下面代码是IIC.c文件:

#include <REGX52.H>

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

/**
  *@brief  I2C开始
  *@param  无
  *@retval 无
  */
void I2C_Start()	
{
	I2C_SDA=1;	//先把两根先都拉高
	I2C_SCL=1;
	I2C_SDA=0;	//趁着时钟线为1的时候,数据线拉低
	I2C_SCL=0;	//接着时钟线再拉低
}

/**
  *@brief  I2C停止
  *@param  无
  *@retval 无
  */
void I2C_Stop()
{
	I2C_SDA=0;	//为了确保数据线由0变1,先把数据线拉低
	I2C_SCL=1;	//再把时钟线拉高
	I2C_SDA=1;	//在时钟线为1时,操作数据线为1
}

/**
  *@brief  I2C发送
  *@param  Byte 要发送的字节
  *@retval 无
  */
void I2C_SentByte(unsigned char Byte)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);	//按位字节与,1和1等于1,1和0等于0,先把数据线的数据固定好
		I2C_SCL=1;	//接着时钟线为1,数据线的数据被发送
		I2C_SCL=0;	//时钟线再为0,数据线可以变化
	}
}

/**
  *@brief  I2C接受一个字节
  *@param  无
  *@retval 接收到的一个字节数据
  */
unsigned char I2C_ReceiveByte()
{
	unsigned char Byte=0x00,i;	//定义一个保存读到字节的变量,初始化成 0
	
	I2C_SDA=1;	//主机释放数据线,让从机操作数据线
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;	//高电平读取
		if(I2C_SDA){Byte|=(0x80>>i);}	//读取数据线发来的数据并存在Byte变量当中,如果I2C_SDA为1,就进入if语句,把当前位置1
		I2C_SCL=0;	
	}
	return Byte;	//返回读出来的数据
}

/**
  *@brief  I2C发送应答位
  *@param  Ackbit 应答位,0为应答,1为非应答
  *@retval 无
  */
void I2C_SentAckbit(unsigned char Ackbit)
{
	I2C_SDA=Ackbit;	//发送完一个字节后,主机发一个应答
	I2C_SCL=1;
	I2C_SCL=0;
}

/**
  *@brief  I2C接受应答位
  *@param  无
  *@retval 接收到的应答位,应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAckbit()
{
	unsigned char Ackbit;
	I2C_SDA=1;	//主机先把数据线释放,让从机来操作
	I2C_SCL=1;	//时钟线为1,就可以读取从机发来的应答信号
    Ackbit=I2C_SDA;
	I2C_SCL=0;
	return Ackbit;	//返回从机发来的应答信号
}

下面是IIC.h文件:

#ifndef __I2C_H__
#define __I2C_H__

void I2C_Start();
void I2C_Stop();
void I2C_SentByte(unsigned char Byte);
unsigned char I2C_ReceiveByte();
void I2C_SentAckbit(unsigned char Ackbit);
unsigned char I2C_ReceiveAckbit();

#endif

二、AT24C02芯片

2.1.存储器

在这里插入图片描述

2.2.AT24C02 芯片介绍

AT24C02是一种可以实现掉电不丢失的存储器,可用于保存单片机运行时想要永久保存的数据信息。

  • 存储介质:E2PROM(电可擦除可编程ROM)
  • 通讯接口:I2C总线
  • 容量:256字节
    AT24C02 芯片管脚及外观图如下图所示:
    在这里插入图片描述

2.3.引脚及应用电路

引脚功能
VCC、GND电源(1.8V~5.5V)
WP写保护(高电平有效)
SCL、SDAIIC接口
A0、A1、A2IIC地址

下图是应用电路:
在这里插入图片描述

2.4.AT24C02芯片软件设计

该器件通过 I2C 总线接口进行操作,下面代码是AT24C02.c文件:

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_Address  0xA0


/**
  *@brief  AT24C02写入一个字节
  *@param  WordAddress 要写入的地址
  *@param  Data 要写入的数据
  *@retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SentByte(AT24C02_Address);	//主机发送从机的地址码加写操作,呼叫该从机
	I2C_ReceiveAckbit();	//从机收到,从机发送应答
	I2C_SentByte(WordAddress);	//主机再发送特定位置写入
	I2C_ReceiveAckbit();	//从机收到,从机发送应答
	I2C_SentByte(Data);		//主机发送数据
	I2C_ReceiveAckbit();	//从机收到,从机发送应答
	I2C_Stop();	//主机发起停止信号
}
/**
  *@brief  AT24C02读取一个字节
  *@param  WordAddress 要读出的地址
  *@retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;	//定义一个变量Data来保存主机接收到从机发来的数据
	I2C_Start();
	I2C_SentByte(AT24C02_Address);
	I2C_ReceiveAckbit();
	I2C_SentByte(WordAddress);	//要读出WordAddress的数据,所以发送WordAddress的地址码
	I2C_ReceiveAckbit();
	I2C_Start();	//主机重新发起起始信号
	I2C_SentByte(AT24C02_Address|0x01);	//主机发送该设备地址码并将最后一位置1,意味着读操作
	I2C_ReceiveAckbit();
	Data=I2C_ReceiveByte();	//用变量Data来承接I2C_ReceiveByte()返出来的数据,也就是主机读出从机发送的数据
	I2C_SentAckbit(1);	//主机发送非应答信号,如果发送0,从机继续发送数据
	I2C_Stop();	
	return Data;	//把读出的数据返出去
}

下面是AT24C02.h头文件:

#ifndef __AT24C02_H__
#define __AT24C02_H__

void AT24C02_WriteByte(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadByte(unsigned char WordAddress);

#endif

由AT24C02芯片实现储存数据,下面是main函数:

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "Key.h"
#include "AT24C02.h"

unsigned char KeyNum;
unsigned int Num;
void main()
{
	LCD_Init();
	LCD_ShowNum(1,1,Num,5);
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
			Num++;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==2)
		{
			Num--;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==3)
		//为什么要区分高8位,低8位,因为定义Num位int类型,int为16位,
		//定义char类型就不需要区分了,char类型只有8位
		{		
			AT24C02_WriteByte(0,Num%256);  //这里是低8位
			Delay(5);
			AT24C02_WriteByte(1,Num/256);  //这里是高8位
			LCD_ShowString(2,1,"Write ok");
			Delay(1000);
			LCD_ShowString(2,1,"        ");
		}
		if(KeyNum==4)
		{
			Num=AT24C02_ReadByte(0);
			Num|=AT24C02_ReadByte(1)<<8;
			LCD_ShowNum(1,1,Num,5);
			LCD_ShowString(2,1,"Read ok");
			Delay(1000);
			LCD_ShowString(2,1,"        ");
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值