本应用笔记讨论了通过 I?C 兼容接口读取多字节数据时需要注意的事项。通过一些具体示例讨论了读取一个字节的陷阱。本文还描述了处理此类数据传输的正确方法。**
简介
I2C 是嵌入式系统中使用的串行数据传输协议之一。它用于将低速外围设备连接到嵌入式微处理器。它还用于中低数据速率通信。EPROM、实时时钟系统存储设备、远程温度
传感器和 I/O 端口扩展器是慢速外围设备的一些示例。
IC 兼容的两线接口是一种强大的机制,用于将
微控制器或微处理器连接到低速外设,例如具有集成模数
转换器 (ADC) 的外设。通过该总线进行通信的基本形式(即,向/从从设备寄存器写入/读取单个字节)非常简单。然而,为了简单起见而将自己限制于这种方法有一些陷阱。
1 字节通道上的 2 字节数据
与外设(尤其是传感器)的任何其他数字接口一样,我们需要从设备的内部寄存器读取正确的数据。当寄存器中的数据在读取过程中发生变化时,这一点尤其重要。如果 ADC 在数据传输时运行转换或更新寄存器,则数据可能会发生变化。许多设备都有一个内部缓冲区(通常无法从外部访问),其中包含的转换结果。当没有 I?C 活动时,设备会使用新数据更新所谓的“客户可访问”寄存器。
IC 协议传输 1 个字节的数据。因此,如果感兴趣的数据总量超过 8 位并且传输处理不当,可能会出现问题。例如,MAX44000的环境
光传感器(ALS)数据寄存器多可以有14位数据(加上1位指示溢出,这意味着计数/勒克斯设置应该增加)。
我们无法通过 IC 直接读取全部 ALSDATA[13:0],因此必须首先读取寄存器 0x??04 的内容,然后读取寄存器 0x??05 的内容,并将数据连接到至少一个 16 位寄存器中。但是,我们必须注意如何读取这些数据。可以简单地执行由 STOP (P) 条件终止的两次单次读取,如图 1 所示。
这种方法有一个致命的缺陷。具体来说,发送停止条件信号设备返回更新“客户可见”寄存器。因此,在从寄存器0x04获取数据之后,实际上可以在读取寄存器0x05之前更新14位数据。在某些情况下,此缺陷可能会造成灾难性后果。
一个例子是,如果光线水平处于特定水平,且 MAX44000 环境光传感器处于 10 位、12 位或 14 位模式。假设电平在某个区域中徘徊,因此寄存器 0x??04 和 0x05 中的 14 位的总计数将达到 255 或 256,这可能是由于光线缓慢增加或一些少量噪声造成的。考虑图 2 所示表中的三种情况。
单字节读取。
在两种情况下,我们读取的不是 255 或 256,而是 0 或 511。这是一个很大的问题。发生这种情况是因为在发送 STOP 条件后,寄存器 0x??04 和 0x05 中的数据在次和第二次读取之间进行了更新。在个有问题的情况下,个字节被正确读取。但到读取第二个字节时,数据读取总数为 256,其中字节为零。因此我们从设备中得到的读数为零。在第二种有问题的情况下,数据总数也是 256 个计数。这似乎变成了 511 个计数,因为在发送 STOP 条件之后、读取第二个字节之前,数据减少了一个计数。请参阅图 3,了解多次读取过程中发生这种情况的次数示例。
单字节读取多个样本的实际读数。
通过读取 2 个字节可以轻松避免此问题,如图 4 所示。这是通过在读取个数据字节后发送 REPEATED START 而不是 STOP 条件来完成的,并且实现起来相当简单。通过读取 2 个字节,我们可以防止该部件执行更多 I?C 寄存器更新,即使我们在两个设备之间发送相同数量的位数。
2 字节读取的图示。
上述示例适用于 MAX44000 和 MAX44009,在进行多次读取时不会自动递增寄存器指针。您的设备的行为可能有所不同,但原理始终相同。这很容易扩展到读取 N 个字节。