I2C总线

I2C 总线概述

I2C(Inter-Integrated Circuit)总线是由 PHILIPS 公司开发的两线式串行总线,用于连接微控制器及其
外围设备。是微电子通信控制领域广泛采用的一种总线标准。具有接口线少,控制方式简单,器件封装形式小,
通信速率较高等优点。
I2C 规程运用主/从双向通讯。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。
主器件和从器件都可以工作于接收和发送状态。
I2C 总线通过串行数据(SDA)线和串行时钟(SCL)线在连接到总线的器件间传递信息。每个器件都有
一个唯一的地址识别(无论是微控制器——MCU、 LCD 驱动器、存储器或键盘接口),而且都可以作为一个
发送器或接收器(由器件的功能决定)。
I2C 有四种工作模式:
1.主机发送
2.主机接收
3.从机发送
4.从机接收
I2C 总线只用两根线:串行数据 SDA(Serial Data)、串行时钟 SCL(Serial Clock)。总线必须由主机(通
常为微控制器)控制,主机产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。 SDA 线上
的数据状态仅在 SCL 为低电平的期间才能改变。
和前面的 UART 比较, UART 是异步串行全双工通信总线, I2C 是同步串行半双工通信总线。

I2C 总线特点

一.总线物理拓扑结构

在这里插入图片描述
I2C 总线在物理连接上非常简单,分别由 SDA(串行数据线)和 SCL(串行时钟线)及上拉电阻组成。通信原
理是通过对 SCL 和 SDA 线高低电平时序的控制,来产生 I2C 总线协议所需要的信号进行数据的传递。在总 线
空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

上拉电阻范围 4.7K~100K 

二.I2C 总线特征

I2C 总线上的每一个设备都可以作为主设备或者从设备,而且每一个从设备都会对应一个唯一的地址(可
以从 I2C 器件的数据手册得知)。主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,
我们把 CPU 带 I2C 总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。

1总线上能挂接的器件数量

I2C 总线上可挂接的设备数量受总线的最大电容 400pF 限制,如果所挂接的是相同型号的器件,则还受器件地址的限制。
一般 I2C 设备地址是 7 位地址(也有 10 位), 地址分成两部分: 芯片固化地址(生产芯片时候哪些接地,
哪些接电源, 已经固定),可编程地址(引出 IO 口,由硬件设备决定)。
例如: 某一个器件是 7 位地址,其中 10101 xxx 高 4 位出厂时候固定了,低 3 位可以由设计者决定。
则一条 I2C 总线上只能挂该种器件最少 8 个。
如果 7 位地址都可以编程,那理论上就可以达到 128 个器件, 但实际中不会挂载这么多。
2. 总线速度传输速度
I2C 总线数据传输速率在标准模式下可达 100kbit/s,快速模式下可达 400kbit/s,高速模式下可达 3.4Mbit/s。
一般通过 I2C 总线接口可编程时钟来实现传输速率的调整。
3. 总线数据长度
I2C 总线上的主设备与从设备之间以字节(8 位)为单位进行双向的数据传输。

I2C 总线协议

1.总线协议基本时序信号
空闲状态: SCL 和 SDA 都保持着高电平。
起始条件: 总线在空闲状态时, SCL 和 SDA 都保持着高电平,当 SCL 为高电平期间而 SDA 由高到低的
跳变,表示产生一个起始条件。在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他
I2C 器件无法访问总线。
停止条件: 当 SCL 为高而 SDA 由低到高的跳变,表示产生一个停止条件。
答应信号: 每个字节传输完成后的下一个时钟信号, 在 SCL 高电平期间, SDA 为低,则表示一个应答信
号。
非答应信号: 每个字节传输完成后的下一个时钟信号, 在 SCL 高电平期间, SDA 为高,则表示一个应答
信号。应答信号或非应答信号是由接收器发出的,发送器则是检测这个信号(发送器,接收器可以从设备也可
以主设备)。
注意: 起始和结束信号总是由主设备产生。
基本时序如下图所示:
在这里插入图片描述
2.数据传输时序
当产生起始条件后,开始数据传输,这个阶段主设备在 SCL 线上的每一个脉冲,都会同时在 SDA 线上传输
一个数据位(地址数据传输方式和普通数据传输方式相同),每个字节完成后,跟着一个应答位。当不想再进行
数据传输时,主机产生一个停止信号,总线释放, SCL,SDA 线都回到空闲状态。数据传输时序图如下:
在这里插入图片描述
3. I2C 寻址方式
I2C 总线上的每一个 I2C 设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,
主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样, 只不过大多
数从设备的地址是 7 位的(有的设备地址是 10 位的, 发送地址要使用两个字节, 这里仅以 7 位地址为例子),
然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向, 0 表示主设备向从设备写数据, 1 表
示主设备从从设备读数据。如图所示:

在这里插入图片描述
4、I2C 总线操作
对 I2C 总线的操作实际就是主从设备之间的读写操作。大致可分为以下三种操作情况:
第一,主设备往从设备中写数据。数据传输格式如下:

在这里插入图片描述
第二,主设备从从设备中读数据。数据传输格式如下:
在这里插入图片描述
第三,主设备往从设备中写数据,然后重启起始条件,紧接着从从设备中读取数据;或者是主设备从从设
备中读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下:

在这里插入图片描述
第三种操作在单个主设备系统中,重复的开启起始条件机制要比用 STOP 终止传输后又再次开启总线更有
效率。

I2C 总线模块时序编程

1、起始条件
根据 I2C 规范,可以使用两个普通 IO 口模拟出来其起始条件时序,代码如下:

static bool i2c_start(void)
{
	SDA_H();
	SCL_H();
	i2c_delay();
	if(!SDA_READ())
	return false; //SDA 线为低电平则总线忙,退出
	SDA_L();
	if(SDA_READ())
	return false; //SDA 线为高电平则总线出错,退出
	SDA_L();
	i2c_delay();
	return true;
}

2、 停止条件
根据 I2C 规范,可以使用两个普通 IO 口模拟出来其停止条件时序,代码如下:

static void i2c_stop(void)
{
	//i2c_delay(); //可以不加,加上去是为了获得更标准的 SCL 波形
	SCL_H();
	SDA_L();
	i2c_delay();//>4us
	SDA_H();
	i2c_delay();//>4.7us
}

3、发送应答信号或非应答信号
根据 I2C 规范,可以使用两个普通 IO 口模拟出来其应答/非答应时序,代码分别如下:
发送应答信号:

static void i2c_ack(void)
{
	SCL_L(); //低电平数据才能变化,先置低
	SDA_L();
	i2c_delay();
	SCL_H();
	i2c_delay();
	SCL_L();
}

发送非应答信号:

static void i2c_noack(void)
{
	SCL_L(); //低电平数据才能变化,先置低
	SDA_H();
	i2c_delay();
	SCL_H();
	i2c_delay();
	SCL_L();
}

接收方要调用这两个函数,告诉发送方自己是否已经已经收到数据。
4 、检测应答信号
根据 I2C 规范,可以使用两个普通 IO 口模拟出来其检测应答信号时序,代码如下:

static bool i2c_waitack(void)
{
	SCL_H();//高电平锁定数据
	i2c_delay();
	if(SDA_READ()) //按照规范,高电平代表非应答
	{
		SCL_L();
		return false; //检测到非应答
	}
	SCL_L();
	return true; //检测到应答信号
}

数据的发送方负责在一个字节后检测接收方传递回来信号(应答或非应答信号)
5 、单字节发送
根据 I2C 规范,可以使用两个普通 IO 口模拟出来字节发送时序,代码如下:

static void i2c_sendbyte(uint8_t SendByte)
{
	uint8_t i = 8;
	while(i--)
	{
		SCL_L(); //让 SDA 线数据可以修改
		if(SendByte & 0x80) //判断最高位, bit7 开始
		SDA_H();
		else
		SDA_L();
		i2c_delay();
		SCL_H();
		i2c_delay();
		SendByte <<= 1;
	}
	SCL_L(); //低电平才可以变化数据
	i2c_delay(); //不加也可以
}

6 、单字节接收
根据 I2C 规范,可以使用两个普通 IO 口模拟出来其单字节接收时序,代码如下

static uint8_t i2c_receivebyte(void)
{
uint8_t i = 8;
uint8_t ReceiveByte = 0;
SDA_H(); //由于读数据,所要要释放总线,不加经测试结果将是全 0
while(i--)
{
	ReceiveByte <<= 1; //移位应该放在这里,接收字节间应该有一定的时间
	SCL_L(); //低电平才可以变化数据
	i2c_delay(); //等待数据稳定
	SCL_H(); //锁定数据
	if(SDA_READ())
	{
		ReceiveByte |= 0x01;
	}
		i2c_delay(); //等待数据稳定
	}
	return ReceiveByte;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux I2C总线寄存器是用于控制和配置I2C总线通信的寄存器集合。I2C(Inter-Integrated Circuit)总线是一种串行通信协议,用于在多个设备之间进行数据交换。 在Linux系统中,I2C总线寄存器位于内核空间中的驱动程序中,由内核提供支持。通过这些寄存器,可以实现对I2C总线的读写操作、设备的探测和配置等功能。 I2C总线寄存器主要包括如下几个方面的功能: 1. 控制寄存器:用于设置I2C总线工作模式和速率等参数。通过控制寄存器可以选择I2C总线的主从模式,设置传输速率和时钟频率等。 2. 数据寄存器:用于存储需要传输的数据。在写操作中,数据会被写入数据寄存器,然后通过I2C总线发送给目标设备。在读操作中,目标设备的数据会被存储在数据寄存器中,然后从数据寄存器中读取出来。 3. 状态寄存器:用于检测I2C总线的状态。通过状态寄存器可以判断I2C总线是否忙碌、传输是否成功等。状态寄存器中的标志位可以提供给驱动程序检测和判断使用。 4. 地址寄存器:用于设置目标设备的地址。在I2C总线中,每个设备都有一个唯一的地址,通过地址寄存器可以设置要读写的目标设备的地址。 总的来说,Linux I2C总线寄存器提供了对I2C总线通信的底层控制和管理能力,通过对这些寄存器的操作可以实现I2C设备的读写操作、总线的配置和控制等功能。同时,通过驱动程序对这些寄存器进行访问和操作,可以方便地实现I2C设备的驱动开发和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值