[导读] 前文大体总结了单片机串口的一些值得注意的要点,本文来梳理一下I2C总线的一些应用要点。这个题目有点大,对于I2C其实不少地方也没讲清楚,只为了与前文造成系列,若是你们有补充欢迎留言。说了些闲话,进入正题吧。编程
\(I^2C\)(Inter-Integrated Circuit),是一种同步、多主、多从、分组交换、单端、串行计算机总线,由飞利浦半导体(如今的NXP半导体)在1982年发明。它普遍用于在短距离、板内通讯中将低速外设集成电路附加处处理器和微控制器上。\(I^2C\)也能够写成I2C或IIC。微信
自2006年10月10日起,实施I2C协议不须要任何许可费用。 可是,得到恩智浦分配的I2C从设备地址须要付费。一些竞争者,如西门子(后来的英飞凌技术,如今的英特尔移动通讯)、NEC、德州仪器TI、意法半导体(之前的SGS-Thomson)、摩托罗拉(后来的飞思卡尔,如今与NXP合并)、Nordic半导体和Intersil,自20世纪90年代中期以来已经将发布了不少兼容的I2C标准的芯片。
异步
自Version 4以后 I2C支持下面几种模式:测试
I2C标准能带来些啥好处呢?ui
系统管理总线(SMBus),由Intel在1995年定义,是I2C的一个子集,定义了更严格的用法。SMBus的一个目的是促进健壮性和互操做性。所以,现代I2C系统合并了来自SMBus的一些策略和规则,有时同时支持I2C和SMBus,只须要经过命令或输出引脚使用最小限度的从新配置。spa
TWI(双线接口)或TWSI(双线串行接口)本质上是在Atmel和其余供应商的各类系统芯片处理器上实现的同一总线。翻译
从概念上,I2C总线有两根线SDA/SCL就能够连一堆芯片,实现不少的应用。链接拓扑极简!
设计
好比这样一个系统:3d
接下来看看各模式下,链接拓扑图:调试
标准速度/快速模式:
高速模式拓扑:
混速模式拓扑:
若是使用IO口模拟I2C总线,或者使用FPGA实现I2C接口,深入理解I2C时序波形无疑是重点中的重点!即便使用内置的I2C控制器外设实现一个I2C总线编程,在调试底层时或者踩坑过程当中,深刻理解时序波形原理,也是很是必要的!
I2C的时序图以下:
START事件:能够联想一下UART的起始位,这个用于通知I2C通讯的发起。用一句话描述就是在SCL常高时,采集到SDA高到低跳变,这就是启动事件。
数据有效性:SDA线上的数据必须在时钟的高周期保持稳定。数据线的高或低状态只能在SCL线上的时钟信号低时改变。每一个传输的数据位产生一个时钟脉冲。
ACK:确认信号ACK的定义以下:发送器在ACK时钟脉冲期间释放SDA线,所以接收器能够将SDA线拉低,并在此时钟脉冲的高电平期间保持稳定的低电平(见上图)。须严格遵循电气的创建保持时间,使用时须要用示波器去严格测试信号是否能知足这些参数。
NACK:当在第九个时钟脉冲期间SDA保持高电平时,这被定义为“NACK”信号。 以后主机能够产生中止条件以停止传输,或产生重复的开始条件以开始新的传输。 致使NACK产生的条件有五个:
时钟同步:两个主机能够同时开始在空闲总线上进行传输,而且必须有一种方法来肯定控制总线并完成其传输的方法。 这是经过时钟同步和仲裁完成的。 在单主机系统中,不须要时钟同步和仲裁。
时钟同步是经过I2C接口中SCL线的线与实现的。啥意思呢?
这里的几句话须要划重点去理解,这就是I2C总线的核心之核心工做原理:线与!
仲裁:仲裁与同步相似,仅在系统中使用多个主机时才会涉及到,从站不参与仲裁过程。首先要理解一下仲裁是干啥的?所谓仲裁就是在多主机模式下,哪个主机能获取介质的访问权限,得到权限的主机才能够传输I2C通讯报文。 只有在总线空闲时,主机才能够开始传输。 两个主机能够在START的最小保持时间内产生START条件这种状况会致使总线上出现有效的START条件。 而后须要仲裁以肯定哪一个主机将完成其传输。
仲裁是一位一位地进行。 节点发送1个位后,回读比较总线上所呈现的数据与本身发送的是否一致。是,继续发送;不然,退出竞争。SDA线的仲裁能够保证I2C总线系统在多个主节点同时企图控制总线时通讯正常进行而且数据不丢失。总线系统经过仲裁只容许一个主节点能够继续占据总线
上图显示了两个主机的仲裁程序。 实际使用中链接到总线的主机数量可能会更多。 当主机产生的DATA1的内部数据电平与SDA线上的实际电平之间存在差别时,DATA1输出将关闭。 从而主机1退出竞争,没有得到总线的控制权。
时钟延长:时钟延长经过将SCL线保持为低电平来暂停事务。 直到再次释放高电平,事务才能继续。 时钟延长是可选的,实际上,大多数从设备不包括SCL驱动能力,所以它们没法延长时钟。
为啥要设计这样一个机制呢?我的理解是为了加强系统的健壮性而设计的:
在字节传输级别,设备可能可以以快速速率接收数据字节,但须要更多时间来存储接收到的字节或准备另外一个要发送的字节。此时,从机能够在接收和确认字节后将SCL线保持为LOW,以强制主机进入等待状态,直到从机为握手过程当中的下一个字节传输作好准备。
在位级别上,诸如微控制器之类的设备能够经过延长每一个时钟的LOW周期来减慢总线时钟。 任何主机的速度都将根据该设备的内部工做速率进行调整。
10位地址:分读写两种状况
保留地址
从设备地址 | 读写位 | 描述 |
---|---|---|
0000 000 | 0 | 广播地址 |
0000 000 | 1 | 启动字节 |
0000 001 | X | CBUS地址 |
0000 010 | X | 预留给不一样的总线格式 |
0000 011 | X | 预留将来扩展使用 |
0000 1XX | 1 | Hs-mode 主代码 |
1111 1XX | 1 | 设备ID |
1111 0XX | X | 10位从地址 |
通用广播地址用于同时寻址链接到I2C总线的全部设备。 可是,若是设备不须要处理广播数据,则能够经过不发出ACK来忽略该地址。 若是某设备须要来自通用广播地址的数据,它将发送ACK给该地址并充当从接收器。 主机实际上不知道有一个或多个设备响应时确认了广播数据(不肯定有多少个ACK)。 每一个可以处理此数据的从机接收器都会确认第二个字节和随后的字节。 没法处理这些字节的从站将不该答从而忽略。 一样,若是一个或多个从机应答,则主机不会看到未确认的消息。通用广播地址的含义老是在第二个字节中指定,以下图:
1.当B为0时,第2字节定义以下:
0000 0110(06h):设备将复位以及设置地址的可编程部分。 接收到这个2字节命令后,全部支持响应通用广播地址的设备将复位,并将其地址的可编程部分改写保存。
须采起预防措施以确保设备在施加电源电压后不会拉低SDA或SCL线,由于这些低电平会阻塞总线。
0000 0100 (04h):收到该命令后设备将经过硬件设置地址的可编程部分。(Write programmable part of slave address by hardware).
0000 0000 (00h): 不容许将此代码用做第二个字节.
对于06h/04h这两个命令,有些不太好理解。复位比较好理解。对于设置设备地址的可编程部分可能不少没有遇到过的朋友则不太好理解。这里来一个实际芯片的例子,以Microchip的MCP3423/MCP3424为例进行描述一下,MCP3423/MCP3424是一颗多通道ADC芯片,其芯片引脚以下:
当接收到通用广播访问且第2字节为06h命令后,芯片作两件事情:
固然对于不一样的芯片,具体如何实现通用广播地址的处理则各有不一样,只须要认真阅读芯片的手册就能获取相应信息。这里仅仅就通用广播地址举个栗子,方便理解。老实说这个功能好像不太常见,具体有什么用?我反正没这么用过,感受这功能有点蛋疼(直接用电阻配置好不更省事?)。若是有好的应用实例场景,欢迎留言交流。
2.当B为“ 1”时,则该2字节序列为“硬件通用呼叫”。 该报文由I2C主设备(例如键盘扫描器)发送,能够对其进行编程以发送所需的从地址。 因为I2C主设备事先不知道该消息必须传输到哪一个从设备,故利用通用广播地址及通用呼叫命令并将自身的地址放在高7位,从而标识总线上发送通用硬件呼叫的设备ID。 该地址由链接到总线的智能设备识别(好比该智能设备是一个单片机系统),而后该智能设备从硬件主机接收信息。 若是硬件主机也能够充当从机,则从机地址与主机地址相同。
因此标准中定义这个功能,能够作些自适应应用,只须要制定出相应协议就能够完成比较灵活的多主通讯应用协议。
如上面描述,当通用广播地址后面跟06h字节,就可使从设备软复位。但这个功能并不是全部芯片都支持,具体使用的时候须要仔细阅读芯片手册是否支持该功能。
须采起预防措施以确保设备在施加电源电压后不会拉低SDA或SCL线,由于这些低电平会阻塞总线。
单片机/DSP能够用两种方法链接到I2C总线:
好比在一个多单片机用I2C总线连一块儿的系统,其中一个单片机I2C是用IO口模拟的,则快速的硬件设备与依赖软件轮询的相对较慢的单片机之间存在速度差别。这个不难想象,由于依靠轮询则不是硬实时,同时单片机确定还有其余事物须要处理,那么检测START条件信号就有可能丢失,致使系统不健壮。那么I2C标准已然考虑这种需求了。
这就是起始字节须要解决的需求,前面介绍的就是起始字节设计的背景。那么起始字节到底是怎样的呢?
在须要访问总线的主机发送了START事件以后,发送START字节(0000 0001)。 另外一个单片机/DSP能够以低采样率对SDA线进行采样,直到检测到START字节中的七个零之一为止。 在SDA线上检测到此LOW电平后,微控制器能够切换到更高的采样率,以找到重复的START事件,而后将其用于同步。
在异常状况下,若是时钟SCL被拉为LOW了,则有哪些办法能够对总线复位呢?
//可能须要先关闭I2C控制器,若是是使用I2C控制器外设实现的 //I2C_SCL根据不一样硬件进行移植,delay #define I2C_SCL P10 void soft_rst_i2c(void) { I2C_SCL = 1; for(int i=0;i<9;i++) { I2C_SCL = 0; delay(xx); I2C_SCL = 1; delay(xx); } }
前面两种方法是更健壮的方案,若是硬件不支持,能够考虑后一种方法,但后一种方法的前提是拉死SCL的设备须要支持这种功能,若是两端都是自定义开发的则比较灵活了。
总线锁死,是I2C总线系统常踩的坑,有哪些缘由会致使锁死呢?程序不健壮,I2C的波形不知足I2C规格书要求,或者在外加干扰状况下致使波形被干扰。有经验的同窗可能会遇到设备平时工做的好好的,可是作EMC测试,经常设备会莫名死机,若是你的设备有I2C总线,请记得检查I2C是否被EMC干扰干死了!
设备ID字段是一个可选的3字节只读(24位)字,提供如下信息:
这个对于设计软件有什么能够利用的信息呢?好比一个系统可兼容不一样厂家的基于I2C协议的传感器,利用这个字段就能够作设备信息管理。至于怎么读取,不一样芯片或有不一样。
前面拓扑图中采用open-drain 开漏结构。I2C有的还用集电极开路输出结构,究其缘由是内部是三极管的集电极开路。以下
在Rev 4中还出现了Ultra Fast-mode,该模式使用push–pull推挽定义I2C内部硬件接口电路(我把它叫推拉),这个又长什么样呢?
这种推挽接口是用在Ultra Fast-mode(UFm)模式,为啥不继续采用集电极开路门/漏极开路门呢?由于这两种硬件已然没法知足如此高速的通信波形要求了,推挽输出能够实现更为快速波形前沿特性以驱动总线电容负载。
对于Ultra Fast-mode模式其余如时序波形,报文定义基本一致,这里不作赘述了。须要提醒的是设备ID在该模式下不支持!
为何要特别讨论一下总线的容性负载特征呢?想象中的理想通讯波形:
因为容性负载以及充放电常数特性,实际中却多是这个鸟样:
若是实际总线中电阻选取过大,或者容性负载过大(设备节点过大或者布线不合理),也即RC常数过大,甚至多是这个德行:
那么参数选取合适时,波形则多是这样的:
因此就其本质而言,就是因为驱动接口电路的RC参数影响了波形的时序参数:
实际应用中,一方面电阻须要选取足够大以下降没必要要的电流消耗,另外一方面电阻又须要选择足够小以知足对应传输速度的波形时序要求。故须要在这一对矛盾体中寻求一个折中平衡!实际项目中先用示波器测测I2C波形很是必要,代码对了总线可未必如愿工做。作底层开发,尽可能先硬后软~~
I2C总线从电气特性上须要特别注意的是其容性负载特征:
Fast-mode:链接到总线的外部上拉设备必须通过调整,以适应快速模式I2C总线较短的最大容许上升时间。 对于200 pF之内的等效总线负载,每条总线的上拉设备能够是一个电阻。 对于200 pF至400 pF之间的总线负载,上拉设备能够是电流源(最大3 mA)或开关电阻电路。
Fast-mode Plus (Fm+):该模式下设备中的驱动接口电路驱动能力比较强大,能够知足Fast-mode Plus时序规范,并具备与标准模式部件相同的400 pF负载。 为了与标准模式向后兼容,它们还能够承受标准模式设备的1μs上升时间。 在仅存在Fast-mode Plus部件的应用中,强驱动接口和对缓慢的上升和降低时间的容忍度容许使用较大的总线电容,只要软件设置好或硬件IC实现好,Fast-mode Plus的最小LOW时间和最小HIGH时间便可知足全部要求,而且降低时间和上升时间不超过标准模式的300ns上升沿时间和1μs 降低沿时间规格。 能够将总线速度与负载电容进行折衷,总线电容可增长大约十倍。
Hs-mode: 高速模式(Hs-mode)器件在I2C总线传输速度方面实现了飞跃。 高速模式设备能够实现高达3.4Mbit/s的比特率传输速度,但仍然向下兼容,与快速模式加强版、快速模式或标准模式(F/S)设备彻底兼容以进行双向通讯总线系统。 除了在Hs模式传输期间不执行仲裁和时钟同步外,与F/S模式系统保持相同的串行总线协议和数据格式。那么如此高速是如何作到的呢?这里将我的认为与应用相关的要点翻译总结下:
具体设计时,可参考规格书电气特性参数规定以及所选芯片的手册。
编程时,比较好的方式就是处理相应的中断事件。利用内置I2C控制器是优选方案。
在实际项目中,须要特别注意I2C的上升沿、降低沿波形时间参数是否知足设计速率要求,可经过配置寄存器以及调整驱动上拉电阻进行调整。对于高速模式则可能须要用电流源进行驱动。另外须要注意的是,I2C总线锁死状况处理。
I2C总线是一个比较复杂的芯片间总线系统,你或许会用。可是若是不注意标准的不少细节,你可能没法用好!尤为总线上挂不少设备时,系统很可能不健壮!本文主要参考I2C version标准,I2C总线看似简单却极为复杂,本文总结了规格书中一些要点,也并不全面。在复杂应用场景中,还须要多多踩坑、填坑并加以总结。前文谈到了对于技术要点尽可能总结、归纳以及提炼,这里想提醒的是一些技术要点的标准每每是最为严谨、也最为全面的总结。具体使用时,可多多研读。
I2C VERSION6规格书可至www.i2c-bus.org下载,也能够至公众号后台回复I2C6,可直接领取。
文章出自微信公众号:嵌入式客栈,版权全部,严谨商用,更多内容,请关注本人公众号