当前位置: 首页 > news >正文

在 Linux 下使用 I2C(Inter-Integrated Circuit)进行用户态编程 — 教程与实战

概述

I2C(Inter-Integrated Circuit)是一种常见的串行总线协议,广泛用于传感器、EEPROM、ADC/DAC 等外设。Linux 提供了用户态访问 I2C 的接口(/dev/i2c-X)。本教程介绍关键结构体、系统调用、示例代码及调试技巧,便于开发者快速上手并排查常见问题。

基本概念与接口

  • 设备节点:Linux 下的 I2C 总线设备通常以 /dev/i2c-X 命名(X 为总线编号)。
  • 访问方式:通过 open / read / write / ioctl 等系统调用在用户态与从设备交互。
  • 主从模型:通常 Linux 作为主控制器(master),从设备(slave)由 7 位或 10 位地址标识。

关键结构体与标志位

  • struct i2c_msg(描述单次 I2C 事务):
struct i2c_msg {__u16 addr;    // 从设备地址__u16 flags;   // 操作标志__u16 len;     // 数据长度__u8 *buf;     // 数据缓冲区指针
};

常见 flags:

  • I2C_M_RD:表示读操作(否则为写操作)。
  • I2C_M_TEN:使用 10 位地址。
  • I2C_M_STOP:在消息结束生成 STOP(取决于驱动/控制器)。

用户态 I2C 编程流程(打开、设置地址、读写)

步骤概览:

  1. 打开设备节点:open("/dev/i2c-X", O_RDWR)
  2. 设置目标从设备地址:ioctl(file, I2C_SLAVE, addr)
  3. 读写数据:write() / read() 或组合多个 i2c_msg 使用 I2C_RDWR

示例:打开设备并设置地址(包含基本错误处理)

int file = open("/dev/i2c-1", O_RDWR);
if (file < 0) {perror("Failed to open the i2c bus");// 处理打开失败(检查驱动、权限、设备节点)
}
int addr = 0x50;
if (ioctl(file, I2C_SLAVE, addr) < 0) {perror("Failed to acquire bus access and/or talk to slave");// 可能原因:设备不存在、驱动不支持该 ioctl 或权限问题
}

简单读写示例

写入单字节:

unsigned char out = 0xA0;
if (write(file, &out, 1) != 1) {perror("Failed to write to the i2c bus");
}

读取单字节:

unsigned char in;
if (read(file, &in, 1) != 1) {perror("Failed to read from the i2c bus");
} else {printf("Data read: 0x%02x\n", in);
}

使用 I2C_RDWR 进行复杂读写(示例与说明)

场景:先写寄存器地址,再读寄存器数据(常用于寄存器映射设备)。

写入多个字节(寄存器地址 + 数据):

unsigned char outbuf[3] = { 0x10, 0x01, 0x02 }; // reg=0x10, data=0x01,0x02
struct i2c_msg messages[1];
messages[0].addr  = addr;
messages[0].flags = 0;  // 写
messages[0].len   = 3;
messages[0].buf   = outbuf;
struct i2c_rdwr_ioctl_data ioctl_data = { messages, 1 };
if (ioctl(file, I2C_RDWR, &ioctl_data) < 0) {perror("Failed to write to the i2c bus");
}

读取寄存器(先写寄存器地址,随后读数据):

unsigned char reg = 0x10;
unsigned char inbuf[1];
struct i2c_msg messages[2];
messages[0].addr  = addr;
messages[0].flags = 0;           // 写寄存器地址
messages[0].len   = 1;
messages[0].buf   = &reg;
messages[1].addr  = addr;
messages[1].flags = I2C_M_RD;    // 读数据
messages[1].len   = 1;
messages[1].buf   = inbuf;
struct i2c_rdwr_ioctl_data ioctl_data2 = { messages, 2 };
if (ioctl(file, I2C_RDWR, &ioctl_data2) < 0) {perror("Failed to read from the i2c bus");
} else {printf("Register 0x10 read: 0x%02x\n", inbuf[0]);
}

完整示例程序(精简版,带错误提示)

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <unistd.h>int main() {int file;int addr = 0x50;file = open("/dev/i2c-1", O_RDWR);if (file < 0) { perror("open"); return 1; }if (ioctl(file, I2C_SLAVE, addr) < 0) { perror("ioctl I2C_SLAVE"); close(file); return 1; }// ...读写示例(参考上文)...close(file);return 0;
}

i2c-tools — 常用命令与示例

  • i2cdetect:扫描 I2C 总线(注意:可能会影响设备)
    i2cdetect -y 1
    
  • i2cget:读取寄存器
    i2cget -y 1 0x50 0x00
    
  • i2cset:写入寄存器
    i2cset -y 1 0x50 0x00 0xFF
    
  • i2cdump:以十六进制显示所有寄存器
    i2cdump -y 1 0x50
    

常见问题与排查建议

  • 权限问题/dev/i2c-X 通常需要 root 权限或将用户加入 i2c 组。
  • 设备不存在:确认内核驱动已加载并且硬件连线正确(SDA、SCL、上拉电阻)。
  • 总线冲突:使用 i2cdetect 时要注意对总线的潜在影响;在生产环境避免盲扫。
  • 超时与 NACK:设备地址错误或设备忙会导致 NACK,检查设备数据手册并尝试复位/重试。

扩展阅读与参考

  • linux/i2c.hlinux/i2c-dev.h 源码注释
  • i2c-tools 官方仓库(包含 i2cdetect / i2cget / i2cset 等实现)
  • 设备数据手册(寄存器与时序要求)
http://www.dtcms.com/a/519814.html

相关文章:

  • 替代HT1621B液晶驱动显示模块芯片程序演示
  • C++和OpenGL实现3D游戏编程【连载26】——添加TransformComponent组件(设置子物体的位移、旋转、缩放)
  • 常规条形光源在工业视觉检测上的应用
  • Zotero插件安装
  • Llama Factory、Unsloth与Hugging Face三大微调平台深度对比分析
  • 电脑卡在 “正在准备 Windows”?5 步解决:从等待到重装
  • 优惠券网站要怎么做的佛山禅城网站建设
  • 基于深度学习计算s21参数,在射频中的应用
  • 微服务day01——拆分作业参考
  • YOLO11训练后的模型无法正常推理解决办法
  • 网站模版 优帮云深圳网络安全公司排名
  • navicat过期了,怎么操作mysql。用DBeaver
  • LangGraph工作流与智能体核心模式总结
  • redis常见问题解决
  • 网站顶部有空白网络营销是什么时候出现的
  • NFS文件存储
  • 07_朴素贝叶斯
  • 【源码项目】简单实现的WPF浏览器,有兴趣的可以自己扩展(带源码)
  • 大连做网站哪家好一点商务网站建设用的是什么软件
  • Mybatis一级缓存
  • Java+OpenCV实现图片切割
  • Linux云计算基础篇(24)-PXE批量安装和Kickstart工具
  • 从零搭建 RAG 智能问答系统 6:Text2SQL 与工作流实现数据库查询
  • 创建Django项目
  • 注册个人网站的方法建设企业网站费用
  • 初识C语言13.自定义类型(联合体与枚举)
  • WebRTC入门指南:实时通信零基础
  • 深圳外贸营销型网站建设引擎搜索网站
  • Django 表单验证详解Form
  • k8s相关学习