一种高效可编程I2C从设备
介绍
设备间的低速串行通信大多采用I2C总线形式。有各种各样的I2C接口的从设备,但具有可编程的I2C从设备确较少。
举例来说,微控制器就是一种可编程的I2C从设备。使用微控制器来模拟I2C从设备并不困难;但近来这种方式受价格和低功耗等因素的限制。新一代低成本、低功耗的微处理器可以很容易地嵌入到可编程I2C从设备中。
典型的I2C系统由一个主控设备和多个从设备组成。此系统可以分解成很多子系统,每个子系统可以由专用的低成本的微控制器控制。每个子系统都和更高速度(通常也会更贵)主控连接。这种方法允许工程师并行开发数个子系统,这些子系统和主控设备相连时仅再需少量的开发活动。图1 给出了此系统的典型结构,每个微控制器控制各自的子系统,所有的微控制器连接到一个I2C主控设备。
假定一个系统由一个线性位置传感器,一个由马达驱动的线性划片,以及基于传感器反馈信号对马达控制的代码。将此控制代码集成到单个主控设备的软件中并不很容易,但很容易将其集成到子系统的微控制器中去。对线性划片进行定位时,主控制器可以通过向某个I2C寄存器写入8bit或16bit定位数据来实现。这种做法的一个额外优点是,因为仅和数字控制接口进行交互,子系统的设计者无需担心其它实时系统工作时会占用微控制器的资源。
图1 工程师可以并行开发多个可编程的I2C从设备,从而加快开发速度。
I2C背景
通过I2C接口进行数据传输仅需两根线(不包括地线)和数据包控制协议。不管数据的流向如何,数据传送总是由主控设备发起。每次数据传输都是以I2C-START条件开头,以I2C-STOP条件结尾(如图2)。
图2 I2C数据的传输总是以START作为数据帧的开始,以STOP标志作为数据帧的结束。
数据以字节为单位进行串行传输。典型地,第一个传输的字节是7bit的从设备地址,其后是R/W控制bit(可能的例外是10bit的地址和高速模式前缀). 后续数据的传输方向由R/Wbit位决定。所有的数据字节后面都带有ACK应答bit位,ACK bit不仅作为数据完整性指示,同时也是流控手段。
图3 数据线的状态变换只能发生在SCL低电平状态,否则会和START/STOP条件混淆。
为避免数据和起始条件的混淆,SDA线上数据变换总是发生在SCL低电平处。
典型的I2C数据帧格式为,一位起始位,7bit的从设备地址,1bit R/W标志,以字节为单位的数据串,一个停止位。
图4典型的I2C总线数据传输格式,一个START位,一个STOP位,一些字节宽度的数据。
总线接口电路
I2C从设备需要一直监视总线是否出现START和STOP条件,如果检测到此条件并检测到相应的从设备地址,则此从设备就要作出响应。通过GPIO进行不断查询的方式来检测SDA/SCL总线会一直占用微控制器的资源,比较好的方法是采用中断方式。即便如此,依然会占用相当的处理器资源。比如I2C主控发送不同的从设备地址时,所有的微控制器都要进行响应,无论使用轮询还是采用中断方式。因此为了尽量将微处理器资源分配给其它任务以使系统的效率最大化,可以采用硬件的方式来检测START和STOP位。
图5 I2C-START 和 I2C-STOP条件检测电路。
见图5所示,硬件接口由如下器件组成:两个D触发器、两个MOSFET、两个缓冲器、一个反相器。该硬件接口负责START和STOP条件检测。所以,微控制器无需再在此条件的检测上耗费资源。此电路符合I2C规范,每根线所增加的负载电容不超过10pf,同时兼容100kHz和400kHz通讯速率,仅消耗4uA的电流。
图6 接口电路可以自动产生相应于START和STOP条件的中断。
I2C从设备架构
软件架构使用C语言编写,采用CrossStudio编译后在MAXQ2000上执行。MAXQ2000是美信公司的16bit低功耗微处理器。尽管本文给出的源代码是针对MAXQ2000的,但下面代码的流程可适用于任何具有边沿触发中断类型的微处理器,不过需要此微处理器在运行时可以动态配置边沿的触发类型。
此软件架构仿真了一个基于寄存器的I2C从设备,该从设备拥有一个8bit的指针寄存器和一些可配置的读写寄存器。当需要向某个寄存器写入数据时,需要将指针寄存器的内容先初始化为该寄存器的地址。数据按字节依次写入,每写完一个字节指针寄存器内容自动加一。
图7 软件框架中包含一般I2C设备的典型寄存器配置。
图8 示例了一个I2C数据传送过程,注意每次数据的传送都对指针和数据寄存器进行写操作。
图8 向从设备写入数据时,必须先对指针寄存器进行初始化。
图9所示,读寄存器需要繁琐一些,因为此时读写动作都要发生,如上所述,写的时候先初始化指针寄存器。虽然一系列的读写操作可以通过STOP条件后接START条件进行区分。但此效率不高,编程人员可以直接用Sr(repeat-START)条件代替STOP和START条件的组合来提高传输效率。在使用方法上,Sr和START很类似,但Sr只能在一对START和STOP条件之间使用。
图9 直接用Sr(repeat-START)条件代替STOP和START条件的组合来提高传输效率。
具体实现
此软件架构隐藏了I2C从设备的实现细节,并添加了几个钩子(hook),这样使程序的开发非常容易。可用的钩子包括:
初始化例程:
void FWInit(void)
{
// This hook is only called once during the program execution. It is called
// after power-up but before the first FWPoll(). Place any initialization
// code such as Port I/O, Timer, and Interrupt initialization in this routine.
// Initialize I2C Registers to some default variables
I2C_REGS[0] = 0x11;
I2C_REGS[1] = 0x22;
I2C_REGS[2] = 0x33;
I2C_REGS[3] = 0x44;
I2C_REGS[4] = 0x55;
I2C_REGS[5] = 0x66;
I2C_REGS[6] = 0x77;
I2C_REGS[7] = 0x88;
// Initialize Port 2 for Square Wave Output
PD2 = 0x01;
delay();
}
轮询例程:
void FWPoll(void)
{
// This hook is called repeatedly by the micro and serves as the controller
// 'main loop' function. Code such as I/O polling should be placed here.
PO2 = (!PO2 && 0x01); //Toggle Output pin on Port 2
delay();
}
因为MAXQ2000对所有的中断条件都放在一个中断矢量中,所以需要一个遍历的中断句柄例程对此中断矢量进行判断以检查是否发生了某个中断。
void FWIntHandler(void)
{
// User interrupts are handled here. Do NOT disable the global interrupt mask,
// as that would disable I2C detection. Also, do NOT mask any of the I2C
// related interrupt bits. I2C interrupts may occur during your interrupt
// routine and these must be considered a top priority.
}
另外一个更重要的I2C中断服务程序(ISR)。
void FW_I2C_Action(void)
{
// Use this routine to hook into the I2C interface. After every
// valid I2C write transaction to this device, the routine is called.
// The affected registers are identified using bits contained in global
// character arrays.
// Special bit handler routines are included to quickly parse the array
// and test for register changes.
if (FlagsChanged())
{ // One of the Registers has changed and it needs servicing
// Figure out which one it is
if (GetRegFlag(0x00))
{// Service register 0x00
PO3 = 0xFF;
PO3 = 0x00;
PO3 = 0xFF;
}
if (GetRegFlag(0x01))
{// Service register 0x01
PO3 = 0xFF;
PO3 = 0x01;
PO3 = 0xFF;
}
}
}
作为I2C从设备寄存器和用户软件之间的连接桥梁,每次数据的写操作都会调用I2C中断服务程序。软件会使用经济且有效的位标志(bit-flag)自动记录寄存器的变化。因此也会极大的减轻软件设计者跟踪寄存器变化的负担。通过内嵌的帮助函数可以访问标志位同时可以检查并设置一个,多个甚至所有的标志位。如同上面软件所示,使用这些函数可以实现简单的寄存器检查算法。
状态图
I2C通讯接口会占用少量的微控制器资源。使用中断来创建状态机可以极大减轻处理器的负担。状态机中状态的变迁由START、STOP和SCL中断条件触发。
一个START中断总是强制状态机进入地址检测状态。一个STOP中断总是中断状态机正在执行的任务,同时清空输入缓存,释放SDA数据线并回到IDLE状态。
SCL线连接到一个从设备的中断线上,当I2C主控设备在和其它从设备进行通讯时,此从设备的SCL中断被屏蔽。因为I2C从设备对SCL上升沿和下降沿都要响应,所以SCL沿中断类型需要在运行时能够动态修改。本文所选的MAXQ2000支持此动态修改特性。
图10 可编程I2C从设备的状态机。
效率
因为软件架构是中断驱动的,所以仅消耗极少的微处理器资源。前面示例的代码可以用于计算效率。此代码使用微控制器的一个GPIO引脚作为FWInt()钩子函数的输出。延迟循环函数FWPoll()在GPIO口上提供展宽的时钟输出。
图11 I2C总线无活动时,微处理器可以以最快的速率驱动GPIO口的输出。
当I2C总线上没有数据传输时,微控制器拥有全部资源并且GPIO口输出一个固定频率的方波。当总线上有数据活动时,由于状态机的运行会占用微控制器的资源,所以GPIO上方波脉冲会展宽。在100μs的时间窗口内计算脉冲的个数,然后计算在I2C IDLE状态下和I2C总线活动状态下脉冲个数的比例;结果发现在I2C传输状态变换期间,I2C的状态机需要占用30%的微处理器资源。尽管资源的平均专用率依赖于I2C数据传送长度和频率,但最大的资源专用率不会超过30%。
图12 I2C总线上有数据传输时将占用一部分微处理器资源来处理输入的数据。
成本
软件架构包含了最小化的代码量和最优的代码执行效率。总共需要824字节的代码空间以及6+寄存器数量的数据空间。总线接口电路预算大概为70美分并且仅消耗最大4uA的电流。和不可编程的I2C从设备相比,此解决方案总共需要花费4-5美元。所选的微控制器是节省空间的QFN封装,并且总线接口电路是SOT-23和SC-70封装,所以PCB的尺寸可以较小。
发展趋势
尽管本文在实现时选用的是7bit的I2C从设备接口,但代码很容易修改为10bit的从设备应用。根据所选的微控制器,接口可以优化工作在400kHz快速(FS)模式或1.7/3.4MHz高速(HS)模式。另外设计者还可以增加一个中断线(SMBALERT#),通过此中断线来要求设备对地址0x18(SMBus Alert Response Address)作出响应。一个I2C从设备可以通过保持时钟线为低的方式来降低数据传送速率。如果微控制器必须对一些优先级更高的实时处理作出响应时则需要增加此功能。
此处的软件主要为低功耗的微控制器所写的,可以在此基础上开发可编程的的I2C从设备。欲知更多的信息及实现细节,请参考此应用的软件。
作者:Eric Schlaepfer, 美信集成(Maxim)
参考资料
"The I2C-Bus Specification," version 2.1, Phillips Semiconductors, January 2000
"System Management Bus (SMBus) Specification", version 2.0, SBS Implementers Forum, August 2000
本文来源:电子系统设计 作者:美信集成(Maxim) Eric Schlaepfer
关于 微处理器 的相关解决方案
- 2008-07-09一种时间触发的多任务调度器设计
- 2008-07-03基于AT91R40008微处理器的软件定时器设计
- 2008-06-30基于ARM-LPC2368的网络接口的设计与实现
- 2008-05-30基于ARM嵌入式近红外光谱仪器的研制
- 2008-05-29基于ARM嵌入式近红外光谱仪器的研制
微处理器 相关产品动态
- 2008-05-15AMD微处理器业务负责人辞职
- 2008-04-21全新Digi NET+ARM微处理器迎合应用程序需求
- 2008-04-18英特尔一季度同比增收9% 但因价格下降NAND销售额未增加
- 2008-03-04英特尔发布Atom低能量处理器 最高能耗2.5瓦
- 2008-02-15飞思卡尔同意以1.1亿美元收购矽玛特

