0

我在尝试使用 dsPIC33f 微控制器对 I2C 从设备进行采样时遇到问题。

我正在使用 PIC 内部 timer1 计时器以定义的采样率“滴答”并获取必要的数据。不幸的是,获得结果的速度不够快,我不知道为什么。我的从属设备之一是 ADXL345 加速度计,它的最大输出数据速率为 3600Hz。我几乎不需要这么高,但我似乎没有在 50Hz 以上的任何地方成功采样。

I2C 设置为 400KHz 的“快速模式”。我想要对加速度计进行采样的绝对最大值是 1KHz,虽然这有点矫枉过正,但我​​真的对 128Hz 更感兴趣。我设置的加速度计的参数是:

  • 数据格式 (0x31) - 自检关闭、中断反转关闭、全分辨率开启、对齐位关闭、范围位 +/-16g。
  • 数据速率 (0x2C) - 低功耗模式关闭(正常模式),输出数据速率模式 400Hz(我在数据表中读到 400KHz I2C 仅支持高达 800Hz,所以我在使用 400Hz 时比较安全)。
  • 电源控制(0x2D)——自动睡眠关闭,测量模式开启,睡眠位关闭,睡眠模式采样率8Hz(虽然没有使用,所以可以忽略)。
  • 中断 (0x2E) - 启用数据就绪中断,其他一切都关闭。

我正在使用 timer1 以指定的采样率进行采样,我知道采样率工作得很好,因为我有一个计数器,它会在计数器达到一分钟后输出一条消息;我用秒表来确保它是正确的。例如,在 100Hz 采样率下,我等待计数器计数到 6,000 (100 * 60) 并显示一条消息,如果秒表在 1 分钟时看到该消息,我知道它至少在一定程度上进行了采样。

当我尝试仅从加速度计采样(I2C 多字节读取模式,一次调用读取所有六个字节)时,它的执行速度不够快。使用我的秒表方法,它似乎需要大约一分 15 秒来完成一项应该需要一分钟的工作(以 100Hz 采样),即它处理 I2C 命令的速度不够快。更高的采样率会增加更多的延迟。

我感觉这与 I2C 时钟和 timer1 未同步有关,因此在我对加速度计数据的调用中存在不必要的等待。我无法想象 I2C 的 400KHz 时钟是不够的,但如果我错了,请纠正我。

我应该如何正确地从 I2C 从设备读取数据?我还有一个陀螺仪和磁力计,我想以足够高的采样率读取它们,磁力计的限制为 160Hz,所以正如我所说,128Hz 的采样率对于所有三个设备都很好。尝试同时读取所有三个设备显然会增加比预期慢的采样速度。

我还将同时从 4 个引脚(ADC 10 位)收集模拟数据。这段代码已经实现,我可以读取 1KHz 的模拟数据,采样率按预期工作,只是 I2C 设备运行缓慢!

我希望加速度计在尝试以 100Hz 采样时会很好,那时我可以以 3600Hz(I2C 的最大 800Hz)输出,但它真的很挣扎,我不知道还能尝试什么。

干杯!

4

1 回答 1

2

好的,这可能是很多事情:

  • 在您的情况下,最简单的解释是您用来触发轮询的计时器配置错误。我需要知道你是如何使用它的,它是否触发了一个中断,你设置了一个标志来触发加速度计轮询?您是否手动轮询计时器以触发加速度计轮询。无论如何,在发生这种情况时将输出引脚切换为高电平和低电平并用示波器查看它会给您提供有价值的信息。是否所有的投票周期都更长,或者只是其中一些花费的时间比预期的要长得多?

  • 我经常看到的是一个缓慢的 I2C 处理例程。您的 I2C 可能设置为 400KHz,这确实是读取和写入字节位的速度,但是字节之间的处理时间在很大程度上取决于您的代码复杂性。在您的情况下,由于您使用的是多字节读取模式,因此这个时间实际上不是在字节之间,而是在轮询周期之间。但奇怪的是这会是你的问题,它不是那么频繁的轮询,也不是大数据读取。

  • 在您的情况下,我会做的(拥有某种您似乎拥有的测量设备)是检查所有时间是否符合您的预期。不要假设任何事情,测量它并验证它是否在做你期望的事情。在这方面,我会从最简单的事情开始。时钟是否以 400kHz 运行?六个字节的读取是否在它们之间没有延迟?轮询之间是否存在预期的空闲间隙?I2C 总线是否在轮询之间卡住(SDA 和/或 SCL 长时间处于低电平)?除了带有加速度计的通信或活动之外,总线上是否有任何意外的通信或活动?这些是我要检查的一些事情,以了解可能出了什么问题。这里的黄金法则是不要推测,测量它!

  • 如果上述一切都完美且符合预期,那么只需较长时间的轮询之间以稳定的方式进行。我会开始检查软件的时间以了解每个例程中的时间,我看到许多软件开发人员对一些看似简单的操作可能需要多少时间感到惊讶。为此,请使用第一个要点中描述的输出引脚位切换。使用几个 IO 端口,因此您在示波器的每个通道上都有两个标记,并更改代码上切换这些位的位置,只需使用它来检查代码的任何慢速部分。如果你想要另一个黄金法则分而治之. 将标记设置在最高的抽象例程上,并在代码的慢速部分向下挖掘,直到找到问题所在。

试试这个,让我知道它是否有帮助。

干杯,祝你好运!

于 2013-04-13T00:45:01.647 回答