加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

读取时不会返回I2C写入的缓冲区

发布时间:2020-12-16 10:08:16 所属栏目:百科 来源:网络整理
导读:我写入后尝试从I2C总线上的存储单元读取一个值.当我在终端中运行它时,我得到奇怪的输出. 这是我的计划 #include stdio.h #include stdlib.h #include stdint.h #include inttypes.h #include errno.h #include string.h #include sys/stat.h #include fcntl.
我写入后尝试从I2C总线上的存储单元读取一个值.当我在终端中运行它时,我得到奇怪的输出.

这是我的计划

#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.nn",strerror(errno));
        }
        else {
            printf("Successful writen");
            printf(buf);
            printf("nn");
        }

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

        return 0;
    }

The output from the program looks like this

Successful write

Successful read ??

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

为什么我不读回0x10,这是我最初写入的地址字节后的第二个字节?

根据第一组答案,这里是更新的代码:

#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: %ldn",addr);

        reg_addr = strtol(argv[2],16);
        printf("Value of reg_addr is: %ldn",reg_addr);
    }
    else {
        printf("arg failednn.");
        addr = 0x00;
    }


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

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

    char buf[10];

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

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

    return 0;
}

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

&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时钟发生器

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

Value of addr is: 84

Value of reg_addr is: 0

Unable to open device as slave

Device or resource busy

尝试测试eeprom设备

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

Value of addr is: 93

Value of reg_addr is: 0

Unable to open device as slave

Device or resource busy

这是我的第三次尝试的程序.在记下答案中的笔记之后,我写了这篇文章

#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],16);

        printf("Value of register address: %dn",reg);

        value = strtol(argv[2],16);
        printf("value to write is: %dn",value);
    }
    else {
        printf("arg failednn.");
    }


    if((file = open(I2C_ADAPTER,DEVICE_ADDRESS) < 0) {
        printf("Unable to open device as slave n%sn",strerror(errno));
        return -1;
    }

    char buf[10];

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

    if(write(file,2) != 2) {
        printf("Failed to write to bus %s.nn",2) != 2) {
        printf("Failed to read from the i2c bus.n %snn",buf[2]);
        printf("nn");
    }

    return 0;
}

不幸的是,即便如此,我也遇到了同样的错误.

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

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

value to write is: 16

Unable to open device as slave

Device or resource busy

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

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

value to write is: 16

Unable to open device as slave

Device or resource busy

解决方法

编辑2:我认为你可能没有正确设置你的I2C设备地址.您拥有的I2C_ADAPTER(“/ dev / i2c-0”)表示设备所在的I2C总线.您甚至没有使用I2C_DEVICE宏,但这应该是您应该传递给ioctl调用的内容(例如ioctl(文件,I2C_DEVICE);)它应该是您要访问的设备的I2C地址(例如0x5D)对于时钟发生器而不是0x00.

我也认为你的读/写不正确.一旦你通过open()和ioctl()指定了总线和设备,你就不用再担心了.您只需要担心要访问的寄存器(如果您的I2C设备使用寄存器)和实际数据.

要写入I2C设备,假设它使用一个字节的寄存器,写入两个字节的缓冲区:第一个是寄存器,第二个是要写入的值:

bool i2cdev_byte_write(int file,uint8_t reg,uint8_t val)
{
    uint8_t bytes[2];

    bytes[0] = reg;
    bytes[1] = val;

    /* Write the register followed by the value */
    if (write(file,bytes,2) != 2)
        return false;

    return true;
}

要从I2C设备读取,写入一个字节的缓冲区(寄存器地址),然后读取一个或多个字节的缓冲区(该寄存器和后续寄存器的值):

bool i2cdev_bytes_read(int file,unsigned int count,uint8_t *out_buf)
{
    if (!out_buf)
        return false;

    /* Write the register */
    if (write(file,&reg,1) != 1)
    {
        printf("Failed to write register valuen");
        return false;
    }

    /* Read the specified number of bytes */
    if (read(file,out_buf,count) != count)
    {
        printf("Failed to read from the i2c busn");
        return false;
    }

    return true;
}

再次注意,上述所有注释都取决于它是使用单字节寄存器地址的I2C器件,并且它支持在一次读取多个字节时自动递增寄存器地址.您需要检查I2C设备的数据表,以确切地确定它是如何被访问的.

编辑:这是一个printf()新手失败.你不能只尝试printf一个字节数组.这不是printf()的工作原理.

试试这个:

printf("Buf = [%02X,buf[1]);

另外,正如我在原始响应中所写的那样,在读取寄存器内容之前,您可能需要再次将寄存器地址写回.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读