I2C接口
阅读原文时间:2023年07月08日阅读:2

I2C是一种多向控制总线,它是由PHILIPS公司在二十世纪八十年代初设计出来的,利用该总线可实现多主机系统所需的裁决和高低速设备同步等功能,是一种高性能的串行总线。I2C总线只用两根双向传输线就可以将128个不同的设备互连到一起。这两根线一根是时钟线SCL,一根是数据线SDA。外部硬件只需要接两个上拉电阻,每根线上一个。所有连接到总线上的设备都有自己的地址。

I2C总线上传输的数据是通过在时钟线(SCL)高电平期间所对应的数据线(SDA)上的电平来判别的。在SCL线拉高期间对应到SDA线的电平,如果为高则这位数据为1,反之则为0。只有在SCL线为低电平期间,SDA线才可以更新下一位数据。

除了传送的数据以外,I2C总线在每一帧数据传送之前,还会有一个启动信号,以通知从机准备接收数据。在数据传送结束之后,也会有一个停止信号,以通知从机数据传输结束。在SCL为高电平期间,若对应的SDA线上有一个由高变低的电平下降沿,表示这是一个启动信号。同样,在SCL为高电平期间,若对应的SDA线上有一个由低变高的电平上升沿,表示这是一个停止信号。当已经有一个启动信号之后,在没有停止信号出现之前若再次出现启动信号,则表示该信号是一个重新启动信号,它主要用于在主机不放弃总线控制的情况下启动新的传送。

在启动信号之后紧接着的是地址帧,所有的地址包均为9位,包括7位地址位、1位READ/WRITE控制位(即方向位,表明是主机写从机还是从机写主机)与1位应答位。如果READ/WRITE为1,则执行读(从机写主机)操作;否则执行写(主机写从机)操作。从机被寻址后,必须在第九个SCL(ACK)周期通过拉低SDA作出应答。

地址帧发送后,紧接着就要发送数据帧。所有在I2C总线上传送的数据包长度为9位,包括8位数据位及1位应答位。在数据传送中,主机产生时钟及START与STOP状态,接收器响应接收。应答是由从机在第9个SCL周期拉低SDA实现的,如果接收器在第9个SCL周期使SDA为高,则发出的是NACK信号。NACK信号是接收器在完成了最后数据的接收,或者由于某些原因无法接收更多数据时,才在收到最后字节后发出去通知发送器的。

I2C总线上一个完整的传输过程将包含地址包和数据包。发送主要由START状态、SLA+R/W、至少一个数据包及STOP状态组成。一个典型的数据传送的过程可用下图来描述。

LPC824在硬件上完整支持I2C接口规范,并配有4个I2C接口(具体引脚取决于开关矩阵SWM的配置),它们具有以下特性。

(1)独立的主机、从机和监控器功能。
(2)支持多主机和带从机功能的多主机。
(3)硬件支持多个I2C从机地址。
(4)可以通过一个位屏蔽或一个地址范围选择性验证一个从机地址,从而响应多个I2C总线地址。
(5)通过软件辅助支持10位寻址。
(6)支持SMBus。
(7)支持I2C总线规格达到超快速模式(高达1兆赫)。

LPC824提供一个基于片上ROM的I2C API,以配置和操作I2C接口。

下图是I2C接口的功能框图。

在LPC824中,一共有四组I2C接口,分别为I2C0/1/2/3。I2C0组接口引脚是固定的(PIO0_10和PIO0_11),通过开关矩阵使能,支持超快速模式。I2C1/2/3这三组接口的引脚都是可移动的,可被分配至任何引脚。除PIO0_10和PIO0_11引脚以外,其他组的引脚不是开漏引脚,也不支持超快速模式,所有的引脚均支持400 kHz比特率。下表给出了这些引脚各自的SWM配置寄存器。

从上表中可以看出,I2C0接口的引脚是固定的,通过PINENABLE0寄存器来使能(详见“开关矩阵SWM”一章)。其他三组I2C接口的共8个引脚可以被分配到任意一个物理引脚上,涉及到PINASSIGN9、PINASSIGN10共2个配置寄存器,接下来就分别给出这两个寄存的具体结构。

下表给出的是引脚分配寄存器PINASSIGN9的全部位结构,其字节地址为0x4000C024。

(1)第0到7位为SCT_OUT5功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(2)第8到15位为I2C1_SDA功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(3)第16到23位为I2C1_SCL功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(4)第24到31位为I2C2_SDA功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。

下表给出的是引脚分配寄存器PINASSIGN10的全部位结构,其字节地址为0x4000C028。

(1)第0到7位为I2C2_SCL功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(2)第8到15位为I2C3_SDA功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(3)第16到23位为I2C3_SCL功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。
(4)第24到31位为ADC_PINTRIG0功能分配引脚,可选范围从PIO0_0到PIO0_28一共29根引脚,默认为未分配状态。

下表给出了I2C接口用到的全部寄存器描述。

由于LPC824的I2C接口功能很完善,所以涉及到的寄存器较多,它一共使用了18个寄存器来进行控制,应用上有些复杂。下面给出了上述寄存器对应的结构体定义。

typedef struct {
__IO uint32_t CFG;
__IO uint32_t STAT;
__IO uint32_t INTENSET;
__O uint32_t INTENCLR;
__IO uint32_t TIMEOUT;
__IO uint32_t CLKDIV;
__I uint32_t INTSTAT;
__I uint32_t RESERVED0;
__IO uint32_t MSTCTL;
__IO uint32_t MSTTIME;
__IO uint32_t MSTDAT;
__I uint32_t RESERVED1[5];
__IO uint32_t SLVCTL;
__IO uint32_t SLVDAT;
__IO uint32_t SLVADR0;
__IO uint32_t SLVADR1;
__IO uint32_t SLVADR2;
__IO uint32_t SLVADR3;
__IO uint32_t SLVQUAL0;
__I uint32_t RESERVED2[9];
__I uint32_t MONRXDAT;
} LPC_I2C0_Type;

为了将4个I2C的基址指针强制转换为上述结构体,还要加上下面的定义。

#define LPC_I2C0_BASE 0x40050000UL
#define LPC_I2C1_BASE 0x40054000UL
#define LPC_I2C2_BASE 0x40070000UL
#define LPC_I2C3_BASE 0x40074000UL
#define LPC_I2C0 ((LPC_I2C0_Type *) LPC_I2C0_BASE)
#define LPC_I2C1 ((LPC_I2C0_Type *) LPC_I2C1_BASE)
#define LPC_I2C2 ((LPC_I2C0_Type *) LPC_I2C2_BASE)
#define LPC_I2C3 ((LPC_I2C0_Type *) LPC_I2C3_BASE)

I2C接口涉及到的寄存器较多,后面会对它们进行具体分析。

--待续--

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器