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

标签 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);

工作中

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.如果计算为:

temperature = raw * AMB_LSB;

所以根本没有使用filtered,输出是这样的:

工作中

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 编写了一个脚本,它的返回值非常一致。没有崩溃或意外的值。

为什么会发生这种情况?

最佳答案

听起来像是硬件问题。您的许多值都是 0x7FFFFFFF,例如SDA线由上拉电阻控制。如果 SDA 线上的噪声导致虚假的 I2C 停止条件,就会发生这种情况 - 设备将立即将其输出置于三态,并且在传输的其余部分中除了高位之外什么也得不到。

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

关于c++ - C i2c芯片读取MCP9800突然开始失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13298793/

相关文章:

c++ - BlueZ5 : Event when inbound pairing is complete

c++ - 包含时间数据的几乎排序列表的有效排序算法?

c - 段错误 : don't know where to start

计算执行 C 程序代码所需的时间?

Linux 内核 Procfs 多次读/写

python - Python 中是否有相当于 Unix 中 vfork 的工具?

c++ - 查询位标志的状态?

c++ - 根据参数调用不同函数的宏

c - 求 C 中两个值之间的步长

regex - Linux shell 提取匹配模式之间的子字符串