#51单片机# I2C时序初步认识和寻址模式

I2C,由PHILIIPS公司开发的两线式串行总线(SCL和SDA),是一种常用的通信协议,多用于连接微处理器及其外围芯片。

I2C的特点:1.接口方式简单。2.两条线可挂多个参与通信的器件,即多机模式。且任一器件都可作为主机(同一时刻只能有一个主机)。

相比与UART通信,I2C属于同步通信。SCL时钟线负责收发双方的时钟节拍,SDA数据线负责传输数据。 I2C的发送方和接收方都以SCL的时钟节拍为基准进行数据发送与接收。

从应用上来说,UART通信多用于板间通信,如:单片机和计算机。I2C多用于板内通信,如:单片机和E2PROM。

I2C时序初步认识

硬件上,I2C总线由SCL时钟总线和SDA数据总线两条线构成。连接到I2C总线的所有器件,SCL相连,SDA相连。

I2C上的任一设备都可做主机(绝大多数情况下是单片机做主机)。

I2C总线是开漏引脚并联的结构其外部有上拉电阻,此时,线与线之间有着‘与’的逻辑关系。也就是说所有接入器件保持高电平,总线才会是高电平。一旦有设备输出低电平,总线就会变成低电平。这也是为什么任一设备都可为主机,因为任一设备都可输出低电平。

开漏引脚图:
在这里插入图片描述

总线上的每一个器件都有唯一属于自己的地址。信息传输中,识别地址可分辨出属于自己的信息。

I2C通信原则:高位在前,低位在后。

I2C中有起始信号、数据传输和停止信号

I2C时序流程图:
在这里插入图片描述
I2C数据传输可一次传输任意数量的字节。每个字节末会跟着一位数据,该数据位叫应答位,通常用ACK表示,类似于UART的停止位。

起始信号:SCL为高电平期间,SDA由高电平向低电平转变,产生的下坡沿(上图中的start部分)。

数据传输:只有当SCL为低电平时,SDA可变化。当SCL为高电平时,SDA不可变化,因为此时接收方要读取当前SDA的电平信号,以此来保证SDA的稳定。

停止信号:SCL为高电平期间,SDA由低电平向高电平变化,产生的上升沿(上图中的Stop部分)。

I2C寻址模式

经历起始信号(Start)后,主机要发送一个从机的地址,地址一共7位,第8位是数据方向位(R/W),‘0’表示接下来要发送数据(写),‘1’表示接下来是请求数据(读)。发送完这8位后,若发送的这个地址存在,主机应收到为’0’的ACK回应(即拉低SDA)。若地址不存在,主机应收到为’1’的ACK回应(即SDA保持高电平)。

下面有一段关于I2C寻址的演示代码

#include <reg52.h>
#include <intrins.h>
 
#define I2CDelay(){_nop();_nop();_nop();_nop();}
//_nop()函数包含在intrins.h文件中,可进行精准延时,一个_nop()就是一个机器周期。
sbit I2C_SCL = P0^0;
sbit I2C_SDA = P0^1;
sbit LED = P1^0;

bit I2CAddressing(unsigned char addr);//I2C寻址函数,即检查地址位addr的器件是否存在,返回值为从器件应答值

void main()
{
	bit ack;
	
	ack = I2CAddressing(0X50); //判断0X50地址是否存在
	if(ack == 1)			   //存在
	LED = 0;				   //LED灯亮起
	while(1);
}

//产生总线起始信号
void I2CStart()
{
	I2C_SDA = 1;	//首先确保SDA,SCL都是高电平
	I2C_SCL = 1;	
	I2CDelay();		
	I2C_SDA = 0;	//先拉低SDA
	I2CDelay();		
	I2C_SCL = 0;	//再拉低SCL
}

//产生总线停止信号
void I2CStop()
{
	I2C_SCL = 0;	//首先确保SDA,SCL都是低电平
	I2C_SDA = 0;
	I2CDelay();
	I2C_SCL = 1;	//先拉高SCL
	I2CDelay();
	I2C_SCA = 1;	//再拉高SDA
	I2CDelay();
}

bit I2CWrite(unsigned char dat)
{
	bit ack;				 				//用于暂存应答位的值
	unsigned char mask;		 				//用于探测字节内某一位值的掩码变量

	for (mask = 0X80; mask!=0; mask>>=1)    //从高位到低位依次进行
	{
		if((mask&dat) == 0)				    //该位的值输出到SDA上
			I2C_SDA = 0;
		else
			I2C_SDA = 1;					
		I2CDelay();
		I2C_SCL = 1;				//拉高SCL
		I2CDelay();			
		I2C_SCL = 0;				//再拉低SCL,完成一个位周期
	}
	I2C_SDA = 1;					//8位数据发送完后,主机释放SDA,以检测从机应答
	I2CDelay();
	I2C_SCL = 1;					//拉高SCL
	ack = I2C_SDA;					//读取此时的SDA值即从机应答值
	I2CDelay();				
	I2C_SCL = 0;					//再拉低SCL完成应答位,并保持住总线

	return ack;						//返回从机应答位
}

bit I2CAddressing(unsigned char addr)
{
	bit ack;							   

	I2CStart();						//产生起始位,即启动一次总线操作
	ack = I2CWrite(addr<<1);		//器件地址需左移一位,因为寻址命令的最低位为读写为,用于表示之后的操作是读是写

	I2CStop();						//不需进行后续读写,直接停止本次总线操作

	return ack;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值