I2C 通信详解

目录

1. I2C 通信介绍

2. 硬件电路

3. I2C 时序基本单元

 3.1 起始与终止信号

3.2 发送一个字节

3.3 接收一个字节

3.4  发送应答与接收应答

 4. I2C 完整时序数据帧

4.1 指定地址写

4.2 指定地址读

5. I2C 基本结构

5.1 主机发送

 5.2 主机接收

6. 软 / 硬件 I2C 对比

7. STM32 I2C 配置

 8. STM32 硬件 I2C 发送与接收

8.1 I2C 发送一个字节

8.2 I2C 接收一个字节

9. I2C 仲裁机制

 


1. I2C 通信介绍

  • I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线
  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data)
  • 同步半双工
  • 带数据应答 (0 -- > 确认应答、1 -- > 非应答)
  • 支持总线挂载多设备(一主多从、多主多从)

异步时序的特点:

  • 好处:不需要时钟线,省一根线
  • 缺点:对硬件电路非常依赖

2. 硬件电路

  • 所有 I2C 设备的 SCL 连在一起,SDA 连在一起
  • 设备的 SCL 和 SDA 均要配置成开漏输出模式
  • SCL 和 SDA 各添加一个上拉电阻,阻值一般为4.7KΩ左右

3. I2C 时序基本单元

特点:

  • SCL 高电平期间如果检测到 SDA 有变化(拉低或者拉高)即是起始或者终止信号。
  • SCL 高电平期间如果 SDA 无变化那就是正在读 SDA 信号,0 或 1。
  • SCL 低电平期间可以允许 SDA 电平发生跳变,为下一次读取信号做准备。

栗子

读取信号类似 123 木头人游戏。SCL 来发口令,SDA 来做动作:

当 SCL 是低电平时(相当于在喊123木头人),此时 SDA 允许变动来做好准备,当 SCL 变成高电平时(相当于喊完木头人此时转身),此时 SDA 不准变动,开始读取 SDA 的值来确定这一位是 0 还是 1,重复上述动作 8 次即可读取或者写入一个字节。

如果在 SCL 高电平期间(喊完123木头人转身后),发现 SDA 还在发生变动(还有人在动 -- > 淘汰),这说明这是一个起始信号或者终止信号。

 3.1 起始与终止信号

起始条件:SCL高电平期间,SDA从高电平切换到低电平

终止条件:SCL高电平期间,SDA从低电平切换到高电平

3.2 发送一个字节

        规则:SCL 低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程 8 次,即可发送一个字节

3.3 接收一个字节

        规则:SCL 低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

接收字节与发送字节的区别(收发都是对主机是描述):

  • (主机)发送数据时:SCL 低电平由主机来设定 SDA 数据,SCL 高电平时从机来读取 SDA 数据
  • (主机)接收数据时:SCL 低电平由从机来设定 SDA 数据,SCL 高电平时主机来读取 SDA 数据

3.4  发送应答与接收应答

        发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据数据0表示应答,数据1表示非应答

        接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)

 4. I2C 完整时序数据帧

4.1 指定地址写

对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)。

从机地址采用七位地址。最后一位(第七位)可变,可以用来区分接了多个相同的设备。

开始信号 --> 发送一个字节(7位从机地址 + 1位读(1) / 写(0)标志位) -- > 接收应答(每发送8位都要接收一次应答) --> 开始写入 8 位代表写入数据的指定地址 --> 接收应答(同上) --> 写入8位代表需要写入指定地址的数据 -- > 接收应答 -- > 结束信号。

4.2 指定地址读

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)

5. I2C 基本结构

5.1 主机发送

 5.2 主机接收

6. 软 / 硬件 I2C 对比

7. STM32 I2C 配置

 8. STM32 硬件 I2C 发送与接收

8.1 I2C 发送一个字节

 根据 5.1 流程可以写出以下逻辑,每次发送完数据后需要等待对应事件的发生。

8.2 I2C 接收一个字节

9. I2C 仲裁机制

I2C 总线仲裁主要遵循三个机制:

  • 线与:多主机时,总线具有“线与”的逻辑功能,即只要有一个节点发送低电平时,总线上就表现为低电平
  • SDA回读:总线被启动后,多个主机在每发送一个数据位时都要对自己的输出电平进行检测,只要检测的电平与自己发出的电平一致,就会继续占用总线
  • 低电平优先:由于线与的存在,当多主机发送时,谁先发送低电平谁就会掌握对总线的控制权

  • 28
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在Linux操作系统下,I2C是一种常见的通信协议,用于连接主机与各种外部设备,如传感器、扩展模块等。在编写Linux下的I2C代码时,需要使用Linux提供的I2C子系统,它包含了各种函数和结构体,用于管理和操作I2C总线。 首先,我们需要创建一个I2C设备的句柄,可以使用函数`open()`打开对应的设备文件,如`/dev/i2c-0`。如果成功打开设备文件,就可以使用`ioctl()`函数进行各种设置和控制操作。例如,通过`I2C_SLAVE`命令可以指定要与之通信的从设备的地址。 接下来,我们可以使用`i2c_smbus_*()`系列函数来进行I2C通信。这些函数封装了一些常用的I2C操作,如读写字节、读取寄存器等。对于特定的I2C设备,可能还需要使用其他特定的函数进行访问。 在使用`i2c_smbus_*()`函数进行通信时,需要注意传入的参数。例如,读操作需要指定要读取的字节个数,写操作需要指定要写入的数据。同时,还要注意处理函数的返回值,以便判断操作是否成功。 另外,可以使用`close()`关闭I2C设备的句柄,释放资源。 需要注意的是,编写Linux下的I2C代码需要有一定的编程基础和对Linux系统的了解。还需要查阅相关的资料,了解具体的设备地址、寄存器映射关系,以及所需的操作命令和数据格式等。 总之,编写Linux下的I2C代码需要熟悉Linux系统提供的I2C子系统和相关函数,同时还需要了解具体的设备和通信协议的细节。只有掌握了这些知识,才能有效地进行I2C通信,并与外部设备进行数据交互。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值