简化理解I2C总线

这篇文章主要是理解,不是入门文章,建议先去搜索入门文章,看不懂再来看这篇文章,帮助理解。

1. 应用场景

  • 嵌入式系统中,用于将板载外设连接到CPU,比如说传感器
  • 因为只有一个数据线和时钟线,抗干扰能力差,传输速度不高,所以适用于板内低速外设,一根线,只能是半双工。

2. 工作原理

两根线:

  • 时钟线 SCL:时钟的作用一定要理解,类似于军训走正步时的口哨声,没时钟就停止,有时钟才继续下一步,系统内的所有设备在时钟的步调下运作,才不会混乱。时钟是目前任何数字系统运行的基本驱动力。
  • 数据线 SDA:就是传数据的一根线,没什么特别的地方。一根线决定了传输数据不会特别快,而且不能长距离传输。

3. 工作模式

  • 一主多从模式(99%场景)
  • 多主多从模式(不用管)

4. 通信过程

4.1 主发从收(CPU下发指令)

CPU视角:

复制代码
发START → [发设备地址+0 → ACK] → [寄存器地址 → ACK] → [数据1 → ACK → ... → 数据N → ACK] → 发STOP
  • 有开始,有结束
  • 先发地址,选中设备,选中设备后,选择设备寄存器,都选好了以后发数据,发数据以字节为单位,数据长度是N个字节,不会有不完整的字节,否则信号会出现歧义
  • 除了开始结束,任何操作都有ACK
  • START:在SCL高电平时拉低SDA,就代表开启信号,那就说明刚开始SDA是高,表示空闲。
  • STOP:在SCL保持高电平时,将SDA从低电平释放至高电平,就代表结束信号。

4.2 从发主收(外设上报状态)无此模式!

不行!从设备不能主动上报状态!

结构上因为时钟是CPU控制的,从机控制不了时钟,所以不能主动发。

4.3 主发主读(CPU先写)

当需要读取从设备的特定寄存器​(如传感器数据寄存器、EEPROM存储单元)时,主设备需先写入目标地址,再切换为读操作。

​流程步骤​:

​写地址阶段​:

主设备发送START信号 + ​从设备地址(写模式,R/W位=0)​​ → 等待ACK。

主设备发送寄存器地址​ → 从设备回复ACK。

​读数据阶段​:

主设备发送Repeated START信号​(不释放总线)。

主设备发送从设备地址(读模式,R/W位=1)​​ → 等待ACK。

从设备发送数据 → 主设备回复ACK/NACK控制数据流。

​终止​:主设备发送STOP信号结束通信。

为什么要先写后读?

大多数I2C从设备(如EEPROM、传感器)内部有一个地址指针寄存器,用于指示当前操作的数据位置。

​工作原理​

  • 写地址阶段​:主设备发送寄存器地址(如0x00),从设备收到后将该地址存入指针寄存器,相当于设置数据读取的起点。

  • ​读数据阶段​:从设备根据指针寄存器的值返回对应地址的数据,并在每次读取后自动递增指针(连续读时)。

​必要性​:若跳过写地址直接读,从设备可能返回随机地址的数据​(如上次操作残留的指针值),导致数据错乱。

相关推荐
序安InToo5 天前
第6课|注释与代码风格
后端·操作系统·嵌入式
济61711 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
嵌入小生00711 天前
线程间通信---嵌入式(Linux)
linux·c语言·vscode·嵌入式·互斥锁·线程间通信·信号量
济61711 天前
ARM Linux 驱动开发篇---GPIO子系统详解-- Ubuntu20.04
linux·嵌入式·嵌入式linux驱动开发
charlie11451419111 天前
嵌入式C++教程——Lambda捕获与性能影响
开发语言·c++·笔记·嵌入式·现代c++·工程实践
嵌入小生00712 天前
线程(2)/ 线程属性 /相关函数接口--- 嵌入式(Linux)
linux·嵌入式·线程·软件编程·僵尸线程·马年开工第一学·线程属性
序安InToo12 天前
第4课|程序结构与编译流程
后端·操作系统·嵌入式
济61712 天前
ARM Linux 驱动开发篇--- pinctrl 子系统详解-- Ubuntu20.04
linux·嵌入式·嵌入式linux驱动开发
济61712 天前
FreeRTOS基础知识---为什么使用FreeRTOS以及其核心功能
嵌入式·freertos
乔碧萝成都分萝13 天前
二十六、IIO子系统 + SPI子系统 + ICM20608
linux·驱动开发·嵌入式