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

DAYS 52【i.MX6ULL 裸机开发】I2C 通信全拆解:从开漏硬件特性到主机写流程实战

  • 首页
  • 资讯中心
  • /
  • DAYS 52【i.MX6ULL 裸机开发】I2C 通信全拆解:从开漏硬件特性到主机写流程实战

相关资讯

准备学c语言 2026/10/15 4:30:15
OpenCV 4.4.0编译world模块与contrib扩展的避坑指南 2026/10/15 4:25:15
开源AI编码代理OpenCode实测:终端里的自主编程助手 2026/10/15 4:25:15

最新资讯

两串电池组均衡方案:基于MP2642与dsPIC的被动均衡实战
程序员AI系统设计补全清单:从模型调用到生产可用
AI搜索时代营销变革:从SEO到GEO/AEO的实操指南
AI系统设计:程序员必须补上的工程护城河
UE4 C++ FVector实战指南:从基础运算到性能优化
用Pandoc把AI生成的Markdown转成Word/PDF全攻略

今日推荐

AI视频生成的时间一致性难题与时空建模演进
基于bbox的PDF文档解析:多栏重排与水印过滤实战
探矿数据进RAG前的清洗全攻略:TXT、Word、PDF、网页四类文档处理实践

本周热门

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

本月精选

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

DAYS 52【i.MX6ULL 裸机开发】I2C 通信全拆解:从开漏硬件特性到主机写流程实战

发布时间:2026/10/15 4:30:15
DAYS 52【i.MX6ULL 裸机开发】I2C 通信全拆解:从开漏硬件特性到主机写流程实战 前言在嵌入式开发里I2C 是绕不开的外设EEPROM、OLED 屏幕、温湿度传感器、触摸屏基本都靠 I2C 驱动。很多同学学 I2C 只背时序图却没搞懂「为什么 I2C 必须开漏 上拉」「线与特性到底有什么用」。 今天结合硬件原理图 标准时序图 寄存器操作流程图从物理层到协议层再到代码实现把 I2C 主机写流程彻底讲透最后附上 i.MX6ULL 裸机驱动代码。一、I2C 硬件基础线与特性与 GPIO 输出模式1. 核心特性总线 “线与”I2C 总线最本质的特点是线与逻辑SDA、SCL 两根线所有设备都并联挂在上面。 只要有任意一个设备把引脚拉低整条总线就会是低电平只有所有设备都输出高电平时总线才是高电平。对应真值表表格chipA 输出chipB 输出实际 pad 电平100010111000通俗理解低电平 “一票否决”高电平需要 “全票通过”。 这也是 I2C 支持多主机仲裁、从机时钟拉伸的硬件基础。2. GPIO 两种输出模式为什么 I2C 必须开漏GPIO 有推挽、开漏两种输出模式I2C 只能用开漏不能用推挽原因就在线与特性。推挽模式Push-Pull内部有上下两个 MOS 管上管接电源下管接地。输出高电平上管导通下管截止引脚强上拉到电源输出低电平上管截止下管导通引脚强下拉到地表格mos1上管mos2下管pad 电平状态10强高 3.3V01强低 GND00高阻悬空11禁止短路推挽模式下如果两个芯片引脚直接接在一起一个输出 1、一个输出 0相当于电源直接短路到地会烧坏芯片。所以I2C 绝对不能使用推挽输出。开漏模式Open-Drain开漏模式下上管永远不导通只有下管工作输出 0下管导通引脚拉到 GND输出 1下管截止引脚处于高阻悬空状态这时候必须外部加一个上拉电阻通常 4.7k~10kΩ引脚悬空时靠电阻把电平拉到高电平。这样就完美适配线与特性任何一个设备拉低总线就变低所有设备都不拉低总线靠上拉电阻走高。多个设备挂在一起也不会短路这就是 I2C 物理层的本质。3. 标准 I2C 硬件连接典型电路SDA、SCL 分别串联上拉电阻到电源主从芯片的 GPIO 都配置为开漏模式。额外优势3.3V 和 5V 设备可以通过开漏 上拉实现电平兼容这也是 I2C 通用性强的原因之一。二、I2C 标准时序详解搞懂硬件层再看协议层时序就非常清晰了。I2C 所有操作都遵循一套标准规则核心是起始、停止、数据传输、应答四个部分。1. 总线空闲SCL 和 SDA 同时保持高电平代表总线空闲没有设备占用。2. 起始信号STARTSCL 为高电平时SDA 由高变低产生下降沿即为起始信号。 只有主机可以发起起始信号标志着一次通信正式开始。3. 数据传输规则MSB 优先一个字节 8 位先传最高位最后传最低位。例如发送0xAC二进制10101100发送顺序为1→0→1→0→1→1→0→0。低电平变数据发送方只能在 SCL 低电平时改变 SDA 电平保证数据稳定。高电平采数据接收方在 SCL 高电平时读取 SDA此时 SDA 不允许变化确保采样正确。4. 应答信号ACK/NACK每传输完 8 位数据第 9 个时钟周期传输应答位ACK应答接收方主动把 SDA 拉低代表 “数据已收到”NACK不应答接收方不拉低 SDASDA 保持高电平代表 “未收到 / 结束通信”注意应答位由接收方控制发送方在第 9 个时钟会释放 SDA 总线。5. 停止信号STOPSCL 为高电平时SDA 由低变高产生上升沿即为停止信号。 标志本次通信结束主机释放总线。6. 完整写操作帧结构一次标准的 I2C 主机写操作帧结构为起始信号 → 从机地址(7bit) 写方向(0) → ACK → 寄存器地址 → ACK → 数据1 → ACK → 数据N → ACK → 停止信号三、i.MX6ULL I2C 主机写流程寄存器级i.MX6ULL 内置硬件 I2C 外设不需要模拟时序直接操作寄存器即可完成收发。下面对照流程图一步步拆解主机写操作。核心寄存器I2CR控制寄存器配置主从模式、收发方向、产生起始 / 停止信号I2SR状态寄存器存放中断标志、应答标志、总线状态I2DR数据寄存器写入即发送读取即接收主机写操作完整步骤初始化预处理清除状态寄存器中的仲裁丢失标志IAL清除中断标志IIF置位I2CR_MTX配置为主机发送模式产生起始信号置位对应控制位硬件自动在总线上产生 START 信号总线被主机占用。发送从机地址 写方向向I2DR写入(从机地址 1) | 0最低位 0 代表写操作。硬件自动按位串行发出。等待应答中断轮询I2SR_IIF位直到硬件置 1代表一帧数据发送完成、应答位已接收。 软件必须手动清除IIF标志。判断应答结果读取I2SR_RXAK位为 0收到 ACK从机正常响应为 1收到 NACK从机无响应直接结束通信发送寄存器地址向I2DR写入从机内部寄存器地址重复步骤 4~5 的等待、判断流程。循环发送数据进入循环依次将每个字节写入I2DR每发一个字节都执行 “等中断→清标志→判应答”。 直到所有数据发送完毕。产生停止信号释放总线配置寄存器产生 STOP 信号轮询总线状态位直到总线回到空闲状态一次写操作完成。四、裸机 C 代码实现下面给出 i.MX6ULL 硬件 I2C 主机写函数完全对应上面的流程图。#include imx6ull.h /* 产生起始信号 */ static void i2c_start(I2C_Type *base) { base-I2CR | (1 5); // MTX1主机发送模式 base-I2CR | (1 4); // 硬件产生START信号 } /* 产生停止信号 */ static void i2c_stop(I2C_Type *base) { base-I2CR ~(1 5); // 切换为接收模式 base-I2CR ~(1 4); // 硬件产生STOP信号 while(!(base-I2SR (1 5))); // 等待总线空闲 } /* * brief 发送一个字节并等待应答 * retval 0ACK 1NACK */ static uint8_t i2c_send_byte(I2C_Type *base, uint8_t data) { base-I2DR data; // 写入数据寄存器硬件自动发送 while(!(base-I2SR (1 1))); // 等待IIF中断标志置1 base-I2SR ~(1 1); // 软件清除IIF标志 // 判断RXAK应答位 return (base-I2SR (1 0)) ? 1 : 0; } /* * brief I2C主机写操作 * param base I2C外设基地址 * param addr 7位从机地址 * param reg 从机内部寄存器地址 * param buf 待发送数据缓冲区 * param len 数据长度 * retval 0成功 其他失败 */ uint8_t i2c_mem_write(I2C_Type *base, uint8_t addr, uint8_t reg, uint8_t *buf, uint32_t len) { uint8_t ret; uint32_t i; // 1. 清除标志配置主机发送模式 base-I2SR ~(1 4); // 清仲裁丢失标志IAL base-I2SR ~(1 1); // 清中断标志IIF base-I2CR | (1 5); // MTX1 主机发送 // 2. 起始信号 i2c_start(base); // 3. 发送从机地址 写方向 ret i2c_send_byte(base, (addr 1) | 0); if(ret) goto error_stop; // 4. 发送寄存器地址 ret i2c_send_byte(base, reg); if(ret) goto error_stop; // 5. 循环发送数据 for(i 0; i len; i) { ret i2c_send_byte(base, buf[i]); if(ret) goto error_stop; } // 6. 停止信号正常结束 i2c_stop(base); return 0; error_stop: i2c_stop(base); return 1; }五、常见踩坑总结上拉电阻不能省开漏模式本身不能输出高电平没有上拉电阻总线永远是低电平通信完全无法进行。从机地址要左移7 位地址存在高 7 位最低位是读写方向位不能直接把 7 位地址写入寄存器。中断标志必须软件清零IIF位硬件置 1必须软件写 0 清除否则下一次会一直卡在等待循环。SCL 高电平时严禁改 SDA模拟 I2C 尤其容易犯这个错误会被从机误判为起始 / 停止信号导致通信错乱。NACK 要及时停止收到 NACK 说明从机没响应继续发数据毫无意义应直接发停止信号退出。结语I2C 看着协议简单其实细节非常多。从硬件层的开漏、线与到时序层的采样规则再到寄存器层的收发流程一层层吃透写驱动才不会只会照搬例程。

关于恒美微站

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

快速链接

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

服务项目

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

联系方式

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

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