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

2024-03-08

我试图在写入后从 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.\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;
    }

程序的输出如下所示

写入成功

读取成功��

在我的终端上,这些块看起来更像是钻石内的问号。我不确定 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: %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 作为输出。这是设备树文件的适用部分。请注意,这是模拟的,因此我无法探测物理设备。

&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-位置 0x54 0x00

地址的值为:84

reg_addr 的值为:0

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

设备或资源繁忙

尝试测试eeprom设备

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

地址的值为:93

reg_addr 的值为:0

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

设备或资源繁忙

这是我第三次尝试的程序。考虑到答案中所做的笔记后,我写下了这个

#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;
}

不幸的是,即使如此,我还是遇到了同样的错误。

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

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

要写入的值为:16

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

设备或资源繁忙

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

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

要写入的值为:16

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

设备或资源繁忙


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

我还认为你的读/写不正确。一旦您通过以下方式指定了总线和设备open() and 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, uint8_t reg, 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 value\n");
        return false;
    }

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

    return true;
}

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

编辑:这是一个printf()新手失败。你不能只是尝试printf字节数组。不是这样的printf() works.

尝试这个:

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读取时不返回写入 I2C 的缓冲区 的相关文章

  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 为什么 VB.NET 和 C# 中针对值检查 null 存在差异?

    In VB NET http en wikipedia org wiki Visual Basic NET有时候是这样的 Dim x As System Nullable Of Decimal Nothing Dim y As System
  • 如何将十六进制字符串转换为十六进制数字[重复]

    这个问题在这里已经有答案了 可能的重复 如何将十六进制字符串转换为有符号整数 https stackoverflow com questions 3705429 how do i convert hex string into signed
  • 获取 std::variant 当前持有的 typeid(如 boost::variant type())

    我已经从 boost variant 迁移到 std variant 但遇到了障碍 我在 boost type 中使用了一个很好的函数 它可以让你获取当前持有的 typeid 看https www boost org doc libs 1
  • C# 中四舍五入到偶数

    我没有看到 Math Round 的预期结果 return Math Round 99 96535789 2 MidpointRounding ToEven returning 99 97 据我了解 MidpointRounding ToE
  • 找到的程序集的清单定义与程序集引用不匹配

    我试图在 C Windows 窗体应用程序 Visual Studio 2005 中运行一些单元测试 但出现以下错误 System IO FileLoadException 无法加载文件或程序集 实用程序 版本 1 2 0 200 文化 中
  • 方法“xxx”不能是事件的方法,因为该类派生的类已经定义了该方法

    我有一个代码 public class Layout UserControl protected void DisplayX DisplayClicked object sender DisplayEventArgs e CurrentDi
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • 在 Ubuntu 上纯粹通过 bash 脚本安装 mysql 5.7

    我想要一个无需任何手动输入即可安装 MySQL 5 7 实例的 bash 脚本 我正在关注数字海洋教程 https www digitalocean com community tutorials how to install mysql
  • 在 MATLAB 中创建共享库

    一位研究人员在 MATLAB 中创建了一个小型仿真 我们希望其他人也能使用它 我的计划是进行模拟 清理一些东西并将其变成一组函数 然后我打算将其编译成C库并使用SWIG https en wikipedia org wiki SWIG创建一
  • 操纵 setter 以避免 null

    通常我们有 public string code get set 如果最终有人将代码设置为 null 我需要避免空引用异常 我尝试这个想法 有什么帮助吗 public string code get set if code null cod
  • 无法加载文件或程序集“EntityFramework,版本=6.0.0.0”

    我究竟做错了什么 我该如何解决这个问题 我有一个包含多个项目的解决方案 它是一个 MVC NET 4 5 Web 应用程序 在调试模式下启动后调用其中一个项目时 出现此错误 导致此错误的项目具有以下参考 两个都是版本6 0 0 0 应用程序
  • 您可以在一个 Windows Azure 实例上部署多个 Web 应用程序吗?

    是否可以在一个 windows azure 小型计算实例中运行一堆 Web 应用程序 我正在考虑使用 Azure 作为放置一堆处于开发和非生产状态的项目 Web 应用程序 的地方 有些实际上已经被封存了 但我想在某个地方有一个活跃的实例 我
  • 防止GDB中的PLT(过程链接表)断点

    在最新版本的 GDB 中 在库函数调用上设置断点会导致多个实际断点 调用过程链接表 PLT 实际的函数调用 这意味着当调用库函数时 我们每次都会经历两次中断 在以前的 GDB 版本中 只会创建 2 因此您只能得到一次中断 那么问题来了 是否
  • 格式化货币

    在下面的示例中 逗号是小数点分隔符 我有这个 125456 89 我想要这个 125 456 89 其他示例 23456789 89 gt 23 456 789 89 Thanks 看看这个例子 double value 12345 678
  • 如何用 C 语言练习 Unix 编程?

    经过五年的专业 Java 以及较小程度上的 Python 编程并慢慢感觉到我的计算机科学教育逐渐消失 我决定要拓宽我的视野 对世界的一般用处 并做一些 对我来说 感觉更重要的事情就像我真的对机器有影响一样 我选择学习 C 和 Unix 编程
  • TPL 数据流块下游如何获取源生成的数据?

    我正在使用 TPL Dataflow 处理图像 我收到处理请求 从流中读取图像 应用多次转换 然后将生成的图像写入另一个流 Request gt Stream gt Image gt Image gt Stream 为此 我使用块 Buff
  • ASP.NET Core Razor Page 多路径路由

    我正在使用 ASP NET Core 2 0 Razor Pages 不是 MVC 构建系统 但在为页面添加多个路由时遇到问题 例如 所有页面都应该能够通过 abc com language 访问segment shop mypage 或
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • 启动画面后主窗口出现在其他窗口后面

    我有一个带有启动屏幕的 Windows 窗体应用程序 当我运行该应用程序时 启动屏幕显示正常 消失并加载应用程序的主窗体 但是 当我加载主窗体时 它出现在包含该应用程序的 Windows 资源管理器目录下 这是运行启动画面然后运行主窗体的代

随机推荐

  • 仅加载适用于 ipad 的 css 文件

    我正在尝试加载仅适用于 ipad 的 css 文件 我试过这个 它适用于 iPad 但如果我在桌面上将分辨率降低到 1024 x 768 并在 Firefox 中查看该网站 ipad 样式表也会加载 所以我尝试 但仍然是同样的问题 我如
  • Express JS 路由中使用 formData 获取 POST 为空

    我有一个表单 它使用 fetch 到 AJAX 并在 NodeJS 上有一个路由 当 AJAX POST 命中路由时 req body 显示一个空对象 这是代码 在 app js 中 app use bodyParser json app
  • Web 服务一次只允许我获取 1000 行,但总数超过 30000

    我正在使用 Netsuite 提供的一些 Web 服务https system netsuite com help helpcenter en US Output Help SuiteFlex WebServices STP searchM
  • AWS Lambda:任务超时

    我的学校项目要求我们编写在 AWS Lambda 中运行的 Java 代码 它应该获取特定 URL 的源代码 然后将其上传到 S3 存储桶 Java 代码应在 AWS Lambda 上运行 我获取了 Java 中 String 变量的源代码
  • ElementTree的iterparse() XML解析错误

    我需要解析一个编码为 ISO 8859 1 的 1 2GB XML 文件 在阅读了 NET 上的几篇文章后 似乎 Python 的 ElementTree 的 iterparse 比 SAX 解析更受青睐 我写了一段非常短的代码只是为了测试
  • Selenium chrome 浏览器中的 Feign 焦点

    我正在使用 Selenium 从网站上抓取数据 该网站需要窗口焦点才能显示我需要的某些元素 我希望能够在后台运行我的程序 而不必在运行时聚焦窗口 有没有什么办法可以让网站认为它的重点是 我正在使用硒铬驱动程序 Edit 这是我构建的一个快速
  • Android是否阉割了ARM的Jazelle技术?

    我认为 Android 中的 Java 字节码 混蛋 的理由是性能 我怀疑还有另一个原因 但是 通过更改字节码 他们难道没有让 Jazelle 等硬件加速技术变得毫无意义 从而实际上降低了 Mobile Java 平台的可用性能吗 目标平台
  • 通过蓝牙传输文件,如 Android 蓝牙聊天示例

    如何使用 Android 蓝牙聊天示例并将其更改为文件传输 我想通过蓝牙将本地 SQLite 数据库传输到另一台 Android 设备 我更改了示例代码 http developer android com resources sample
  • 在多个文件之间共享枚举的正确方法是什么?

    我想在当前 C 项目的客户端和服务器部分使用相同的枚举 但不确定执行此操作的正确方法 我可以轻松地将枚举写入它自己的文件中 并将其包含在两个文件中 但这感觉像是不好的做法 将其放入命名空间然后将其包含在两者中是正确的方法吗 我知道这有点主观
  • 如何在 Django 模板上下文中获取“调试”变量?

    根据这个SO帖子 如何检查 django 模板中的 TEMPLATE DEBUG 标志 https stackoverflow com questions 1271631 how to check the template debug fl
  • 将 aSmack 0.8.3 用于 XMPP 聊天应用程序时出现 NoSuchAlgorithmException

    我已经包含了 logcat 输出 请帮我解决这个问题 08 09 11 06 32 762 警告 NetworkManagementSocketTagger 883 setKernelCountSet 10012 0 失败 错误号 2 08
  • 检测多个if语句中哪个条件为假

    我尝试缩短我的代码 因此我来缩短以下类型的 if 语句 a b c d needed to run if empty a echo a is empty elseif empty b echo b is empty elseif empty
  • 在 Prolog 中解答爱因斯坦之谜

    我正在尝试解决爱因斯坦之谜 https www wikiwand com en Zebra Puzzle在序言中 我在编写程序时遇到了困难 基本方法是添加所有约束并让 Prolog 找出唯一可能的解决方案 问题是 Prolog 找到了 0
  • html5视频预加载

    是否可以预加载 html 视频 注意 该标签是稍后动态创建的 目前 我可以通过创建一个隐藏的 div 并将所有图像放入其中来对图像执行此操作 然后当我稍后创建需求时 图像不需要重新加载 当使用视频标签完成此操作时 浏览器仍会在创建元素时从头
  • 从类库 .NET Core 3 中的非控制器类访问 ILogger

    我们正在将 NET Framework 应用程序 MVC 迁移到 NET Core 3 应用程序 MVC 我们有一个场景如下 流程1 由Controller实例化的类 流程 2 ClassX 由 ClassY 实例化 由 Class 实例化
  • Matlab - 缩放图像的颜色条

    我怎样才能扩展colorbar假彩色图像的轴 我读了这篇文章 并复制了代码 但似乎无法正常工作 MATLAB Colorbar 相同的颜色 缩放值 https stackoverflow com questions 45285114 mat
  • 使用 Google Cloud Storage python 客户端进行批量请求

    我找不到任何有关如何使用 python 谷歌云存储的批处理功能的示例 我看到它存在here https github com GoogleCloudPlatform google cloud python blob master stora
  • Indexeddb:onsuccess 和 oncomplete 之间的区别?

    当 IndexedDB 事务完成或成功时 我使用两个不同的事件来响应回调 比方说 db IDBDatabase 对象 tr IDBTransaction 对象 os IDBObjectStore 对象 tr db transaction o
  • 防止以编程方式单击按钮

    我有以下按钮
  • 读取时不返回写入 I2C 的缓冲区

    我试图在写入后从 I2C 总线上的内存位置读取一个值 当我在终端中运行它时 我得到奇怪的输出 这是我的程序 include