恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Linux 驱动开发学习笔记:I2C 子系统从入门到实践

  • 首页
  • 资讯中心
  • /
  • Linux 驱动开发学习笔记:I2C 子系统从入门到实践

相关资讯

Claude Code实战:终端里的AI编程助手,从安装到工作流落地 2026/10/14 4:43:01
自考本科论文用哪个工具可以免费查AI率?PaperRR每天2次免费AI检测,亲测好用! 2026/10/14 4:38:01
Python连接SQL Server完全指南:驱动选型、连接串避坑与增删改查实战 2026/10/14 4:38:01

最新资讯

别让AI一键成稿:如何用AI生成内容+模板渲染做出可编辑的高级感PPT
ADE不是新IDE,而是智能体开发范式迁移
Matlab实现风光互补系统Weibull-Beta联合建模
三菱PLC通讯协议对比:MC、CC-Link IE、EtherNet/IP怎么选?
OpenWAM:世界-动作模型预训练的模块化设计与实操
C# 反射获取接口特性:从 InterfaceMapping 到通用扩展方法全解析

今日推荐

IBM Verify Identity Access 修复 22 个漏洞:两个 9.8 严重 RCE 无需认证
小区物业管理系统
小型超市仓库管理系统

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Linux 驱动开发学习笔记:I2C 子系统从入门到实践

发布时间:2026/10/14 4:43:01
Linux 驱动开发学习笔记:I2C 子系统从入门到实践 1. 引言I2CInter-Integrated Circuit总线是一种由 Philips 公司现 NXP开发的两线式串行通信总线广泛应用于嵌入式系统中连接低速外设如传感器、EEPROM、RTC 时钟芯片、触摸控制器等。在 Linux 内核中I2C 子系统提供了完整的驱动框架屏蔽了底层硬件差异让开发者可以专注于设备驱动的业务逻辑。本文记录笔者学习 Linux I2C 驱动开发的过程从硬件协议基础到内核框架再到实际驱动编写逐步梳理关键知识点。2. I2C 协议基础在深入 Linux 驱动之前先回顾 I2C 总线的硬件协议要点这对理解内核框架的设计至关重要。2.1 物理层特性两线制SCL串行时钟线和 SDA串行数据线均为开漏输出需外接上拉电阻。多主多从总线上可挂载多个主机和从机通过地址区分设备。7 位或 10 位地址常用 7 位地址一个总线上最多挂载 112 个设备保留地址除外。传输速率标准模式 100 kbit/s快速模式 400 kbit/s高速模式 3.4 Mbit/s。2.2 数据传输格式一次完整的 I2C 传输包含起始条件START、地址帧、数据帧和停止条件STOP。读写操作的基本格式如下写操作START 从机地址(写) ACK 寄存器地址 ACK 数据 ACK STOP 读操作START 从机地址(写) ACK 寄存器地址 ACK START 从机地址(读) ACK 数据 NACK STOP理解这个时序是编写驱动的基础因为 Linux 内核的 I2C 传输接口本质上就是对这些时序的封装。3. Linux I2C 子系统架构Linux 内核将 I2C 子系统划分为三个层次控制器驱动Adapter、核心层Core和设备驱动Client Driver。理解这三层的关系是学习 I2C 驱动的关键。3.1 三层结构总览I2C Adapter控制器驱动直接操作硬件寄存器负责在总线上产生时序对应 SoC 上的 I2C 控制器外设。I2C Core核心层提供统一的设备模型、总线注册机制、数据传输接口以及设备与驱动的匹配逻辑对上层屏蔽控制器差异。I2C Client Driver设备驱动针对具体挂在总线上的设备如某型号传感器编写通过核心层提供的 API 与设备通信不直接操作硬件寄存器。3.2 关键数据结构I2C 子系统的核心数据结构主要有以下几个数据结构作用struct i2c_adapter描述一个 I2C 控制器包含总线号、算法、锁等。struct i2c_algorithm定义控制器收发数据的主函数master_xfer。struct i2c_client描述一个挂在总线上的设备包含地址、驱动名等。struct i2c_driver描述一个设备驱动包含 probe、remove 回调及 id 表。struct i2c_msg描述一次传输的消息包含地址、标志、缓冲区等。4. 设备驱动开发流程编写一个 I2C 设备驱动通常遵循固定的步骤。下面以读取一个虚拟传感器为例梳理完整流程。4.1 驱动框架搭建首先定义一个i2c_driver结构体并实现 probe 和 remove 回调#include linux/i2c.h #include linux/module.h #include linux/init.h static int my_sensor_probe(struct i2c_client *client) { pr_info(my_sensor: probe success, addr0x%02x\n, client-addr); return 0; } static void my_sensor_remove(struct i2c_client *client) { pr_info(my_sensor: remove\n); } static const struct i2c_device_id my_sensor_id[] { { my-sensor, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, my_sensor_id); static struct i2c_driver my_sensor_driver { .driver { .name my-sensor, }, .probe my_sensor_probe, .remove my_sensor_remove, .id_table my_sensor_id, }; module_i2c_driver(my_sensor_driver); MODULE_LICENSE(GPL);4.2 数据传输接口在 probe 中获取设备后就可以通过i2c_transfer或更便捷的i2c_smbus_read_byte_data等接口读写数据。以读取传感器寄存器为例static int my_sensor_read_reg(struct i2c_client *client, u8 reg, u8 *val) { int ret; struct i2c_msg msgs[2] { { .addr client-addr, .flags 0, .len 1, .buf reg, }, { .addr client-addr, .flags I2C_M_RD, .len 1, .buf val, }, }; ret i2c_transfer(client-gt;adapter, msgs, 2); if (ret ! 2) { dev_err(amp;client-gt;dev, read reg 0x%02x failed, ret%d\n, reg, ret); return ret lt; 0 ? ret : -EIO; } return 0; }4.3 设备树匹配在现代内核中通常通过设备树描述硬件。在设备树中声明设备节点后驱动通过of_match_table完成匹配static const struct of_device_id my_sensor_of_match[] { { .compatible vendor,my-sensor }, { } }; MODULE_DEVICE_TABLE(of, my_sensor_of_match); static struct i2c_driver my_sensor_driver { .driver { .name my-sensor, .of_match_table my_sensor_of_match, }, .probe my_sensor_probe, .remove my_sensor_remove, };对应的设备树节点示例i2c1 { my_sensor48 { compatible vendor,my-sensor; reg 0x48; }; };5. SMBus 接口与辅助函数对于大多数简单设备不必每次都构造i2c_msg数组。内核提供了 SMBus 风格的封装函数使用更加简洁。5.1 常用 SMBus API函数功能i2c_smbus_read_byte()读取一个字节不带寄存器地址。i2c_smbus_write_byte()写入一个字节不带寄存器地址。i2c_smbus_read_byte_data()读取指定寄存器的值。i2c_smbus_write_byte_data()向指定寄存器写入值。i2c_smbus_read_word_data()读取 16 位寄存器值。i2c_smbus_write_word_data()写入 16 位寄存器值。5.2 使用示例使用 SMBus 接口后前面的读寄存器函数可以简化为static int my_sensor_read_reg(struct i2c_client *client, u8 reg, u8 *val) { int ret; ret i2c_smbus_read_byte_data(client, reg); if (ret lt; 0) { dev_err(amp;client-gt;dev, read reg 0x%02x failed, ret%d\n, reg, ret); return ret; } *val (u8)ret; return 0; }6. 用户空间访问除了编写内核驱动Linux 还提供了用户空间访问 I2C 设备的接口方便调试和快速验证。通过/dev/i2c-N设备节点配合i2c-dev内核模块可以在应用层直接读写设备。6.1 使用 i2c-tools在开发板上安装i2c-tools后可以快速扫描总线和读写设备# 扫描总线上的设备 i2cdetect -y 1 读取 0x48 设备 0x00 寄存器的值 i2cget -y 1 0x48 0x00 向 0x48 设备 0x01 寄存器写入 0xff i2cset -y 1 0x48 0x01 0xff6.2 应用层编程在 C 程序中通过ioctl系统调用与I2C_RDWR命令完成读写#include stdio.h #include fcntl.h #include linux/i2c-dev.h #include sys/ioctl.h int main(void) { int fd open(/dev/i2c-1, O_RDWR); if (fd 0) { perror(open); return -1; } struct i2c_msg msgs[2]; unsigned char reg 0x00; unsigned char val 0; msgs[0].addr 0x48; msgs[0].flags 0; msgs[0].len 1; msgs[0].buf amp;reg; msgs[1].addr 0x48; msgs[1].flags I2C_M_RD; msgs[1].len 1; msgs[1].buf amp;val; struct i2c_rdwr_ioctl_data data { .msgs msgs, .nmsgs 2, }; if (ioctl(fd, I2C_RDWR, amp;data) lt; 0) { perror(ioctl); close(fd); return -1; } printf(reg 0x00 0x%02x\n, val); close(fd); return 0; }7. 调试与常见问题I2C 驱动开发中遇到问题可以从以下几个方向排查。7.1 常用调试手段开启内核调试日志在drivers/i2c目录下开启CONFIG_I2C_DEBUG_CORE和CONFIG_I2C_DEBUG_ALGO观察传输细节。逻辑分析仪抓取 SCL/SDA 波形确认时序是否符合协议。i2cdetect 扫描确认设备地址是否正确设备是否真的挂在总线上。检查上拉电阻SDA/SCL 必须有上拉电阻否则通信不稳定。7.2 常见错误码错误码含义-ENXIO无此设备通常是没有 ACK 应答地址错误或设备未上电。-ETIMEDOUT传输超时总线可能被拉死或时钟异常。-EBUSY总线忙可能被其他主机占用。-EINVAL参数无效检查消息长度和标志位。8. 总结Linux I2C 驱动开发的核心在于理解三层架构控制器驱动负责时序核心层负责统一抽象设备驱动负责业务逻辑。实际开发中大部分工作集中在编写i2c_driver和利用 SMBus 辅助函数读写寄存器。建议初学者先在用户空间用 i2c-tools 验证硬件通路再编写内核驱动这样能有效缩小问题排查范围。后续可以进一步学习 I2C 的 10 位地址、多主机仲裁、DMA 传输等进阶内容。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号