读取时不返回I2C的写入缓冲区 [英] Written Buffer to I2C Not Returned when Read

查看:62
本文介绍了读取时不返回I2C的写入缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在写入后从I2C总线上的存储位置读取一个值.在终端中运行它时,我得到奇怪的输出.

I am trying to read one value from a memory location on the I2C bus after writing to it. I am getting strange output when I run it in the terminal.

这是我的程序

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <inttypes.h>

    #include <errno.h>
    #include <string.h>

    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>

    #include <linux/i2c.h>
    #include <linux/i2c-dev.h>
    #include <sys/ioctl.h>

    #define I2C_ADAPTER "/dev/i2c-0"
    #define I2C_DEVICE  0x00


    int main (int argc, char *argv[])
    {
        int file;
        int addr = 0X00; /* XGPIOPS_DATA_LOW_OFFSET */

        if((file = open(I2C_ADAPTER, O_RDWR)) < 0) {
            printf("Failed to open the bus");
            return -1;
        }

        if(ioctl(file, I2C_SLAVE, addr) < 0) {
            printf("Unable to open device as slave %s", strerror(errno));
            return -1;
        }

        char buf[10];

        buf[0] = addr;
        buf[1] = 0x10;
        if(write(file, buf, 2) != 2) {
            printf("Failed to write to bus %s.\n\n", strerror(errno));
        }
        else {
            printf("Successful write\n");
            printf(buf);
            printf("\n\n");
        }

        if(read(file, buf, 2) != 2) {
            printf("Failed to read from the i2c bus. %s\n\n", strerror(errno));
        }
        else {
            printf("Successful read\n");
            printf(buf);
            printf("\n\n");
        }

        return 0;
    }

程序的输出如下所示

The output from the program looks like this

成功写入

成功阅读

在我的终端机上,这些块看起来更像是钻石内部的问号.我不确定ASCII对应什么.

On my terminal those blocks look more like question marks inside of diamonds. I am not sure what that corresponds to in ASCII.

为什么我不读回原来写的地址字节之后的第二个字节0x10?

Why am I not reading back that 0x10 which is the second byte after the address byte that I originally write?

根据第一组答案,下面是更新的代码:

Based on the first set of answers, here is the updated code:

#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

#include <errno.h>
#include <string.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

#define I2C_ADAPTER "/dev/i2c-0"
#define I2C_DEVICE  0x00


int main (int argc, char *argv[])
{
    int file;

    long addr, reg_addr;

    char *end;

    if(argc == 3) {
        addr = strtol(argv[1], &end, 16);
        printf("Value of addr is: %ld\n", addr);

        reg_addr = strtol(argv[2], &end, 16);
        printf("Value of reg_addr is: %ld\n", reg_addr);
    }
    else {
        printf("arg failed\n\n.");
        addr = 0x00;
    }


    if((file = open(I2C_ADAPTER, O_RDWR)) < 0) {
        printf("Failed to open the bus\n");
        return -1;
    }

    if(ioctl(file, I2C_SLAVE, addr) < 0) {
        printf("Unable to open device as slave \n%s\n", strerror(errno));
        return -1;
    }

    char buf[10];

    buf[0] = addr;
    buf[1] = reg_addr;
    buf[2] = 0x10;
    if(write(file, buf, 3) != 3) {
        printf("Failed to write to bus %s.\n\n", strerror(errno));
    }
    else {
        printf("Successful write\n");
        printf(buf);
        printf("\n\n");
    }

    if(read(file, buf, 3) != 3) {
        printf("Failed to read from the i2c bus.\n %s\n\n", strerror(errno));
    }
    else {
        printf("Successful read\n");
        printf("Buf = [%02X,%02X,%02X]\n", buf[0], buf[1], buf[2]);
        printf("\n\n");
    }

    return 0;
}

这时,每当我使用0x00作为地址时,无论argv [2]是什么,我都会得到FF,FF,FF作为输出.这是设备树文件的适用部分.请注意,这是仿真的,因此我无法探测物理设备.

At this point, whenever I use 0x00 as the addr, I get FF, FF, FF as the output, no matter what argv[2] is. Here is the applicable part of the device tree file. Note that this is being emulated, so I cannot probe the physical device.

&i2c0 {
    status = "okay";
    clock-frequency = <400000>;
    pinctrl-names = "default";

    i2cswitch@74 {
        compatible = "nxp,pca9548";
        #address-cells = <1>;
        #size-cells = <0>;
        reg = <0x74>;

        i2c@0 {
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <0>;
            si570: clock-generator@5d {
                #clock-cells = <0>;
                compatible = "silabs,si570";
                temperature-stability = <50>;
                reg = <0x5d>;
                factory-fout = <156250000>;
                clock-frequency = <148500000>;
            };
        };

        i2c@2 {
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <2>;
            eeprom@54 {
                compatible = "at,24c08";
                reg = <0x54>;
            };
        };

        i2c@3 {
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <3>;
            gpio@21 {
                compatible = "ti,tca6416";
                reg = <0x21>;
                gpio-controller;
                #gpio-cells = <2>;
            };
        };

        i2c@4 {
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <4>;
            rtc@51 {
                compatible = "nxp,pcf8563";
                reg = <0x51>;
            };
        };

        i2c@7 {
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <7>;
            hwmon@52 {
                compatible = "ti,ucd9248";
                reg = <52>;
            };
            hwmon@53 {
                compatible = "ti,ucd9248";
                reg = <53>;
            };
            hwmon@54 {
                compatible = "ti,ucd9248";
                reg = <54>;
            };
        };
    };
};

以下是一些示例测试

尝试测试SiLabs时钟发生器

Try to test the SiLabs clock generator

root @ plnx_arm:〜#/usr/bin/i2c-test-mem-location 0x54 0x00

root@plnx_arm:~# /usr/bin/i2c-test-mem-location 0x54 0x00

addr的值是:84

Value of addr is: 84

reg_addr的值是:0

Value of reg_addr is: 0

无法将设备作为从设备打开

Unable to open device as slave

设备或资源繁忙

尝试测试eeprom设备

Try to test the eeprom device

root @ plnx_arm:〜#/usr/bin/i2c-test-mem-location 0x5d 0x00

root@plnx_arm:~# /usr/bin/i2c-test-mem-location 0x5d 0x00

addr的值是:93

Value of addr is: 93

reg_addr的值是:0

Value of reg_addr is: 0

无法将设备作为从设备打开

Unable to open device as slave

设备或资源繁忙

这是我的程序第三次尝试.在记下答案中的注释后,我写下了

This is my program on the third try. After taking to mind the notes made in the answers, I have this written

#include <stdio.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

#include <errno.h>
#include <string.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

#define I2C_ADAPTER "/dev/i2c-0"
#define DEVICE_ADDRESS 0x54


int main (int argc, char *argv[])
{
    int file;

    uint8_t reg, value;

    char *end;

    printf("The device address on the bus: %d", DEVICE_ADDRESS);

    if(argc == 3) {
        reg = strtol(argv[1], &end, 16);

        printf("Value of register address: %d\n", reg);

        value = strtol(argv[2], &end, 16);
        printf("value to write is: %d\n", value);
    }
    else {
        printf("arg failed\n\n.");
    }


    if((file = open(I2C_ADAPTER, O_RDWR)) < 0) {
        printf("Failed to open the bus\n");
        return -1;
    }

    if(ioctl(file, I2C_SLAVE, DEVICE_ADDRESS) < 0) {
        printf("Unable to open device as slave \n%s\n", strerror(errno));
        return -1;
    }

    char buf[10];

    buf[0] = reg;
    buf[1] = value;

    if(write(file, buf, 2) != 2) {
        printf("Failed to write to bus %s.\n\n", strerror(errno));
    }
    else {
        printf("Successful write\n");
        printf(buf);
        printf("\n\n");
    }

    if(read(file, buf, 2) != 2) {
        printf("Failed to read from the i2c bus.\n %s\n\n", strerror(errno));
    }
    else {
        printf("Successful read\n");
        printf("Buf = [%02X,%02X,%02X]\n", buf[0], buf[1], buf[2]);
        printf("\n\n");
    }

    return 0;
}

不幸的是,即使如此,我仍然遇到相同的错误.

Unfortunately, even still, I am getting the same error.

root @ plnx_arm:〜#/usr/bin/i2c-test-mem-location 0x00 0x10

root@plnx_arm:~# /usr/bin/i2c-test-mem-location 0x00 0x10

总线上的设备地址:84寄存器地址的值:0

The device address on the bus: 84Value of register address: 0

要写入的值是:16

无法将设备作为从设备打开

Unable to open device as slave

设备或资源繁忙

root @ plnx_arm:〜#/usr/bin/i2c-test-mem-location 0x30 0x10

root@plnx_arm:~# /usr/bin/i2c-test-mem-location 0x30 0x10

总线上的设备地址:84寄存器地址的值:48

The device address on the bus: 84Value of register address: 48

要写入的值是:16

无法将设备作为从设备打开

Unable to open device as slave

设备或资源繁忙

推荐答案

基于设备树,需要提供给IOCtl的地址是i2cswitch多路复用器地址.该地址为0x74,可以在设备树中看到.打开i2c-0设备文件对应于设备树中i2c0条目,该条目是多路复用器的父级.写入EEPROM时,缓冲区中的第一个字节应为设备地址,如@AndrewCottrell所述.该地址是0x54.第二个字节应该是您要写入的数据

Based on the device tree, the address that needs to be fed to IOCtl is the i2cswitch mux address. This address is 0x74, which can be seen in the device tree. Opening the i2c-0 device file corresponds to the i2c0 entry in the device tree which is parent to the mux. When writing to EEPROM, the first byte in the buffer should be the device address, as mentioned by @AndrewCottrell. This address is 0x54. The second byte should be the data you want to write

#define I2C_ADAPTER                 "/dev/i2c-0"
#define I2C_SWITHC_MUX_ADDRESS      0x74
#define DEVICE_ADDRESS              0x54

...

file = open(I2C_ADAPTER, O_RDWR); /* Check for error */
ioctl(file, I2C_SLAVE_FORCE, I2C_SWITHC_MUX_ADDRESS); /* Check for error */

uint8_t reg, value;

reg = DEVICE_ADDRESS;

buf[0] = reg;
buf[1] = value;

write(file, buf, 2); /* Check for error */
read(file, buf, 1); /* Check for error */
/* buf[0] should be value*/

这篇关于读取时不返回I2C的写入缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆