I2C 应用编程

1. I2C 框架结构

1.1 I2C 硬件框架

I2C 总线拓扑图

在一个芯片 (SoC) 内部,有一个或多个 I2C 控制器
在一个 I2C 控制器上,可以连接一个或多个 I2C 设备
I2C 总线只需要 2 条线:时钟线 SCL 数据线 SDA
I2C 总线的 SCL SDA 线上,都有上拉电阻

1.2 I2C 软件框架

I2C 接口的存储设备 AT24C02 为例:

APP
        ◼ 提出要求:把字符串 "www.100ask.net" 写入 AT24C02 地址 16 开始的地方
        ◼ 它是大爷,不关心底层实现的细节
        ◼ 它只需要调用设备驱动程序提供的接口
AT24C02 驱动:
        ◼ 它知道 AT24C02 要求的地址、数据格式
        ◼ 它知道发出什么信号才能让 AT24C02 执行擦除、烧写工作
        ◼ 它知道怎么判断数据是否烧写成功
        ◼ 它构造好一系列的数据,发给 I2C 控制器
I2C 控制器驱动
        ◼ 它根据 I2C 协议发出各类信号: I2C 设备地址、 I2C 存储地址、数据
        ◼ 它根据 I2C 协议判断

1.3 我们讲什么

1.3.1 对于 Linux I2C 结构

从上到下:
先讲 I2C 协议
APP 可以通过两类驱动程序访问设备
        ◼ I2C 设备自己的驱动程序
        ◼ 内核自带的 i2c-dev.c 驱动程序,它是 i2c 控制器驱动程序暴露给用户空间的驱动程序(i2c-dev.c)
I2C Device Driver
        ◼ I2C 设备自己的驱动程序
        ◼ 内核自带的 i2c-dev.c 驱动程序,它是 i2c 控制器驱动程序暴露给用户空间的驱动程序(i2c-dev.c)
I2C Controller Driver
        ◼ 芯片 I2C 控制器的驱动程序 ( 称为 adapter)
        ◼ 使用 GPIO 模拟的 I2C 控制器驱动程序 (i2c-gpio.c)

1.3.2 对于单片机/裸机

从上到下:
先讲 I2C 协议
APP
I2C Device Driver
I2C Controller Driver( 也被称为 adapter)

2 I2C 协议

2.1 硬件连接

        I2C 在硬件上的接法如下所示,主控芯片引出两条线 SCL,SDA 线,在一条 I2C 总线上可以接很多 I2C 设备,我们还会放一个上拉电阻(放一个上拉电阻的原因以后我们再说)。

2.2 传输数据类比

        怎么通过 I2C 传输数据,我们需要把数据从主设备发送到从设备上去,也需要把数据从从设备传送到主设备上去,数据涉及到双向传输。
        举个例子:         

        体育老师:可以把球发给学生,也可以把球从学生中接过来。
发球:
        ◼ 老师:开始了 (start)
        ◼ 老师: A !我要发球给你! ( 地址 / 方向 )
        ◼ 学生 A :到! ( 回应 )
        ◼ 老师把球发出去(传输)
        ◼ A 收到球之后,应该告诉老师一声(回应)
        ◼ 老师:结束(停止)
接球:
        ◼ 老师:开始了 (start)
        ◼ 老师: B !把球发给我! ( 地址 / 方向 )
        ◼ 学生 B :到!
        ◼ B 把球发给老师(传输)
        ◼ 老师收到球之后,给 B 说一声,表示收到球了(回应)
        ◼ 老师:结束(停止)
我们就使用这个简单的例子,来解释一下 IIC 的传输协议:
老师说开始了,表示开始信号 (start)
老师提醒某个学生要发球,表示发送地址和方向 (address/read/write)
老师发球 / 接球,表示数据的传输
收到球要回应:回应信号 (ACK)
老师说结束,表示 IIC 传输结束 (P)

2.3 IIC 传输数据的格式

2.3.1 写操作

主芯片要发出一个 start 信号
然后发出一个设备地址 ( 用来确定是往哪一个芯片写数据 ) ,方向 ( / 写, 0 表示写,1 表示读 )
从设备回应 ( 用来确定这个设备是否存在 ) ,然后就可以传输数据
主设备发送一个字节数据给从设备,并等待回应
每传输一字节数据,接收方要有一个回应信号(确定数据是否接受完成 ) ,然后再传输下一个数据。
数据发送完之后,主芯片就会发送一个停止信号。
下图:白色背景表示 " " ,灰色背景表示 " "

2.3.2 读操作

流程如下:
主芯片要发出一个 start 信号
然后发出一个设备地址 ( 用来确定是往哪一个芯片写数据 ) ,方向 ( / 写, 0 表示写,1 表示读 )
从设备回应 ( 用来确定这个设备是否存在 ) ,然后就可以传输数据
从设备发送一个字节数据给主设备,并等待回应
每传输一字节数据,接收方要有一个回应信号(确定数据是否接受完成 ) ,然后再传输下一个数据。
数据发送完之后,主芯片就会发送一个停止信号。
下图:白色背景表示 " " ,灰色背景表示 " "

3 I2C 信号

        I2C 协议中数据传输的单位是字节,也就是 8 位。但是要用到 9 个时钟:前面 8 个时钟用来传输 8 数据,第 9 个时钟用来传输回应信号。传输时,先传输最高位(MSB)
开始信号( S ): SCL 为高电平时, SDA 由 高电平向低电平跳变,开始传送数据。
结束信号( P ): SCL 为高电平时, SDA 由低电平向高电平跳变,结束传送数据。
响应信号 (ACK) :接收器在接收到 8 位数据后,在第 9 个时钟周期,(从设备)拉低 SDA
SDA 上传输的数据必须在 SCL 为高电平期间保持稳定, SDA 上的数据只能在SCL 为低电平期间变化
        I2C 协议信号如下(前半部分数据是发送地址位和方向,后半部分是数据,发送原理一样):

        在 SCL 为高电平时,SDA 拉高,读取到 1;在SCL为高电平时,SDA拉低,读取到0。

4 协议细节

如何在 SDA 上实现双向传输?
        ◼ 主芯片通过一根 SDA 线既可以把数据发给从设备,也可以从 SDA 上读取数据,连接 SDA 线的引脚里面必然有两个引脚(发送引脚 / 接受引脚)。
主、从设备都可以通过 SDA 发送数据,肯定不能同时发送数据,怎么错开时间?在 9 个时钟里:
        ◼ 前 8 个时钟由主设备发送数据的话,第 9 个时钟就由从设备发送数据;
        ◼ 前 8 个时钟由从设备发送数据的话,第 9 个时钟就由主设备发送数据。
双方设备中,某个设备发送数据时,另一方怎样才能不影响 SDA 上的数据?
        ◼ 设备的 SDA 中有一个三极管,使用开极 / 开漏电路 ( 三极管是开极, CMOS 管是开漏,作用一样) ,如下图:

相关推荐

  1. Linux在应用层上使用I2C

    2023-12-12 13:32:04       33 阅读
  2. STM32外设编程指南:GPIO、UART、SPI和I2C

    2023-12-12 13:32:04       10 阅读
  3. 模拟I2C通信

    2023-12-12 13:32:04       38 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-12 13:32:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-12 13:32:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-12 13:32:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-12 13:32:04       20 阅读

热门阅读

  1. C++大型项目经验

    2023-12-12 13:32:04       39 阅读
  2. Windows使用virtualenv创建python环境

    2023-12-12 13:32:04       42 阅读
  3. 使用CloudCompare计算点云曲率 - 编程指南

    2023-12-12 13:32:04       44 阅读
  4. C++相关闲碎记录(7)

    2023-12-12 13:32:04       29 阅读
  5. UGUI - 动态赋值后刷新不及时问题

    2023-12-12 13:32:04       44 阅读
  6. VTK:使用AlignFrames进行帧对齐的用法

    2023-12-12 13:32:04       39 阅读
  7. 基于协同过滤算法的旅游推荐系统设计与实现

    2023-12-12 13:32:04       38 阅读