I2C总线

I2C作为常用的通讯外设,广泛应用在各种通讯场合,而且也衍生各种变体协议,比如SCCB,SMbus,PMbus等等。先楫半导体在I2C这个通讯外设上,每个传输的阶段都可以独立自由去控制,这也极大得提高了开发的自由灵活度,而且也可以随性发挥生成I2C的变体协议,而不需要去进行IO模拟。

首先介绍一下先楫半导体I2C的一些主要特性和功能,方便后续说明,大家也可以到官网参考先楫用户手册。

1、I2C 特征

  • 支持标准模式 (100Kb/s),快速模式 (400Kb/s) 和快速模式 +(1Mb/s)

  • 可配置主从模式

  • 支持 7 位和 10 位地址模式

  • 支持广播呼叫地址 (general call address)

  • 自动时钟延展 (clock stretching)

  • 可配置的时钟/数据时序

  • 支持直接内存访问 (DMA)

  • 4 字节 FIFO

2、I2C 功能

  • 每个传输由 4 个阶段组成:起始,地址,数据和结束。在起始阶段会产生 START 操作,在地址阶段发送地址,在数据阶段 1 个或多个数据字节被传送,在结束阶段产生 STOP 操作。每个阶段都能够独立控制是否执行

  • 4个字节FIFO,可不使用DMA的情况下,满足多字节一次性传输。并且软件没有准备好下一个字节的收发数据或者FIFO已满时候,I2C控制器会自动延展I2C总线时钟来暂停总线传输。

  • I2C控制器默认使能了自动ACK响应,即是除了最后一个字节外其余字节接收后都会自动发出ACK,软件可以使能字节接收中断来禁止自动响应功能,软件自己接收后决定是否发送ACK。

3、场合需求

在某些场合,当I2C作为主机的时候,一次数据量传输当中,可能会有以下的需求方式:

  • 传输过程中间变化读写方向,比如START操作到第一个数据字节传输是写,后面变为读。或者读变成写。

  • 传输过程中分三次传输,START,数据,STOP传输。比如第一次传输需要带START,但不需要STOP。

  • 传输过程中需要restart重新发送start信号。

举例,比如SMBUS,在进行block read传输中,就需要传输过程中发送restart信号,并且切换读写方向。

1.png

4、实现方式

先楫半导体的用户手册对于 I2C 的寄存器说明一共有好几个,本文重点介绍以下三个密切相关的寄存器:

1. CTRL寄存器:该寄存器是用来配置一次传输中的每个阶段的控制,比如主机模式下,方向是发送,在START开始后,STOP结束前,传输的是数据段,可以不发START,地址,STOP。那么可以对其寄存器的对应位进行开启和关闭。

2.png

3.png

2. INTEN寄存器的BYTERECV位,开启或关闭自动响应功能。

4.png

3. CMD寄存器:定义的是对一次transaction的相关操作。比如主机在接收到从机的数据,需要不接受数据了,可以发送一个NACK响应。前提是关闭了自动响应功能。

5.png

6.png

根据以上的寄存器说明,在新的sdk版本V1.2.0中,我们在SDK的i2c driver中看到有定义一个顺序传输接口,定义一个枚举,分别表示第一帧,中间帧,最后一帧。

/** 
    * @brief I2c sequential transfer options 
    * @arg: i2c_frist_frame: has start signal 
    * @arg: i2c_next_frame: middle transfer 
    * @arg: i2c_last_frame: has stop signal 
*/ 
typedef enum i2c_seq_transfer_opt 
{ 
    i2c_frist_frame = 0, 
    i2c_next_frame, 
    i2c_last_frame, 
} i2c_seq_transfer_opt_t;

对于发送接口,sdk1.2也提供了i2c_master_seq_transimit 这个 API。

7.png

对于接收接口,sdk1.2也提供了i2c_master_seq_receive这个API,从内部API可以看出是关闭自动响应,软件控制一次传输的ACK和NACK,避免STOP未出现时出现数据断开。

8.png

5、验证功能

根据以上信息,我们来操作一个实验,以sdk的poll例子的master和slave两个开发板进行相互收发,slave不做改动,master的读写接口替换以上的接口。

int main(void) 
{ 
    hpm_stat_t stat; 
    i2c_config_t config; 
    uint32_t freq; 
    board_init(); 
    init_i2c_pins(TEST_I2C); 
    config.i2c_mode = i2c_mode_normal; 
    config.is_10bit_addressing = false; 
    freq = clock_get_frequency(TEST_I2C_CLOCK_NAME); 
    stat = i2c_init_master(TEST_I2C, freq, &config); 
    if (stat != status_success) { 
        return stat; 
    } 
    printf("I2C polling master example\n"); 
    prepare_tx_data(); 
    uint32_t index = 0; 
    uint32_t inc_len = 30; 
    if (status_success != i2c_master_seq_transmit(TEST_I2C, TEST_I2C_SLAVE_ADDRESS, &tx_buff[index], inc_len, i2c_frist_frame)) 
    { 
        printf("Master transfer frist frame failed\n"); 
        while (1) {         
        } 
    } 
    index += inc_len; 
    if (status_success != i2c_master_seq_transmit(TEST_I2C, TEST_I2C_SLAVE_ADDRESS, &tx_buff[index], inc_len, i2c_next_frame)) 
    { 
        printf("Master transfer next frame failed\n"); 
        while (1) { 
        } 
    } 
    index += inc_len; 
    inc_len = (sizeof(tx_buff) - (inc_len * 2)); 
    if (status_success != i2c_master_seq_transmit(TEST_I2C, TEST_I2C_SLAVE_ADDRESS, &tx_buff[index], inc_len, i2c_last_frame)) 
    { 
        printf("Master transfer last frame failed\n"); 
        while (1) { 
        } 
    } 
    /* wait for slave controller to be ready to send data */ 
    board_delay_ms(100); 
    index = 0; 
    inc_len = 30; 
    if (status_success != i2c_master_seq_receive(TEST_I2C, TEST_I2C_SLAVE_ADDRESS, &rx_buff[index], inc_len, i2c_frist_frame)) 
    { 
        printf("Master transfer read frist frame failed\n"); 
        while (1) { 
        } 
    } 
    index += inc_len; 
    if (status_success != i2c_master_seq_receive(TEST_I2C, TEST_I2C_SLAVE_ADDRESS, &rx_buff[index], inc_len, i2c_next_frame)) 
    { 
        printf("Master transfer read next frame failed\n"); 
        while (1) { 
        } 
    } 
    index += inc_len; 
    inc_len = (sizeof(tx_buff) - (inc_len * 2)); 
    if (status_success != i2c_master_seq_receive(TEST_I2C, TEST_I2C_SLAVE_ADDRESS, &rx_buff[index], inc_len, i2c_last_frame)) 
    { 
        printf("Master transfer read last frame failed\n"); 
        while (1) { 
        } 
    } 
    check_transfer_data(); 
    while (1) { 
    } 
    return 0; 
}

实验现象

① 当把一次完整传输拆分三次frame传输时候,依旧是没什么问题的。可见以上的功能使用并没有什么问题。

9.png

② 可以模拟下一个配置错误的现象,开启auto-ack功能,master接收slave数据的数据,由于开启了自动响应,在第一包frame接收的时候,I2C控制器认为传输到最后一个字节,会自动补充NACK,但我们并不希望补充NACK,因为一次完整的传输还没完成,这时候就需要软件自己添加ACK或者NACK。

10.png

6、小 结

对于I2C,无论是poll方式,还是中断方式,还是DMA方式,先楫的I2C控制器对于I2C传输的每个阶段都是可控的,这为开发者的应用需求也极大提高软件灵活度。

来源:先楫半导体HPMicro

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

围观 58

国内领先的信号链芯片及其解决方案提供商苏州纳芯微电子股份有限公司(以下简称“纳芯微”)日前宣布推出五款I2C总线接口类芯片产品,适用于各种工业、企业和消费类应用中的控制总线设计,例如安防、电力电子、个人电脑、企业交换机、服务器等领域。该系列新产品包括I2C/SMBus通用总线I/O扩展器NCA9555、I2C/SMBus热插拔缓冲器NCA9511、四通道I2C/SMBus多路复用器NCA9545、I2C/SMBus双路双向缓冲器NCA9617以及I2C/SMBus电平转换器NCA9306,这五款芯片可在-40℃至85℃的宽温工作范围内稳定运行,闩锁性能超过100mA,均符合JESD78II类规范,兼容绝大部分MCU I/O电平,提高系统集成度,并带来更优的性能和更低的成本。

NCA9xxx系列产品可以为工程师提供最大的控制总线设计灵活性。伴随物联网等应用的发展,系统设计复杂度在持续增加,多个主设备和大量终端设备往往存在于一个系统中,多设备之间互连所导致的超长走线进一步影响增加控制总线布局难度,也带来更多信号完整性的挑战,NCA9xxx提供了应对这些挑战的理想解决方案。利用NCA9xxx系列芯片,工程师不但能让系统满足功能拓展需求,还能简化电路设计从而改善信号完整性与EMI,最终有效节省开发时间并降低系统总成本。

NCA9xxx全兼容市场主流I2C接口类芯片,用户无需修改设计就可以直接更换,降低成本并提高性能,帮助客户应对因国际贸易纠纷而导致的供应风险。

纳芯微首席执行官王升杨表示:“I2C是当前最通用的设备管理总线,应用广泛,开发成本低,广受工程师喜爱。NCA9xxx系列I2C接口产品满足工业级温度要求,兼容市面大部分MCU的接口电平,完全满足系统开发中对I2C总线的功能与性能需求。该系列产品从设计、制造到封装测试全部实现国产化,确保供应的安全与可靠。此外,纳芯微还提供灵活的库存管理机制,以更好地满足国内客户的交付需求。”

纳芯微NCA9xxx I2C接口产品系列采用业界通用的小型封装, 包括TSSOP24、MSOP8、SOP8、TSSOP20、TSSOP16等,具体型号的封装形式可至官网查看或发邮件至sales@novosns.com 索取产品规格书。

附录:NCA9xxx系列产品信息

NCA9555: 具有中断输出和可配置寄存器的16 位 I2C 和 SMBus I/O 扩展器

产品特点:

  • I2C 至并行端口扩展器
  • 16 GPIO 端口, 默认输入
  • 工作电压2.3~5.5V
  • 3地址引脚,支持8个不同地址
  • 开漏电路低电平有效中断输出
  • 可耐受 5V 电压的 I/O 端口
  • 兼容大多数微控制器
  • 400kHz 快速 I2C 总线
  • 极性反转寄存器
  • 具有最大高电流驱动能力的锁存输出,可用于直接驱动 LED
  • 锁断性能超过 100mA

NCA9555是一款24针CMOS器件,可为I2C总线应用提供16位通用并行输入/输出(GPIO)扩展。当ACPI电源开关,传感器,按钮,LED,风扇等需要额外的I/O时,它提供了一种简单的解决方案,实现低至0.25uA的待机功耗。

NCA9511:热插拔I2C总线和SMBus缓冲器

产品特点:

  • 支持 I2C 总线信号双向数据传输
  • 工作电源电压范围为 2.3V 至 5.5V
  • TA 环境空气温度范围-40°C 至 105°C
  • 对所有 SDA 和 SCL 线路的 1V 预充电可防止带电板插入过程中发生损坏
  • 可适应标准模式及快速模式 I2C 器件
  • 支持时钟展宽、仲裁及同步
  • 断电高阻抗 I2C 引脚

NCA9511是一款可热插拔的I2C总线缓冲器,支持将I/O卡插入带电背板,而不会损坏数据和时钟总线。控制电路可防止背板侧I2C线(输入)连接到卡侧I2C线(输出),直到背板上发生停止命令或总线空闲状态而卡上没有总线争用为止。建立连接后,该设备将提供双向缓冲,从而使背板和卡的电容保持分离。在插入过程中,SDA和SCL线被预充电至1V,以最大程度地减小为器件的寄生电容充电所需的电流。

NCA9545:具有中断逻辑和复位功能的4 通道 I2C 和 SMBus 多路复用器

产品特点:

  • 4选1 I2C选择器
  • 支持4中断输入,1输出
  • 2地址引脚,支持4个不同地址
  • 0~400K I2C 时钟
  • 电源电压范围2.3V~5.5V
  • 闩锁性能超过JESD78要求的100mA

NCA9545是一款通过I2C总线控制的四路双向转换开关,支持热插拔。串行时钟/串行数据(SCL/SDA)上行对分散到四个下行对,或者通道。根据可编程控制寄存器的内容,可选择任一单独SCn/SDn通道组合。提供四个中断输入(INT3-INT0),每个中断输入针对一个下行对。一个中断(INT)输出可作为四个中断输入的与(AND)操作。

NCA9617:I2C和SMBus双路双向缓冲器

产品特点:

  • 双通道双向缓冲器
  • 支持标准模式/400K/1Mhz I2C模式
  • 0.8V ~ 5.5V到2.2V~5.5V电平转换;
  • VCC掉电时I2C BUS高阻态
  • 闩锁性能超过JESD78要求的100mA

NCA9617是一款专门用于I2C总线和SMBus双路双向缓冲器,支持标准模式、快速模式(400kHz)和快速模式+(1MHz)。 此器件可在混合应用中提供低电压(低至0.8V)和较高电压(2.2V至5.5V)间的双向电压电平转换(上行转换模式和下行转换模式)。电平转换期间,在不损失系统性能的情况下可扩展I2C和相似的总线系统。

NCA9306:2 位双向 I2C 总线和 SMBus 电平转换器

产品特点:

  • 双通道双向电平转换
  • 可实现以下电压之间的电压电平转换
  • 1.2V to 1.8V/2.5V/3.3V/5V
  • 1.8V to 2.5V/3.3V/5V
  • 2.5V to 3.3V/5V
  • 3.3V to 5V
  •  0~1Mhz I2C 时钟
  • 漏极开路I2C I/O端口
  • 闩锁性能超过JESD78要求的100mA

NCA9306器件是一款采用使能(EN)输入的双路双向I2C和SMBus电压电平转换器,可以在1.2V到5V之间实现双向电压转换而无需使用方向引脚。 此开关具有低导通状态电阻(RON),最大传播延迟小于1.5ns,可以在最短传播延迟情况下建立连接。当EN为高电平时,转换器开关打开,并且SCL1和SDA1 I/O被分别连接至SCL2和SDA2 I/O,从而实现端口间的双向数据流。当EN为低电平时,转换器开关关闭,在端口之间存在一个高阻抗状态。除了电压转换,在快速模式通信过程中控制EN引脚以断开较慢总线的连接,NCA9306器件还可用于将400kHz总线与100kHz总线隔离开。

关于纳芯微

苏州纳芯微电子股份有限公司是国内领先的信号链芯片及其解决方案提供商,聚焦传感器与数字隔离两大产品方向。纳芯微电子专注于高性能集成电路芯片的设计、开发、生产和销售,为客户提供一站式系统解决方案。如需了解更多信息,敬请访问www.novosns.com

围观 757
订阅 RSS - I2C总线