听了这么多理论,依旧没学会 I2C?

关键字 :I2C
一、I2C 基础知识

I2C 总线是由 Philips 公司开发的一种简单、双向二线制同步串行总线。它只需要两根线 SDA 、SCL 即可在连接于总线上的器件之间传送信息,I2C 总线数据传输速率在标准模式下可达 100kbit/s,快速模式下可达 400kbit/s,高速模式下可达 3.4Mbit/s,在超高速模式下可达到 5Mbit/s。

1. I2C 主要特点

    (1)简单的双向两线总线(漏极开路模式):

    (2)串行数据(SDA)串行时钟(SCL)

    (3)带仲裁功能的多主机的总线

    (4)总线上的每个设备都具有不同的识别地址

    (5)每次数据传输都是由主机发起,且时钟总是由主机提供

2. I2C 硬件框图

    (1)I2C 支持带仲裁功能的多设备通信,在一条总线上可以挂载多个 I2C 外设

     (2)I2C 两条总线为漏极开路结构,需要外接上拉电阻




3. I2C 数据通讯

3.1 I2C 总线协议

    I2C 总线由起始信号、停止信号、应答信号、非应答信号组成,如图 1.4.1 所示:

    起始信号:当时钟线 SCL 为高期间,数据线 SDA 由高到低的跳变

    停止信号:当时钟线 SCL 为高期间,数据线 SDA 由低到高的跳变

    应答信号(ACK):应答位为低电平时,规定为有效应答位,表示接收器已经成功接收该字节;

    非应答信号(NACK):应答位为高电平时,规定为非应答位,一般表示接收器接收该字节没有成功

数据有效性:SCL 在高电平期间,SDA 上的数据必须保持稳定,只有在 SCL 为低电平期间,SDA 状态才允许变化。


3.2 I2C 总线的操作

    对 I2C 总线的操作实际就是主从设备之间的读写操作。大致可分为以下二种操作情况:

    1. 主设备往从设备中写数据,如图 1.4.3 所示

    2. 主设备从从设备中读数据,如图 1.4.3 所示

4. I2C 时钟同步

    由于总线具有线“与”的逻辑功能,当多个节点同时发送时钟信号时,在总线上表现的是统一的时钟信号,只要有一个节点发送的是低电平,总线上表现为低电平,只有当所有节点都发送高电平时,总线才表现为高电平,由此可知总线时钟取决于低电平周期最长的节点时钟。这就是 SCL 的同步原理,如图 4.5 所示


5. I2C 仲裁

    (1)I2C 仲裁:在多节点的 I2C 通信中,为解决两个或两个以上节点同时向一条总线发送数据形成的冲突,需要进行 I2C 总线仲裁。

    (2)仲裁机制:根据总线线“与”逻辑原理,当有一个节点发送低电平时,总线上表现为低电平,而发送高电平的节点将会失去仲裁。

    (3)以图 4.6 两个节点为例,DATA1 和 DATA2 分别是节点向总线所发送的数据信号,SDA 为总线上所呈现的数据信号,SCL 是总线上所呈现的时钟信号

              起始:DATA 1 和 DATA 2 发送起始信号,DATA 1 和 DATA 2 为高电平,根据总线线“与”功能,总线为高电平,DATA 1、DATA 2 与 总线电平相同,继续发送数据。

              第一个时钟周期:DATA1 和 DATA 2 为高电平,总线为高电平,DATA 1、DATA 2 继续发送数据。

              第二个时钟周期:DATA1 和 DATA 2 为低电平,总线为低电平,DATA 1、DATA 2 继续发送数据。

              第三个时钟周期:DATA1 为高电平,DATA2 为低电平,SDA 总线为低电平,DATA1 继续发送数据,DATA 2 与 SDA 总线电平不同失去仲裁。



二、LPC824 I2C 性能概述

1. 性能概述

    (1)支持数据速率 400 Kbit/s 的标准模式和高达 1Mbit/s 的快速模式

    (2)独立的主机、从机和监视器功能

    (3)硬件中支持多个 I2C 从机地址

    (4)支持 SMBus

    (5)片上 ROM 提供 I2C 驱动

    (6)收发支持 DMA

    (7)支持低功耗模式唤醒

2. I2C0 与 I2C1/2/3 异同

3. I2C 时钟框图

    I2C 的时钟由 system clock、AHB 时钟控制寄存器、时钟分频寄存器、SCL 主机时间寄存器四部分组成

4. I2C 功能框图

三、LPC824 I2C 具体应用操作

    LPC824 I2C 具体应用操作可分为 8 种:时钟配置、IO 配置、地址配置、主从机功能配置、主机功能初始化、主机数据传输、主机中断处理、从机功能初始化、从机中断处理

1. 时钟配置

1.1 I2C 的 AHB 时钟使能
   
1.2 I2C 的时钟分频寄存器

1.3 I2C 的时钟 SCL 主机时间寄存器

1.4 波特率计算

2.  IO 配置
2.1 I2C 的管脚分配

2.2 I2C 的管脚配置

3. 地址配置

3.1 从机地址寄存器


3.2 从机地址限定寄存器



4. 主从功能配置   



5. 其它寄存器一览



6. I2C 主机功能初始化



7. I2C 主机数据传输



8. I2C 主机中断处理



9. I2C 从机功能初始化



10. I2C 从机中断处理



11. 监测功能

    (1)监测功能用于监听 I2C 总线数据传输

    (2)操作配置寄存器使能监测功能

    (3)读取 MONRXDAT 寄存器,获取 I2C 总线数据传输信息



12. DMA 应用

    (1)I2C 被设置为主机或从机模式,都可以使用 DMA 进行数据收发

    (2)需要软件来确认地址传输

    (3)使用 DMA 模式,需要配置 DMA 控制器相关寄存器

    (4)DMA 请求



四、LPC824 I2C 低功耗模式唤醒

1. 低功耗模式唤醒

    Sleep 模式下,任何触发 I2C 中断的信号都可以唤醒芯片。相关配置如下:




2. 低功耗模式唤醒

    Deep_Sleep/Power_down 模式下,只能支持 I2C 从机模式的唤醒(因为 I2C 时钟被关闭)。相关配置如下:



Start logic 1 interrupt wake-up enable register

 

五、LPC824 I2C 主从机通信实验


1. 实验目的:

    通过本实验,理解和掌握 I2C 配置和用法。

2. 实验软/硬件环境搭建:

    − 硬件:LPC824Lite-V1.0(评估板)

    − 软件:SDK 从 NXP 官网下载(https://mcuxpresso.nxp.com/en/select);

       工程位置:

        ..\..\..\driver_examples\i2c\interrupt_b2b_transfer\master\mdk\lpc_i2c_interrupt_b2b_transfer_master.uvprojx

        ..\..\..\driver_examples\i2c\interrupt_b2b_transfer\slave\mdk\lpc_i2c_interrupt_b2b_transfer_master.uvprojx

3. 实验描述:

    本实验中以 I2C0 为例,一个板子作为主机,将另一个板子作为从机,主机发送数据给从机,从机接收数据并发送给主机,串口助手上可看到主从的收发数据。

4. 实验结果:

    上电之前将两个板子的 SDA 和 SCL 相连,按下复位键,在串口助手上可以看到 master 及 slave 的收发打印信息。
 
5. 软件设计

5.1 使能 I2C 时钟

    /* Enable clock of i2c0. */

    CLOCK_EnableClock(kCLOCK_I2c0);//使能 I2C 时钟

 

    通过 SYSAHBCLKCTRL 寄存器使能 I2C 时钟,具体函数实现如图 5.1 所示

5.2 IO 配置

    BOARD_InitPins();              //IO 配置

    具体函数实现如上图所示:

5.3 master 配置

(1)master 初始化

    masterConfig.enableMaster  = true;           //使能 Master

    masterConfig.baudRate_Bps  = 100000U;      //设置波特率 100K

    masterConfig.enableTimeout = false;           //不使能 Timeout

    I2C_MASTER_CLOCK_FREQUENCY=12000000;   //master 时钟

                

    /* Initialize the I2C master peripheral */

    I2C_MasterInit(EXAMPLE_I2C_MASTER, &masterConfig, I2C_MASTER_CLOCK_FREQUENCY);//初始化 I2C




    I2C 的角色为 Master,波特率为 100K,没有 Timeout 功能,I2C_MasterInit 具体函数配置实现如图 5.3.1 所示



    (2)创建中断回调函数

     /* Create the I2C handle for the non-blocking transfer */

    I2C_MasterTransferCreateHandle(EXAMPLE_I2C_MASTER, &g_m_handle, i2c_master_callback,

 

    I2C_MasterTransferCreateHandle具体函数实现如图 5.3.2 所示



    (3)master 发送一次数据

    /* subAddress = 0x01, data = g_master_txBuff - write to slave.

          start + slaveaddress(w) + subAddress + length of data buffer + data buffer + stop*/

        uint8_t deviceAddress     = 0x01U;

        masterXfer.slaveAddress   = I2C_MASTER_SLAVE_ADDR_7BIT;     //从机地址

        masterXfer.direction      = kI2C_Write;                      //I2C 写模式

        masterXfer.subaddress     = (uint32_t)deviceAddress;          //子地址

        masterXfer.subaddressSize = 1;                              //子地址大小

        masterXfer.data           = g_master_txBuff;                //发送数据 buff

        masterXfer.dataSize       = I2C_DATA_LENGTH;              //发送数据 buff 大小

        masterXfer.flags          = kI2C_TransferDefaultFlag;               //传输以起始信号开始,以停止信号结束

        /* Send master non-blocking data to slave */

       reVal = I2C_MasterTransferNonBlocking   (EXAMPLE_I2C_MASTER, &g_m_handle, &masterXfer);//发送一次数据

 

    I2C_MasterTransferNonBlocking 具体函数实现如图 5.3.3 所示

   5.4 slave 配置

    (1)slave 初始化

        /* Set up i2c slave */

        slaveConfig.enableSlave             = true;//使能 slave

        slaveConfig.address1.addressDisable = true;//address1 使能

        slaveConfig.address2.addressDisable = true;//address2 使能

        slaveConfig.address3.addressDisable = true;//address3 使能

        /* Change the slave address */

        slaveConfig.address0.address = I2C_MASTER_SLAVE_ADDR_7BIT;//设置主机地址

 

        /* Initialize the I2C slave peripheral */

        I2C_SlaveInit(EXAMPLE_I2C_SLAVE, &slaveConfig, I2C_SLAVE_CLOCK_FREQUENCY);//初始化 I2C


        I2C_SlaveInit 具体函数实现如图 5.4.1 所示


    (2)创建中断回调函数

        /* Create the I2C handle for the non-blocking transfer */

    I2C_SlaveTransferCreateHandle(EXAMPLE_I2C_SLAVE, &g_s_handle, i2c_slave_callback, NULL);//创建中断回调函数

 

    I2C_SlaveTransferCreateHandle 具体函数实现如图 5.4.2 所示

 

    (3)接收一次数据

    /* Start accepting I2C transfers on the I2C slave peripheral */

        reVal = I2C_SlaveTransferNonBlocking(EXAMPLE_I2C_SLAVE, &g_s_handle,

    kI2C_SlaveAddressMatchEvent | kI2C_SlaveCompletionEvent);//读一次数据



    I2C_SlaveTransferCreateHandle 具体函数实现如图 5.4.3 所示   

 








 

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★博文作者未开放评论功能