I2C总线传输协议

简介

I2C(Inter-integrated Circuit)总线支持设备之间的短距离通信,用于处理器和一些外围设备之间的接口,它只需要两根信号线来完成信息交换。I2C最早是飞利浦在1982年开发设计并用于自己的芯片上,一开始只允许100kHz、7-bit标准地址。1992年,I2C的第一个公共规范发行,增加了400kHz的快速模式以及10-bit扩展地址。在I2C的基础上,1995年Intel提出了“System Management Bus” (SMBus),用于低速设备通信,SMBus 把时钟频率限制在10kHz~100kHz,但I2C可以支持0kHz~5MHz的设备:普通模式(100kHz即100kbps)、快速模式(400kHz)、快速模式+(1MHz)、高速模式(3.4MHz)和超高速模式(5MHz)。

与串行端口、SPI对比

串行端口

串行端口是异步的(不传输时钟相关数据),两个设备在使用串口通信时,必须先约定一个数据传输速率,并且这两个设备各自的时钟频率必须与这个速率保持相近,某一方的时钟频率相差很大都会导致数据传输混乱。 
异步串行端口在每个数据帧中都要插入至少一个起始位和一个终止位,意味着每传输8bits的数据实际要花费10bits的传输时间,从而降低了数据传输速率。 
另一个问题是异步串行端口的设计就是针对两个设备之间通信的,那么如果有多个设备连接到一个串口上,就必须解决信号碰撞的问题(bus contention),通常要通过额外硬件来完成。 
最后就是数据传输速率,异步串行通信并没有一个理论上的速率限制,大部分UART设备只支持一些特定的波特率,最高通常在230400bps左右。

SPI

SPI最明显的缺点就是引脚数量,使用SPI总线相连的一个master和一个slave需要四根线(MISO/MOSI/SCK/CS),每增加一个slave,就需要在master上增加一个CS引脚。当一个master接多个slaves的时候,疯狂增长的引脚连接是难以忍受的,并且对紧凑的PCB layout是一个挑战。 
SPI总线上只允许有一个master,但可以有任意多个slaves(只受限于总线上设备的驱动程序的能力,以及设备上最多能有多少个CS引脚)。 
SPI可以很好的用于高速率全双工的连接,对一些设备可支持高达10MHz(10Mbps)的传输速率,因此SPI吞吐量大得多。SPI两端的设备通常是一个简单的移位寄存器,让软件的实现很简单。

I2C

I2C最少只需要两根线,和异步串口类似,但可以支持多个slave设备。和SPI不同的是,I2C可以支持mul-master系统,允许有多个master并且每个master都可以与所有的slaves通信(master之间不可通过I2C通信,并且每个master只能轮流使用I2C总线)。master是指启动数据传输的设备并在总线上生成时钟信号以驱动该传输,而被寻址的设备都作为slaves。 
这里写图片描述
I2C的数据传输速率位于串口和SPI之间,大部分I2C设备支持100KHz和400KHz模式。使用I2C传输数据会有一些额外消耗:每发送8bits数据,就需要额外1bit的元数据(ACK或NACK)。I2C支持双向数据交换,由于仅有一根数据线,故通信是半双工的。 
硬件复杂度也位于串口和SPI之间,而软件实现可以相当简单。

I2C协议

I2C协议把传输的消息分为两种类型的帧: 
一个地址帧 —— 用于master指明消息发往哪个slave; 
一个或多个数据帧 —— 由master发往slave的数据(或由slave发往master),每一帧是8-bit的数据。 
注:协议要求每次放到SDA上的字节长度必须为8位,并且每个字节后须跟一个ACK位,在下面会讲到。 
数据在SCL处于低电平时放到SDA上,并在SCL变为高电平后进行采样。读写数据和SCL上升沿之间的时间间隔是由总线上的设备自己定义的,不同芯片可能有差异。 
I2C数据传输的时序图如下: 
这里写图片描述
开始条件(start condition): 
为了标识传输正式启动,master设备会将SCL置为高电平(当总线空闲时,SDA和SCL都处于高电平状态),然后将SDA拉低,这样,所有slave设备就会知道传输即将开始。如果两个master设备在同一时刻都希望获得总线的所有权,那么谁先将SDA拉低,谁就赢得了总线的控制权。在整个通信期间,可以存在多个start来开启每一次新的通信序列(communication sequence),而无需先放弃总线的控制权,后面会讲到这种机制。 
地址帧(address frame): 
地址帧总是在一次通信的最开始出现。一个7-bit的地址是从最高位(MSB)开始发送的,这个地址后面会紧跟1-bit的操作符,1表示读操作,0表示写操作。 
接下来的一个bit是NACK/ACK,当这个帧中前面8bits发送完后,接收端的设备获得SDA控制权,此时接收设备应该在第9个时钟脉冲之前回复一个ACK(将SDA拉低)以表示接收正常,如果接收设备没有将SDA拉低,则说明接收设备可能没有收到数据(如寻址的设备不存在或设备忙)或无法解析收到的消息,如果是这样,则由master来决定如何处理(stop或repeated start condition)。 
数据帧(data frames): 
在地址帧发送之后,就可以开始传输数据了。Master继续产生时钟脉冲,而数据则由master(写操作)或slave(读操作)放到SDA上。每个数据帧8bits,数据帧的数量可以是任意的,直到产生停止条件。每一帧数据传输(即每8-bit)之后,接收方就需要回复一个ACK或NACK(写数据时由slave发送ACK,读数据时由master发送ACK。当master知道自己读完最后一个byte数据时,可发送NACK然后接stop condition)。 
停止条件(stop condition): 
当所有数据都发送完成时,master将产生一个停止条件。停止条件定义为:在SDA置于低电平时,将SCL拉高并保持高电平,然后将SDA拉高。 
注意,在正常传输数据过程中,当SCL处于高电平时,SDA上的值不应该变化,防止意外产生一个停止条件。 
重复开始条件(repeated start condition): 
有时master需要在一次通信中进行多次消息交换(例如与不同的slave传输消息,或切换读写操作),并且期间不希望被其他master干扰,这时可以使用“重复开始条件” —— 在一次通信中,master可以产生多次start condition,来完成多次消息交换,最后再产生一个stop condition结束整个通信过程。由于期间没有stop condition,因此master一直占用总线,其他master无法切入。 
为了产生一个重复的开始条件,SDA在SCL低电平时拉高,然后SCL拉高。接着master就可以产生一个开始条件继续新的消息传输(按照正常的7-bit/10-bit地址传输时序)。重复开始条件的传输时序如下图所示: 
这里写图片描述 
时钟拉伸(clock stretching): 
有时候,低速slave可能由于上一个请求还没处理完,尚无法继续接收master的后续请求,即master的数据传输速率超过了slave的处理能力。这种情况下,slave可以进行时钟拉伸来要求master暂停传输数据 —— 通常时钟都是由master提供的,slave只是在SDA上放数据或读数据。而时钟拉伸则是slave在master释放SCL后,将SCL主动拉低并保持,此时要求master停止在SCL上产生脉冲以及在SDA上发送数据,直到slave释放SCL(SCL为高电平)。之后,master便可以继续正常的数据传输了。可见时钟拉伸实际上是利用了时钟同步的机制(见下文),只是时钟由slave产生。 
如果系统中存在这种低速slave并且slave实现了clock stretching,则master必须实现为能够处理这种情况,实际上大部分slave设备中不包含SCL驱动器的,因此无法拉伸时钟。 
所以更完整的I2C数据传输时序图为: 
这里写图片描述
10-bit地址空间: 
上面讲到I2C支持10-bit的设备地址,此时的时序如下图所示: 
这里写图片描述
在10-bit地址的I2C系统中,需要两个帧来传输slave的地址。第一个帧的前5个bit固定为b11110,后接slave地址的高2位,第8位仍然是R/W位,接着是一个ACK位,由于系统中可能有多个10-bit slave设备地址的高2bit相同,因此这个ACK可能由多有slave设备设置。第二个帧紧接着第一帧发送,包含slave地址的低8位(7:0),接着该地址的slave回复一个ACK(或NACK)。 
注意,10-bit地址的设备和7-bit地址的设备在一个系统中是可以并存的,因为7-bit地址的高5位不可能是b11110。实际上对于7-bit的从设备地址,合法范围为b0001XXX-b1110XXX,’X’表示任意值,因此该类型地址最多有112个(其他为保留地址[1])。 
两个地址帧传输完成后,就开始数据帧的传输了,这和7-bit地址中的数据帧传输过程相同。

时钟同步和仲裁

如果两个master都想在同一条空闲总线上传输,此时必须能够使用某种机制来选择将总线控制权交给哪个master,这是通过时钟同步和仲裁来完成的,而被迫让出控制权的master则需要等待总线空闲后再继续传输。在单一master的系统上无需实现时钟同步和仲裁。

时钟同步

时钟同步是通过I2C接口和SCL之间的线“与”(wired-AND)来完成的,即如果有多个master同时产生时钟,那么只有所有master都发送高电平时,SCL上才表现为高电平,否则SCL都表现为低电平。

总线仲裁

总线仲裁和时钟同步类似,当所有master在SDA上都写1时,SDA的数据才是1,只要有一个master写0,那此时SDA上的数据就是0。一个master每发送一个bit数据,在SCL处于高电平时,就检查看SDA的电平是否和发送的数据一致,如果不一致,这个master便知道自己输掉仲裁,然后停止向SDA写数据。也就是说,如果master一直检查到总线上数据和自己发送的数据一致,则继续传输,这样在仲裁过程中就保证了赢得仲裁的master不会丢失数据。 
输掉仲裁的master在检测到自己输了之后也不再产生时钟脉冲,并且要在总线空闲时才能重新传输。 
仲裁的过程可能要经过多个bit的发送和检查,实际上两个master如果发送的时序和数据完全一样,则两个master都能正常完成整个的数据传输。

注:本文是对两篇文档中协议部分的翻译整理,并做了调整和补充,见文末的附录链接。

I2C波形

设定I2C读的地址:01101101(0x6d)  10001000(0x88),注意观察第9个时钟为低电平,表示从设备应答

Slave Read Address:0x6d,ID register value:0x88

I2C源码

收集了两个I2C源码,一个是GPIO口模拟I2C,一个是androitd i2c tools

下载链接如下

链接:https://pan.baidu.com/s/1KQQuATd5Lul_IzKavzoncA 密码:8cd2

 


[1]: http://www.nxp.com/docs/en/user-guide/UM10204.pdf I2C总线规格书和用户手册Rev.6 
[2]: https://learn.sparkfun.com/tutorials/i2c SparkFun I2C手册

 

喜欢可以关注微信公众号:嵌入式Linux

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469057.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot外卖系统06: 新增员工功能+全局异常处理器

2. 新增员工 2.1 需求分析 后台系统中可以管理员工信息,通过新增员工来添加后台系统用户。点击[添加员工]按钮跳转到新增页面,如下 当填写完表单信息, 点击"保存"按钮后, 会提交该表单的数据到服务端, 在服务端中需要接受数据, 然后将数据保…

Linq 实现sql中的not in和in条件查询

T-SQL的IN: Select ProductID, ProductName, CategoryID From dbo.Products Where CategoryID in (1, 2)T-SQL的NOT IN: Select ProductID, ProductName, CategoryID From dbo.Products Where CategoryID not in (1, 2)Or Select ProductID, ProductName…

spring aop实现原理_Spring 异步实现原理与实战分享

最近因为全链路压测项目需要对用户自定义线程池 Bean 进行适配工作,我们知道全链路压测的核心思想是对流量压测进行标记,因此我们需要给压测的流量请求进行打标,并在链路中进行传递,那么问题来了,如果项目中使用了多线…

基于Springboot外卖系统07:员工分页查询+ 分页插件配置+分页代码实现

1. 员工分页查询 1.1 需求分析 在分页查询页面中, 以分页的方式来展示列表数据,以及查询条件 "员工姓名"。 请求参数 搜索条件: 员工姓名(模糊查询) 分页条件: 每页展示条数 , 页码 响应数据 总记录数 结果列表 1…

1045-Access denied for user 'root'@'localhost'(using password:YES)

解决: 1. 开始 --> cmd --> net stop mysql (停用MySQL服务 没启动的可以省略) 2. 找到安装路径 MySQL Server 5.1下的my.ini 3. 打开 my.ini 找到 [mysqld] 然后在下面加上 这句: skip_grant_tables (意思好像是 启动MySQL服务…

arial字体可以商用吗_【工作总结】莫让字体版权引火上身

前段一条微软雅黑字体引发的巨额罚款新闻,引起国内多个TW大群小地震,人人自危。我也赶紧检查自家文档、商用出版物、网站的字体,以免给公司带来法务后患。把这两天收集的信息,采取的行动记录一下。哪些中文字体免费?事…

基于Springboot外卖系统08:员工账号状态管理功能+对象转换器+扩展Spring mvc的消息转换器

1. 员工账号状态管理 1.1 需求分析 在员工管理列表页面,可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登录系统,启用后的员工可以正常登录。如果某个员工账号状态为正常,则按钮显示为 "禁用",如果员工…

Android init.rc 服务启动不成功

Android init.rc 服务启动不成功 问题 在开发过程中发现一个问题,我们需要在开机的时候判断硬件版本号去启动服务, 服务的名字是ledservice和ledservice4,但是发现每次烧录完固件后,服务启动不 成功,需要再复位重启一次&#xff0…

python爬虫什么网站都能爬吗_python如何爬取动态网站

python有许多库可以让我们很方便地编写网络爬虫,爬取某些页面,获得有价值的信息!但许多时候,爬虫取到的页面仅仅是一个静态的页面,即网页 的源代码,就像在浏览器上的“查看网页源代码”一样。一些动态的东西…

hdu4027Can you answer these queries?

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid4027 区间&#xff08;单点&#xff09;更新&#xff0c;区间求和。 1 #include<cstdio>2 #include<algorithm>3 #include<cmath>4 #define lson l,m,rt<<15 #define rson m1,r,rt<…

基于Springboot外卖系统09:员工信息编辑+员工信息保存

1 编辑员工信息功能 1.1 需求分析 在员工管理列表页面点击 "编辑" 按钮&#xff0c;跳转到编辑页面&#xff0c;在编辑页面回显员工信息并进行修改&#xff0c;最后点击 "保存" 按钮完成编辑操作。 那么从上述的分析中&#xff0c;当前实现的编辑功能需…

共享资料

共享资料 请关注公众号 嵌入式Linux 索取posted on 2018-09-22 00:27 公众号&#xff1b;嵌入式Linux 阅读(...) 评论(...) 编辑 收藏

selenium-05-常见问题

一&#xff1a;日期控件 selenium不能直接对日期控件操作&#xff0c;可以通过js对日期控件做赋值操作 WebElement inputTimeBoxdriver.findElement(by.name("###")); //定位日期控件 Stringtime "2015/10/10"; ((JavascriptExecutor)driver).executeScri…

bcp 不能调用where 子句_MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!

不知道从什么时候开始&#xff0c;网上流传着这么一个说法&#xff1a;MySQL的WHERE子句中包含 IS NULL、IS NOT NULL、! 这些条件时便不能使用索引查询&#xff0c;只能使用全表扫描。这种说法愈演愈烈&#xff0c;甚至被很多同学奉为真理。咱啥话也不说&#xff0c;举个例子。…

基于Springboot外卖系统10:公共字段填充功能+ThreadLocal模块改进

1. 公共字段自动填充 1.1 问题分析 在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段&#xff0c;在编辑员工时需要设置修改时间、修改人等字段。这些字段属于公共字段&#xff0c;也就是也就是在系统中很多表中都会有这些字段&#xff0c;如下&#xff1a; 而…

## __VA_ARGS__ ... 宏和可变参数

在GNU C中&#xff0c;宏可以接受可变数目的参数&#xff0c;就象函数一样&#xff0c;例如: 1 2 #define pr_debug(fmt,arg...) \ printk(KERN_DEBUG fmt, ##arg) 用可变参数宏(variadic macros)传递可变参数表 你可能很熟悉在函数中使用可变参数表&#xff0c;如: 1 vo…

腾讯云挂在和格式化数据盘

新购买了数据盘时&#xff0c;需要格式化才可使用。未购买数据盘的用户可以跳过此步骤。也可以根据需要进行多分区操作。 这里以Windows 2012R2为例进行格式化说明。 1) 通过步骤四介绍的方法登录Windows云服务器。 2) 点击【开始】&#xff08;Start&#xff09;-【服务器管理…

基于Springboot外卖系统11:菜品新增类别+类别信息分页查询

1. 新增分类 1.1 需求分析 后台系统中可以管理分类信息&#xff0c;分类包括两种类型&#xff0c;分别是 菜品分类 和 套餐分类 。当我们在后台系统中添加菜品时需要选择一个菜品分类&#xff0c;在后台系统中添加一个套餐时需要选择一个套餐分类&#xff0c;在移动端也会按照…

Linux内核自旋锁

Linux内核自旋锁 自旋锁 自旋锁&#xff08;spinlock&#xff09;是用在多个CPU系统中的锁机制&#xff0c;当一个CPU正访问自旋锁保护的临界区时&#xff0c;临界区将被锁上&#xff0c;其他需要访问此临界区的CPU只能忙等待&#xff0c;直到前面的CPU已访问完临界区&#xf…

词云python_诗词名句网 -古诗词大全|诗歌|诗词鉴赏|古诗名句|诗句赏析!

倾酒向涟漪&#xff0c;乘流欲去时。 寸心同尺璧&#xff0c;投此报冯夷。 展开全文 江曲全萦楚&#xff0c;云飞半自秦。 岘山回首望&#xff0c;如别故乡人。 浦烟含夜色&#xff0c;冷日转秋旻。 自有沈碑在&#xff0c;清光不照人。 楚岸云空合&#xff0c;楚城人不来。 只…