I2C集成电路总线
(摘要:空闲时,时钟线数据线都是高电平,主机发送数据前,要在时钟为高电平时,把数据线从高电平拉低,数据发送采取高位先行,时钟线低电平时可以修改数据线,时钟线高电平时要求数据线稳定,数据为8bit,发到第九个bit时,是应答位,另一个设备应答为低电平为ack,高电平为nack,结束通信,时钟线高电平时,把数据线从低电平拉高。)
(主设备发送完起始信号,第一个字节是设备地址8bit,最后一位为0表示主机发数据,从机收数据,反之主收从发,所以设备可以有2^7个)
e2prom芯片
IIC(Inter-Integrated Circuit)又称I2C,是是IICBus简称,所以中文应该叫集成电路总线。是飞
利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展而来的一种同
步串行半双工通信总线方式。该总线允许同时连接多个设备(芯片)。每块芯片在总线上拥有特定的
地址。自2006年10月1日起,使用I²C协议已经不需要支付专利费,但制造商仍然需要付费以获取
IIC从属设备地址。
上图所示是IIC的总线的使用场景,所有挂载在IIC总线上的设备都有两根信号线,一根是数据线SDA,另一根是时钟线SCL。这两个信号线都是双向的。作为一种通信方式, IIC总线在某一时刻,总线只允许有一个设备处于发送状态,所发生的数据被总线上所有的设备所接收。 IIC通信协议包含有设备地址,只有发送方携带的地址与某个接收方的地址相同时,接收方才真正执行相关的指令.
IIC总线规定,设备在空闲时,两根总线都处于高电平状态。为保证这种状态,数据线SDA和时钟线SCL都要外接上拉电阻。 对于I.MX来说,这个上拉电阻也可以在引脚电器配置中设置。
IIC总线上连接的若干设备中,每次通信前,发送方首先发送一个“起始”信号,其实信号就是在SCL为高电平时, SDA发送一个低电平。当其它设备接收到这个其实信号后,将进行一次“总线仲裁”。意思就是设备(除发送起始信号的那个设备以外的)都将处于聆听状态。
IIC总线进行数据传送时,时钟线(SCL)上的信号为高电平期间,数据线(SDA)上的数据必须保持稳定。只有在时钟线(SCL)上的信号为低电平期间,数据线(SCL)上的高电平或低电平状态才允许变化。同时, SCL信号由数据启动发送的设备提供。输出到数据线(SDA)上的每个字节必须是8位。数据传送时,先传送最高位(MSB),后传送最低位(LSB)
发送器每发送一个字节(8个bit),就在时钟脉冲 9 期间释放数据线,由接收器反馈一个应答信号。 主机SCL拉高,读取从机SDA的电平。对于反馈有效应答位ACK的要求是:接收器在第9个时钟脉冲之前的低电平期间将数据线SDA拉低,并且确保在该时钟的高电平期间为稳定的低电平。
数据线(SDA)为低电平时,规定为有效应答位(ACK,简称应答位),表示接收器已经成功地接收了该字节。
数据线(SDA)为高电平时,规定为非应答位(NACK),表示接收器没有成功接收该字节。
当发送方发送完最后一个bit后,需要发送一个结束标志来终止整个通信过程。当时钟线SCL 为高电平时,数据线SDA 由低电平向高电平跳变。
上图就是一个完整的IIC通信时序图。
由于I2C总线是一种总线式连接方式,意味着在同样的两根线上可能连接有多个不同的设备,这种总线式连接方案通常会被设计为主从应答通信方式。也就是说,对于总线上连接的所有设备来说,有一个设备是主设备,而其他设备都是从设备。设备之间的通信都是由主设备发起的,从设备被动应答主设备。这里不难看出: 1、从设备之间是无法直接完成通信的; 2、总线上的从设备必须拥有一个独一无二的标识,这个标识被称为设备地址。设备地址类似一个人的名字,因为在I2C总线通信过程中,无论哪个设备发送数据,其他所有设备都能够监听得到,所以每次通信时,主设备先发送要访问的子设备地址,每个子设备都把监听到的这个地址拿来跟自己进行匹配,只有匹配成功的子设备才是真正需要操作的设备。
按照I2C标准,主设备发起通信时先发送一个起始信号,之后发送的第一个字节就是子设备的设备地址。需要注意的是。设备地址本身只占7个比特,最后一个比特所代表的是之后的数据流向。 0代表主发从收,通常描述为写, 1表示从发主收,通常描述为读。
例如,某个设备的从机地址为0x48(二进制0100 1000b),主机在发送完起始信号之后要发送要发送的从机地址其实是1001 000x,这里x就是数据流向位。如果x为0,表示接下来主机发送数据,从机接收数据,如果x为1,表示接下要求从机发送数据,主机接收数据
I.MX6ULL本身有四路I2C控制器,但是I.MX6ULL-Mini 开发板上只在I2C2控制器上连接了一个触控装置,用于检测用户点击了屏幕的哪个位置。关于触摸屏的操作我们之后再加以说明。而I2C1、 3、4控制器是空置的,我们可以用杜邦线连接我们需要接入的任意传感器。这里我们在I2C1上连接两个传感器AT24C02和LM75为例,作为本次I2C实验内容。
首先是AT24C02,这是一款EEPROM,是一种非易失性存储器。同类型的芯片还有AT24C04,AT24C08,之间的区别仅仅是存储大小不同。既然是一种存储器,那么对其操作无外乎有两种操作,读取和写入操作。这两种操作又同时面临了一个问题,读取和写入的位置。由于AT24C02有256个字节的空间,因此无论读取还是写入,都必须先告诉24C02读取或者写入的位置,即地址。因此,我们不难总结出对24C02的两种操作流程,我们分别加以说明:
接下来讨论从24C02中读取数据,事实上读取数据可以通过两种不同的方式进行,第一种方式是主机先发送设备地址,然后再发送要读取的位置地址。需要注意的是,虽然最终的目的是要从从机那里读取数据,但是由于我们需要先把读取的存储地址发送给从机,因此发送设备地址时我们把数据流向设置为写。发送完存储地址之后,第一种做法是发送停止位,然后重新启动通信,这次我们把发送设备地址时的数据流向设置为读,然后就顺序读取若干字节
第一种方式。这种读从机方式需要两次通信才行。大多数情况下我们并不采用这种方式,而是采用第二种方式,形式于此类似,不同之处仅在于第一次通信之后不发停止位,而是立即重新发送从机地址并标记数据流向为读:
上图就是完整的第二种方式的时序,可见这种方式在发送完写入地址之后并未结束通信,而是重新发送起始信号并改变数据流量,因此这种方式效率更高。需要注意的是,大多数I2C芯片都支持两种方式,但是在读取到最后一个字节的时候,注意必须回复NACK,否则可能会导致从机通信异常。
I.MX6U 提供了 4 个 I2C 外设,通过这四个 I2C 外设即可完成与 I2C 从器件进行通信I.MX6U的 I2C 支持两种模式:标准模式和快速模式,标准模式下 I2C 数据传输速率最高是 100Kbits/s,在快速模式下数据传输速率最高为 400Kbits/s。
先介绍一下跟I2C相关的寄存器,首先看一下 I2Cx_IADR(x=1~4)寄存器,这是I2C 的地址寄存器, ADR(bit7:1)位有效,用来保存 I2C 从设备地址数据。当我们要访问某个 I2C 从设备的时候就需要将其设备地址写入到 ADR 里面。
寄存器 I2Cx_IFDR 也只有 IC(bit5:0)这个位,用来设置 I2C 的波特率, I2C 的时钟源可以选择IPG_CLK_ROOT=66MHz,通过设置 IC 位既可以得到想要的 I2C 波特率。需要注意的是不像其他外设的分频设置一样可以随意设置,手册第1464页给出了I2Cx_IFDR[bit5:0]为不同的值时的分频值。比如现在 I2C 的时钟源为 66MHz,我们要设置I2C 的波特率为 100KHz,那么IC 就可以设置为 0X15,也就是 640 分频。 66000000/640=103.125KHz≈100KHz。
寄存器 I2Cx_I2CR 的各位含义如下:
• IEN(bit7): I2C 使能位,为 1 的时候使能 I2C,为 0 的时候关闭 I2C;
• IIEN(bit6): I2C 中断使能位,为 1 的时候使能 I2C 中断,为 0 的时候关闭 I2C 中断;
• MSTA(bit5):主从模式选择位,设置 IIC 工作在主模式还是从模式,为 1 的时候工作在主模式,为 0的时候工作在从模式;
• MTX(bit4):传输方向选择位,用来设置是进行发送还是接收,为 0 的时候是接收,为 1 的时候是发送;
• TXAK(bit3):传输应答位使能,为 0 的话发送 ACK 信号,为 1 的话发送 NO ACK 信号;
• RSTA(bit2):重复开始信号,为 1 的话产生一个重新开始信号。寄存器 I2Cx_I2SR 的各位含义如下:
• ICF(bit7):数据传输状态位,为 0 的时候表示数据正在传输,为 1 的时候表示数据传输完成;
• IAAS(bit6):当为 1 的时候表示 I2Cx_IADR 寄存器中的地址是从设备地址。为0表示I2Cx_IADR是自己的地址;
IBB(bit5): I2C 总线忙标志位,当为 0 的时候表示 I2C 总线空闲,为 1 的时候表示 I2C 总线忙;
• IAL(bit4):仲裁丢失位,为 1 的时候表示发生仲裁丢失。仲裁丢失在手册第1455页有说明,如果多个设备同时尝试连接总线,则其中一个成为主设备。硬件会立即将仲裁失败的设备切换到Slave
Receive模式 。那么仲裁失败的设备就会产生仲裁丢失,导致此位置位。需要理解的是这种情况一定发生在发送起始位的时候,也就是说在发送完起始位之后应该判断此位是否为1;
• SRW(bit2):从机读写状态位,当 I2C 作为从机的时候使用,此位用来表明主机发送给从机的是读还是写命令。为 0 的时候表示主机要向从机写数据,为 1 的时候表示主机要从从机读取数据;
• IIF(bit1): I2C 中断挂起标志位,当为 1 的时候表示有中断挂起,此位需要软件清零;
• RXAK(bit0):应答信号标志位,无论作为主机还是从机,为 0 的时候表示接收到 ACK 应答信号,为1 的话表示检测到 NO ACK 信号。
最后一个寄存器就是 I2Cx_I2DR,这是 I2C 的数据寄存器,此寄存器只有低 8 位有效,当要发送数据的时候将要发送的数据写入到此寄存器,注意此时LSB代表的是数据流向,需要按照实际情况设置为1或者0;如果要接收数据的话直接读取此寄存器即可得到接收到的数据。
本次实验中我们通过 I.MX6ULL 的 I2C1 来写AT24C02,为完成这个实验,需要大家使用杜邦线外接AT24C02,如下图,我们需要连接4根线:电源、地、 SCL和SDA。查阅AT24C02手册可以看出24C02的供电电压从1.8~5.5V之间,电压越高速度越快,由于I.MX6ULL芯片本身供电是3.3V,所以我们接3.3V电源。查阅I.MX6ULL手册可以看出,该芯片UART4_RX是可以复用I2C1_SDA的, UART4_TX是可以复用I2C1_SCL的,因此24C02的SCL接43号针脚, SDA接SDA针脚。