C i2c芯片读取MCP9800突然开始失败

时间:2012-11-08 22:16:19

标签: c++ c linux filter i2c

我有一些代码:

#define AMB_LSB 0.0625

void Ambient::read()
{
    uint32_t raw; 
    float filtered;

    uint8_t bytes = 2;
    uint8_t buf[bytes];

    if(i2c_smbus_read_i2c_block_data(i2c_bus_address, A_TEMP_REG, bytes, buf) < 0)
        printf("AMB Block Read Failed\n");

    uint32_t va = buf[0];
    uint32_t vb = buf[1];

    uint32_t result = ((va<<8)+vb);

    // 12-bit code
    raw = result >> 4; 

    filtered = filter.execfilter( raw );
    temperature = filtered * AMB_LSB;  << CALCULATION 

    printf("AMB buffers %d %d -> result %d -> raw %d -> filtered %d -> amb C %f\n",va, vb, result, raw, filtered, temperature);
}

是通过i2c从MCP9800读取信息的代码。很抱歉包含它,但也许它与它有关。

该功能可以很好地工作十几个周期,直到它突然开始有不正确的值。但有一些奇怪的差异。

1。如果计算如下

temperature = filtered * AMB_LSB;

我得到了这个输出:

temperature = ((float) filtered * (float) AMB_LSB);

WORKING

AMB buffers 28 240 -> result 7408 -> raw 463 -> filtered 463 -> amb C 28.937500 
AMB buffers 28 240 -> result 7408 -> raw 463 -> filtered 463 -> amb C 28.937500 
AMB buffers 28 240 -> result 7408 -> raw 463 -> filtered 1024 -> amb C 64.000000 

失败

AMB buffers 29 0 -> result 7424 -> raw 464 -> filtered -**2147483648** -> amb C -134217728.000000 
AMB buffers 29 0 -> result 7424 -> raw 464 -> filtered **2147483647** -> amb C 134217728.000000
AMB buffers 29 0 -> result 7424 -> raw 464 -> filtered -**2147483648** -> amb C -134217728.000000 

因此,一旦它开始失败,我可以看到过滤值的输出不正确。

2. 如果CALCULATION为:

temperature = raw * AMB_LSB;

因此根本不使用过滤,输出为:

WORKING

AMB buffers 29 48 -> result 7472 -> raw 467 -> filtered 0 -> amb C 29.187500 
AMB buffers 29 48 -> result 7472 -> raw 467 -> filtered 2147483647 -> amb C 29.187500
AMB buffers 29 64 -> result 7488 -> raw 468 -> filtered 468 -> amb C 29.250000 

失败

AMB buffers **255 130** -> result **65410** -> raw **4088** -> filtered 2147483647 -> amb C 255.500000 
AMB buffers **255 130** -> result **65410** -> raw **4088** -> filtered -2147483648 -> amb C 255.500000 
AMB buffers **255 130** -> result **65410** -> raw **4088** -> filtered 2147483647 -> amb C 255.500000 

请参阅输出的星号数字不正确。出于某种原因,当您不使用过滤值时,其他数字也开始变得不正确!一直回到我拉下i2c芯片的字节。

首先,我发现可能过滤后无法正常工作。但要删除它似乎也会使原始的未过滤值也不正确。所有execFilter()都在做一些平均以防止大的随机变化。

另外,我还通过使用i2cget的CLI编写了一个脚本,它的返回值非常一致。没有崩溃或意外的值。

为什么会这样?

3 个答案:

答案 0 :(得分:2)

听起来像硬件问题。您的许多值都是0x7FFFFFFF,例如SDA线由上拉电阻控制。如果SDA线上的噪声导致了一个寄生的I2C停止条件,就会发生这种情况 - 器件会立即将其输出置为三态,并且除了传输的其余部分之外,你只能得到高位。

SCL和SDA线上建议使用RC低通滤波器,以减慢边沿并阻止高频噪声,有助于防止此类通信错误。

答案 1 :(得分:0)

检查来自i2c_smbus_read_i2c_block_data()来电的返回值,而不仅仅是否定为负值。

我敢打赌,当你收到失败的转账时,它会返回0或1。请记住,实际功能取决于适配器;如果它没有返回错误,我永远不会假设它完全成功,因为它被记录为返回字节数。

答案 2 :(得分:0)

它最终导致我的应用程序中另一个类的内存损坏。

HERE