MCU微课堂 | CKS32K148 LPI2C

LPI2C(Low Power Inter-Integrated Circuit)是CKS32K148微控制器中的一个低功耗I2C接口模块。CKS32K148款MCU存在LPI2C0、LPI2C1两个LPI2C,支持标准模式(100 kbps)、快速模式(400 kbps)、快速+模式(1Mbps)和高速模式(3.4 Mbps)通信速率。

主要特性

兼容性:支持 I2C 总线标准模式、快速模式、快速+模式、从机模式下的高速模式 (HS)。

低功耗:支持低功耗模式。

多主模式:支持多主操作,包括同步和仲裁机制。

中断和 DMA 支持:提供中断和 DMA 支持,减少 CPU 负载。

可配置性:可配置广播呼叫、7 位或 10 位地址模式。可选择SOSC、SIRC、FIRC、SPLL时钟源,支持时钟延长、时序可通过寄存器灵活配置。

错误检测:支持总线忙检测、仲裁丢失、FIFO错误、端口低电平超时、位错误检测。

主机特性

  • 4字深度的 命令/发送/接收FIFO

  • 命令 FIFO 等待空闲 I2C 总线:在启动传输之前,命令 FIFO 会等待 I2C 总线空闲

  • 命令 FIFO 支持启动(重复)START 和 STOP 条件:可以发起一个或多个主接收器传输

  • STOP 条件可以从命令 FIFO生成,也可在发送 FIFO为空时自动生成

  • 主机请求输入:用于控制 I2C总线传输的启动时间

  • 灵活的接收数据匹配功能:可以在数据匹配时生成中断,并丢弃不需要的数据

  • 标志位和可选中断:用于指示重复 START 条件、STOP 条件、仲裁丢失、意外的 NACK 以及命令字错误

  • 支持可配置的总线空闲超时和引脚低电平超时:增强总线的鲁棒性和可靠性

从机特性

  • 独立的 I2C 从机寄存器:减少因主/从切换带来的软件开销

  • 支持 7 位或 10 位地址、地址范围、SMBus 警报和通用呼叫地址:提供灵活的地址配置和通信功能

  • 发送/接收数据寄存器支持中断或 DMA 请求:便于高效的数据收发

  • 软件可控制的 ACK 或 NACK:支持在 ACK/NACK 位上进行可选的时钟拉伸

  • 可配置的时钟拉伸:避免发送 FIFO 下溢和接收 FIFO 上溢错误

  • 标志位和可选中断:用于指示数据包结束、STOP 条件或位错误检测

主机/从机传输数据

CKS32K148系列MCU的LPI2C框图如下所示:

1.png

图1 LPI2C框图

LPI2C 主机和从机控制器逻辑相互独立,用于在 I2C 总线上分开执行所有主/从模式传输任务。这种独立性使得主/从控制器能够高效地管理总线通信,提高了系统的灵活性和性能。

LPI2C端口

LPI2C在不同外部条件下支持不同端口配置模式,通过MCFGR1[26:24]寄存器配置。

开漏支持:LPI2C主设备默认将SDA和SCL引脚配置为开漏模式。

高速模式支持:高速模式的支持也取决于具体的设备,并且要求SCL引脚支持I2C规范中所需的电流源上拉。

超快速模式支持:LPI2C主设备还支持使用SDA和SCL引脚实现I2C超快速模式所需的仅输出推挽功能。支持超快速模式还需要设置MCFGR1[IGNACK]位。

推挽式双线支持:LPI2C主设备还支持推挽式双线配置,如果LPI2C是唯一的主设备且总线上的所有I2C引脚电压相同,则可以支持部分高速模式。

推挽式四线支持:推挽式4线配置将SCL/SDA引脚用于输入数据;SCLS/SDAS引脚用于输出数据,且极性可配置。注意在使用此四线配置时,LPI2C主设备逻辑和LPI2C从设备逻辑无法连接到单独的I2C总线。

LPI2C主机传输

当LPI2C被启用时,它会持续监控I2C总线,以检测总线是否处于空闲状态(通过MSR[BBF]标志位)。当检测到总线空闲超时(由 MCFGR2[BUSIDLE] 配置)或者STOP条件时,I2C总线将被视为空闲。

在I2C总线空闲后,如果发送 FIFO不为空,并且主机请求被触发或禁用,LPI2C主控制器将启动I2C总线上的传输。这一过程包括以下步骤:

  • 等待总线空闲时间

    等待的时间= (MCCR0[CLKLO] + 1) * 预分频器 (MCFGR1[PRESCALE])。

  • 发送 START 条件和地址字节

    使用主时钟配置寄存器 0 (MCCR0) 中的时序配置发送 START 条件和地址字节;如果配置为高速模式传输,则使用主时钟配置寄存器 1 (MCCR1) 中的时序配置。

  • 执行主发送或主接收传输

    根据发送 FIFO 的配置执行主发送或主接收传输。

  • 在最后一次主接收传输中发送 NACK

    除非发送 FIFO 中的下一个命令也是接收数据命令且发送 FIFO 不为空,否则在最后一次主接收传输中发送 NACK。

  • 发送重复 START 或 STOP 条件

    根据发送 FIFO 和/或 MCFGR1[AUTOSTOP] 的配置发送重复 START 或 STOP 条件。

    当 LPI2C 主控制器被禁用时(无论是由于 MCR[MEN] 被清除还是由于模式进入自动禁用),LPI2C 将继续清空发送 FIFO(在发送 FIFO 为空后,LPI2C 会自动生成 STOP 条件)直到发送 STOP 条件。

LPI2C从机传输

当LPI2C被启用前可对从机的地址进行匹配设置:支持 7 位或 10 位地址模式,地址可以配置匹配范围。

  • 等待主机的 START 条件:从机监控 I2C 总线,等待主机发送 START 条件和从机地址。

  • 地址匹配:如果接收到的地址与从机配置的地址匹配,从机发送 ACK 响应,然后LPI2C从机会自动执行从机发送(slave-transmit)或从机接收(slave-receive)传输。

  • 发送、接收数据:从机通过发送数据寄存器 STDR 发送数据;通过接收数据寄存器SRDR接收主机发送的数据。

  • 处理接收完成:如果检测到 STOP 条件或数据包结束,从机可以触发中断或标志位,通知软件处理接收到的数据。

LPI2C主机时序配置说明

LPI2C通讯时,时序参数必须配置为满足 I2C 规范的要求;这将取决于所支持的模式和 LPI2C 功能时钟频率。以下表格提供了不同模式下寄存器时序配置示例:

表1 寄存器时序配置

2.png

LPI2C主从通讯实例

1. 配置LPI2C时钟

CLOCK_DRV_Init(&clockMan1ffig0);
其中“clockMan1_InitConfig0”中包含对SIRC、FIRC、SOSC、PLL、以及LPI2C外设(在peripheralClockConfig0结构体内)的时钟配置。
peripheral_clock_config_t 
peripheralClockConfig0[NUM_OF_PERIPHERAL_CLO CKS_0] = {
    ...    
    {        
        .clockName = LPI2C1_CLK,        
        .clkGate = true,        
        .clkSrc=CLK_SRC_SIRC_DIV2,//LPI2C的时钟选择:SOSC/SIRC/FIRC/SPLL        
        .frac = MULTIPLY_BY_ONE,        
        .divider = DIVIDE_BY_ONE,    
    }
    ,...
}

2. 配置LPI2C 引脚

PINS_DRV_Init(NUM_OF_CONFIGURED_PINS0, g_pin_mux_InitConfigArr0);
其中“g_pin_mux_InitConfigArr0”内对LPI2C引脚进行配置:
pin_settings_config_t 
g_pin_mux_InitConfigArr0[NUM_OF_CONFIGURED_PINS0] =  {
...    
    {//LPI2C SDA引脚设置        
        .base         = PORTC,        
        .pinPortIdx    = 31U,        
        .pullConfig    = PORT_INTERNAL_PULL_UP_ENABLED,        
        .driveSelect    = PORT_LOW_DRIVE_STRENGTH,        
        .passiveFilter   = false,        
        .mux          = PORT_MUX_ALT4,        
        .pinLock       = false,        
        .intConfig      = PORT_DMA_INT_DISABLED,        
        .clearIntFlag    = false,        
        .gpioBase      = NULL,        
        .digitalFilter   = false,    
    },    
    {//LPI2C SCK引脚设置        
        .base          = PORTE,        
        .pinPortIdx     = 1U,        
        .pullConfig     = PORT_INTERNAL_PULL_UP_ENABLED,        
        .driveSelect     = PORT_LOW_DRIVE_STRENGTH,        
        .passiveFilter   = false,        
        .mux          = PORT_MUX_ALT4,        
        .pinLock       = false,        
        .intConfig      = PORT_DMA_INT_DISABLED,        
        .clearIntFlag    = false,        
        .gpioBase      = NULL,        
        .digitalFilter   = false,    
    }
,...
}

下表显示了LPI2C0、LPI2C1的PIN脚在MCU中的资源分配:

表2 LPI2C0外设引脚复用

3.png

表3 LPI2C1外设引脚复用

4.png

3. LPI2C作为主机收发数据

LPI2C作为主机FAST模式400K速率配置从机地址50,设置参数如下:

lpi2c_master_user_config_t lpi2c1_MasterConfig0 = {  
    .slaveAddress = 50U,//地址配置  
    .is10bitAddr = false,//十位地址配置  
    .operatingMode = LPI2C_FAST_MODE,//模式配置  
    .baudRate = 400000UL,//波特率设置  
    .transferType = LPI2C_USING_INTERRUPTS,//传输方式  
    .dmaChannel = 0U,//若使能了DMA,则DMA设置的通道  
    .masterCallback = NULL,//中断函数  
    .callbackParam = NULL
};
LPI2C_DRV_MasterInit(INST_LPI2C1,&lpi2c1_MasterConfig0,&lpi2c1MasterState);//LPI2C作为主机初始化
LPI2C_DRV_MasterSendDataBlocking(INST_LPI2C1, masterTxBuffer, BUFF_SIZE, true, OSIF_WAIT_FOREVER);//LPI2C作为主机发送数据
while(!((LPI2C1->MSR)&LPI2C_MSR_SDF_MASK))//停止位检测
{
    LPI2C_DRV_MasterReceiveDataBlocking(INST_LPI2C1,masterRxBuffer, BUFF_SIZE, true, OSIF_WAIT_FOREVER);//LPI2C作为主机接收数据
}
  1. LPI2C作为从机收发数据LPI2C作为从机,地址设置50,配置中断接收,设置参数如下:

lpi2c_slave_user_config_t lpi2c1_SlaveConfig0 = 
{  
    .slaveAddress = 50U,//从机地址  
    .is10bitAddr = false,//十位地址配置 
    .operatingMode = LPI2C_FAST_MODE,//模式配置 
    .slaveListening = true,//监听模式  
    .transferType = LPI2C_USING_INTERRUPTS,//中断传输  
    .dmaChannel = 0U,//若配置了DMA,则从机DMA的通道  
    .slaveCallback = lpi2c1_SlaveCallback0,//从机中断函数  
    .callbackParam = NULL
};
LPI2C_DRV_SlaveInit(INST_LPI2C1, &lpi2c1_SlaveConfig0, &lpi2c1SlaveState);//从机初始化中断内进行数据收发:
void lpi2c1_SlaveCallback0(i2c_slave_event_t slaveEvent,void *userData)
{    
    uint32_t instance;    
    instance = (uint32_t)userData;    
    switch(slaveEvent)    
    {       
         case I2C_SLAVE_EVENT_RX_REQ://从机接收数据            
             LPI2C_DRV_SlaveSetRxBuffer(instance,slaveRxBuffer, BUFF_SIZE);           
             break;        
         case I2C_SLAVE_EVENT_TX_REQ://从机发送数据            
             LPI2C_DRV_SlaveSetTxBuffer(instance, slaveTxBuffer, BUFF_SIZE);            
             break;        
         case I2C_SLAVE_EVENT_TX_EMPTY://发送完成        
         case I2C_SLAVE_EVENT_RX_FULL://接收完成            
             break;        
         case I2C_SLAVE_EVENT_STOP:         
         SendOK = true;        
         break;    
     }
}

至此,LPI2C模块简单的主机从机特性及主机从机传输机制讲述完毕。

来源:中科芯MCU

免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。