使用I2C dev驱动程序

时间:2018-05-31 07:18:52

标签: linux-kernel linux-device-driver i2c

我想使用I2C-dev模块在I2C总线上配置传感器。 所需的I2C总线已启动并运行,但我似乎无法从传感器接收任何数据。有谁可以帮我调试下面的代码。所有传感器寄存器都是8位。

  int main()
{
    int devFile=0;
    const char *devFileName="/dev/i2c-1";
    char writeBuf[2];
    uint16_t readBuf[2];
    uint16_t tempReading = 0;

    /* Initialize I2C interface */  
    devFile = hdc2010_i2c_init(devFileName, HDC2010_ADDR);

    /* Configuring the sensor and trigerring measurement */
    writeBuf[0] = HDC2010_CONFIG; 
    writeBuf[1] = 0x57;
    hdc2010_i2c_write(devFile, writeBuf, 2);

    writeBuf[0] = HDC2010_INTERRUPT_CONFIG; 
    writeBuf[1] = 0x78;
    hdc2010_i2c_write(devFile, writeBuf, 2);

    writeBuf[0] = HDC2010_MEASUREMENT_CONFIG; 
    writeBuf[1] = 0x03;
    hdc2010_i2c_write(devFile, writeBuf, 2);

    /* Reading temperature data from the registers */
    writeBuf[0] = HDC2010_TEMP_LOW; 
    hdc2010_i2c_write(devFile, writeBuf, 1);
    readBuf[0] = hdc2010_i2c_read(devFile, 1);

    writeBuf[0] = HDC2010_TEMP_HIGH; 
    hdc2010_i2c_write(devFile, writeBuf, 1);
    readBuf[1] = hdc2010_i2c_read(devFile, 1);

    /* 
     * Converting the temperature to readable format 
     * Formula Source : HDC2010 Datasheet
     */
    tempReading = ((readBuf[1] << 8) | (readBuf[0]));
    tempReading = ((tempReading/65536)*165)-40;

    printf("\nTemp: %d\n",tempReading);
}

    int hdc2010_i2c_init(const char *devFileName, int slaveAddr)
{
    int devFile;

    /* Opening I2C device file */
    devFile=open(devFileName,O_RDWR);

    if (devFile < 0)
    {
        printf("\nError opening the %s device file.\n",devFileName);
        exit (1);
    }

    /* Selecting HDC2010 by its slave address */
    if (ioctl(devFile,I2C_SLAVE,slaveAddr) < 0)
    {
        printf("\nFailed to select HDC2010(addr=%u)\n",HDC2010_ADDR);
        exit (1);
    }

    return devFile;
}

    void hdc2010_i2c_write(int devFile, char *buf, int numBytes)
{
    write(devFile, buf, numBytes);
}

    uint16_t hdc2010_i2c_read(int devFile, int numBytes)
{
    uint16_t readBuf;

    read(devFile, &readBuf, 1);

    return readBuf;
}

我是否需要使用SMBus命令或读/写就足够了? 是否有任何测试应用程序,例如SPIdev?

1 个答案:

答案 0 :(得分:0)

我不知道你芯片的接口。有很多种可能的方法可以使用I2C。但是有一种非常常见的方法可以访问具有8位寄存器的器件,因此我们假设这就是您所需要的。

要读取寄存器,您需要生成(简化的)原语I2C序列:

Start I2CAddr+Write RegAddr Start I2CAddr+Read [DATA] Stop

但你正在做的是:

Start I2CAddr+Write RegAddr Stop
Start I2CAddr+Read [DATA] Stop

基本上,您需要将读取寄存器操作作为单个事务,最后一次停止,并且在写入模式和读取模式之间重复启动。但是你发送的是两笔交易。

您不应该使用i2c-dev的read() / write()接口。该接口非常简单,不适合大多数I2C事务。而是使用ioctl()界面和I2C_RDWR。这允许生成适当的事务。

由于某些形式的交易非常普遍,包括您最想要的交易,因此有一个库已经对它们进行了编码。使用i2c-tools中的库中的i2c_smbus_read_byte_data()i2c_smbus_write_byte_data()

对于测试程序,i2cgeti2cset是上述i2c工具的一部分,可以做你想要的。