天天看点

S5PV210系列 (裸机十六) 之 I2C通信详解

什么是I2C通信

物理接口:SCL + SDA

(1)SCL(serial clock):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道。

(2)SDA(serial data): 数据线,通信数据都通过SDA线传输

通信特征:串行、同步、非差分、低速率

(1) I2C 属于串行通信,所有的数据以位为单位在 SDA 线上串行传输。

(2)同步通信就是通信双方工作在同一个时钟下,一般是通信的 A 方通过一根CLK 信号线传输 A 自己的时钟给 B,B 工作在 A 传输的时钟下。所以同步通信的显著特征就是:通信线中有 CLK

(3)非差分。因为 I2C 通信速率不高,而且通信双方距离很近,所以使用电平信号通信。

(4)低速率。I2C 一般是用在同一个板子上的 2 个 IC 之间的通信,而且用来传输的数据量不大,所以本身通信速率很低(一般几百 KHz,不同的 I2C 芯片的通信速率可能不同,具体在编程的时候要看自己所使用的设备允许的 I2C 通信最高速率,不能超过这个速率)

突出特征1:主设备+从设备

(1) I2C 通信的时候,通信双方地位是不对等的,而是分主设备和从设备。通信由主设备发起,由主设备主导,从设备只是按照 I2C 协议被动的接受主设备的通信,并及时响应。

(2)谁是主设备、谁是从设备是由通信双方来定的( I2C 协议并无规定),一般来说一个芯片可以只能做主设备、也可以只能做从设备、也可以既能当主设备又能当从设备(软件配置)。

突出特征 2:可以多个设备挂在一条总线上(从设备地址)

(1) I2C 通信可以一对一( 1 个主设备对 1 个从设备),也可以一对多( 1 个主设备对多个从设备)。

(2)主设备来负责调度总线,决定某一时间和哪个从设备通信。注意:同一时间内,I2C 的总线上只能传输一对设备的通信信息,所以同一时间只能有一个从设备和主设备通信,其他从设备处于“冬眠”状态,不能出来捣乱,否则通信就乱套了。

(3)每一个 I2C 从设备在通信中都有一个 I2C 从设备地址,这个设备地址是从设备本身固有的属性,然后通信时主设备需要知道自己将要通信的那个从设备的地址,然后在通信中通过地址来甄别是不是自己要找的那个从设备。(这个地址是一个电路板上唯一的,不是全球唯一的)

主要用途:SoC 和周边外设之间的通信(典型的如 EEPROM、电容触摸 IC、各种 sensor 等)

由I2C学通信时序

什么是时序?

(1)时序:字面意思,时序就是时间顺序,实际上在通信中时序就是通信线上按照时间顺序发生的电平变化,以及这些变化对通信的意义就叫时序。

I2C 的总线空闲状态、起始位、结束位

(1)I2C 总线上有 1 个主设备,n(n >= 1)个从设备。I2C 总线上有 2 种状态;空闲态(所有从设备都未和主设备通信,此时总线空闲)和忙态(其中一个从设备在和主设备通信,此时总线被这一对占用,其他从设备必须歇着)。

(2)整个通信分为一个周期一个周期的,两个相邻的通信周期是空闲态。每一个通信周期由一个起始位开始,一个结束位结束,中间是本周期的通信数据。

(3)起始位并不是一个时间点,起始位是一个时间段,在这段时间内总线状态变化情况是:SCL 线维持高电平,同时 SDA 线发生一个从高到低的下降沿。

(4)与起始位相似,结束位也是一个时间段。在这段时间内总线状态变化情况是:SCL 线维持高电平,同时 SDA 线发生一个从低到高的上升沿。

I2C 数据传输格式(数据位& ACK )

(1)每一个通信周期的发起和结束都是由主设备来做的,从设备只有被动的响应主设备,没法自己自发的去做任何事情。

(2)主设备在每个通信周期会先发 8 位的从设备地址(其实 8 位中只有 7 位是从设备地址,还有 1 位表示主设备下面要写入还是读出)到总线(主设备是以广播的形式发送的,只要是总线上的所有从设备其实都能收到这个信息)。然后总线上的每个从设备都能收到这个地址,并且收到地址后和自己的设备地址比较看是否相等。如果相等说明主设备本次通信就是给我说话,如果不想等说明这次通信与我无关,不用听了不管了。

(3)发送方发送一段数据后,接收方需要回应一个 ACK。这个响应本身只有 1 个bit 位,不能携带有效信息,只能表示 2 个意思(要么表示收到数据,即有效响应;要么表示未收到数据,无效响应)

(4)在某一个通信时刻,主设备和从设备只能有一个在发(占用总线,也就是向总线写),另一个在收(从总线读)。如果在某个时间主设备和从设备都试图向总线写那就完蛋了,通信就乱套了。

数据在总线上的传输协议

(1) I2C 通信时的基本数据单位也是以字节为单位的,每次传输的有效数据都是1个字节( 8 位)。

(2)起始位及其后的 8 个 clk 中都是主设备在发送(这设备掌控总线),此时从设备只能读取总线,通过读总线来得知主设备发给从设备的信息;然后到了第 9 周期,按照协议规定从设备需要发送 ACK 给主设备,所以此时主设备必须释放总线(主设备把总线置为高电平然后不要动,其实就类似于总线空闲状态),同时从设备试图拉低总线发出 ACK。如果从设备拉低总线失败,或者从设备根本就没有拉低总线,则主设备看到的现象就是总线在第 9 周期仍然一直保持高,这对主设备来说,意味着我没收到 ACK,主设备就认为刚才给从设备发送的 8 字节不对(接收失败)

S5PV210 的 I2C 控制器

通信双方本质上是通过时序在工作,但是时序会比较复杂不利于 SoC 软件完成,于是乎解决方案是 SoC 内部内置了硬件的控制器来产生通信时序。这样我们写软件时只需要向控制器的寄存器中写入配置值即可,控制器会产生适当的时序在通信线上和对方通信。

结构框图

S5PV210系列 (裸机十六) 之 I2C通信详解

(1)时钟部分,时钟来源是 PCLK_PSYS,经过内部分频最终得到 I2C 控制器的 CLK,通信中这个 CLK 会通过 SCL 线传给从设备。

(2) I2C 总线控制逻辑(前台代表是 I2CCON、I2CSTAT 这两个寄存器),主要负责产生 I2C 通信时序。实际编程中要发送起始位、停止位、接收 ACK 等都是通过这两个寄存器(背后所代表的电路模块)实现的。

(3)移位寄存器(shift register),将代码中要发送的字节数据,通过移位寄存器变成 1 个位一个位的丢给 SDA 线上去发送/接收。学过数字电路的同学应该对移位寄存器不陌生。

(4)地址寄存器+比较器。本 I2C 控制器做从设备的时候用。(我没用过,理论分析)

系统分析 I2C 的时钟

(1)I2C 时钟源头来源于 PCLK(PCLK_PSYS,等于65MHz),经过了 2 级分频后得到的。

(2)第一级分频是 I2CCON 的 bit6,可以得到一个中间时钟 I2CCLK(等于PCLK/16 或者 PCLK/512)

(3)第二级分频是得到最终 I2C 控制器工作的时钟,以 I2CCLK 这个中间时钟为来源,分频系数为 [1,16]

(4)最终要得到时钟是 2 级分频后的时钟,譬如一个可用的设置是:65000KHz/512/4 = 31KHz

主要寄存器 I2CCON、I2CSTAT、I2CADD、I2CDS

I2CCON + I2CSTAT:主要用来产生通信时序和 I2C 接口配置。

I2CADD:用来写自己的 slave address

I2CDS:发送/接收的数据都放在这里

X210 板载 gsensor 介绍

原理图查阅

S5PV210系列 (裸机十六) 之 I2C通信详解

(1)gsensor 的供电由 PWMTOUT3 引脚控制。当 PWMTOUT3 输出低电平时gsensor 无电不工作;当输出高电平时 gsensor 才会工作。

(2)gsensor 的 SDA 和 SCL 接的是 S5PV210 的 I2C 端口 0

(3)将来编程时在 gsensor_init 函数中要去初始化相关的 GPIO。要把相应的 GPIO 设置为正确的模式和输入输出值。

重力加速度传感器简介

(1)用在手机、平板、智能手表等设备上,用来感受人的手的移动,获取一些运动的方向性信息用来给系统作为输入参量。

(2)可以用来设计智能手表的计步器功能。

(3)重力加速度传感器、地磁传感器、陀螺仪等三个传感器结合起来,都是用来感谢运动的速度、方位等信息的,所以现在最新的有 9 轴传感器,就是把三者结合起来,并且用一定的算法进行综合得出结论,目的是更加准确。

(4)一般传感器的接口有 2 种:模拟接口和数字接口。模拟接口是用接口电平变化来作为输出的(譬如模拟接口的压力传感器,在压力不同时输出电平在 0〜3.3V范围内变化,每一个电压对应一个压力。),SOC 需要用 AD 接口来对接这种传感器对它输出的数据进行 AD 转换,转换得到数字电压值,再用数字电压值去校准得到压力值;数字接口是后来发展出来的,数字接口的 sensor 是在模拟接口的sensor 基础上,内部集成了 AD,直接(通过一定的总线接口协议,一般是 I2C )输出一个数字值的参数,这样 SoC 直接通过总线接口初始化、读取传感器输出的参数即可(譬如 gsensor、电容触摸屏 IC)。

I2C从设备的设备地址

(1) KXTE9 的 I2C 地址固定为 0b0001111(0x0f)

(2)I2C从设备地址本身是7位的,但是在 I2C 通信中发送 I2C 从设备地址时实际发送的是8位,这8位中高7位(bit7-bit1)对应I2C从设备的7位地址,最低一位(LSB)存放的是R/W信息(就是说下一个数据是主设备写从设备读(对应0),还是主设备读从设备写(对应1))

(3)基于上面讲的,对于 KXTE9 来说,主设备( SoC )发给 gsensor 信息时,SAD应该是:0b00011110(0x1E)

如果是主设备读取 gsensor 信息时,SAD 应该是:0b00011111( 0x1F )

I2C从设备的通信速率

(1) I2C 协议本身属于低速协议,通信速率不能太高。

(2)实际上通信的主设备和从设备本身都有最高的通信速率限制(属于各个芯片本身的参数),实际编程时怎么确定最终的通信速率?只要小于两个即可。

(3)一般来说只能做从设备的 sensor 芯片本身 i2c 通信速率偏低,像 KXTE9 最高支持 400KHz 的频率。

I2C总线的通信流程

S5PV210的主发送流程图

S5PV210系列 (裸机十六) 之 I2C通信详解

S5PV210的主接收流程图

S5PV210系列 (裸机十六) 之 I2C通信详解

gsensor的写寄存器流程图

S5PV210系列 (裸机十六) 之 I2C通信详解

gsensor的读寄存器流程图

S5PV210系列 (裸机十六) 之 I2C通信详解

I2C通信代码分析

I2C控制器初始化:s3c24xx_i2c_init

(1)初始化做的事情:初始化GPIO,设置IRQEN和ACKEN,初始化I2C时钟

I2C控制器主模式开始一次读写:s3c24xx_i2c_message_start

I2C控制器主模式结束一次读写:s3c24xx_i2c_stop

框架分析:

我们最终目的是通过读写 gsensor 芯片的内部寄存器来得到一些信息。为了完成这个目的,我们需要能够读写 gsensor 的寄存器,根据 gsensor 的规定我们需要按照一定的操作流程来读写 gsensor 的内部寄存器,这是一个层次(姑且叫做传输层、协议层、应用层);我们要按照操作流程去读写寄存器,就需要考虑 I2C 接口协议(这就是所谓的物理层,本质就是那些时序)。此时主机 SoC 有或者没有控制器,有控制器时考虑控制器的寄存器,没控制器时要自己软件模拟时序。

协议层的代码主要取决于 gsensor 芯片;物理层代码主要取决于主机 SoC。

gsensor写寄存器:gsensor_i2c_write_reg

gsensor读寄存器:gsensor_i2c_read_reg

gsensor编程:gsensor_initial等

继续阅读