I2C使用参考


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 04/09/2025

    1. 概述

    1.1 I2C

    I2C,全称Inter-Integrated Circuit,集成电路总线,使用多主从架构,是一种串行、同步、半双工的通信总线,包含串行时钟线(SCL)与串行数据线(SDA),都是双向IO线。通信过程中,时钟信号由主设备全程提供;数据信号取决于主设备是做读操作还是写操作,当进行写操作时,数据信号由主设备提供,当进行读操作时,数据信号由从设备提供。

    1.2 MIIC

    MIIC,即Master IIC device,是SigmaStar提供的专门作为I2C通信主设备的IP,可实现与各种外接的I2C slave device通讯,满足绝大部分I2C通讯协议设备的需求。

    设备节点和硬件组别的关系如下表所示:

    MIIC Group bank addr DEV
    HW MIIC group0 1114H /dev/i2c-0
    HW MIIC group1 1115H /dev/i2c-1
    HW MIIC group2 1116H /dev/i2c-2
    HW MIIC group3 1117H /dev/i2c-3
    HW MIIC group4 1118H /dev/i2c-4
    HW MIIC group5 3EH /dev/i2c-5

    2. 关键字

    dts/dtsi:

    Linux设备树文件,通常用于描述CPU所支持的外设,外设节点中包含的属性值可用于外设的配置。

    padmux:

    引脚复用,用于将模块功能引脚连接到具体的外部引脚上面,打通信号连接。

    open-drain:

    即开漏输出,不输出电压,控制输出低电平时的引脚接地,控制输出高电平时为高阻态,有外部电路负责高电平。

    push-pull:

    即推挽输出,既可以输出低电平,也可以输出高电平。一般由两个参数相同的三极管或MOSFET组成, 有较强的驱动能力。

    3. 功能描述

    3.1 通信协议

    一个完整的I2C通信,应包含:起始信号、从设备地址与读写位、应答信号、任意字节长度的数据以及停止信号。

    起始信号: 一次完整I2C通信的第一个信号,由主设备提供。示意本次通讯开始。电平信号为 - 当SCL为高电平,SDA从高电平拉为低电平。

    从设备地址: 通信从设备的“身份证”,与读写位一起共享address frame。占据高7bit或高10bit。通过主设备发出来的地址来确认自己是否被选中。设备地址可以相同,但如果同时接在同一总线上,很容易导致通讯失败或数据错误。

    读写位: 用于指示当次传输主设备要进行写操作还是读操作,b0为写操作,b1为读操作。与从设备地址一起共享address frame。占据最低位bit0。

    例: 如果从设备地址为7bit的0x50,进行读操作,那么:

    address frame = (0x50 << 1) | 0x01 = 0xA1
    

    应答信号: 数据接收方反馈给发送方的信号,低电平表示接收成功,高电平表示接收失败。接收方可以是主设备也可以是从设备。当主设备在读取数据时,发送完从设备地址之后,就会变成数据的接收方。但是clock信号始终都是由主设备提供的。

    数据: 传输的数据,写操作或者读操作。以字节为单位。另外,一般在I2C通讯写操作时,从设备地址之后会跟随所要读写的从设备寄存器地址,可能是8bit长度,可能是16bit长度,他们也属于传输过程中的数据。

    停止信号: 一次完整通讯的最终信号,由主设备提供。示意本次通讯到此结束。电平信号为 - 当SCL为高电平,SDA从低电平拉为高电平。

    如下为I2C通信协议格式:


    图3-1 I2C通信协议格式

    3.2 功能配置

    功能
    说明
    备注
    FIFO transfer 每个传输信号都需要由CPU来参与,通过写入不同的MIIC寄存器发送不同的信号 采用polling方式,CPU loading会比较大;单次最大传输数据量为8192字节;在每次传输量都比较小的时候建议使用此模式
    DMA transfer 整个通信过程都由MIIC自行动作,仅需要提前填入传输内容,再触发即可;HW MIIC会根据已经填入的时序设定来进行通讯 采用中断方式,CPU loading会比FIFO mode小;单次最大传输数据量为4086字节;每次传输量都比较大时建议使用此模式;当传输期间出现错误时HW会立即停止这次通讯,触发中断
    timing 调整 开放了几个I2C通讯时序可供调整,当具体某部分时序不满足从设备要求时,在dtsi节点中调整 可调时序: t-SU-STA, t-HD-STA, t-SU-STO, t-HD-STO, t-SU-DAT, t-HD-DAT
    rate 支持通讯速率区间可调,不分档位,可根据实际需要在dtsi节点或sysfs节点中调整 支持50kHz - 1500KHz,更大速率需求不做保证
    输出方式调整 支持open-drain与push-pull两种输出方式,可在dtsi节点中调整 MIIC不支持任意调整波形的上升/下降沿时间,仅可以通过调整输出方式来改变,且时间无法确认push-pull上升沿时间会较快
    padmux 可配置不同的padmux使总线引到不同的引脚上面
    1toN 部分padmux会同时连接几组PAD引脚,通讯时信号会同时提供到这几组PAD上面 该方式有如下限制: 所有的从设备必须类型一样且地址一样,而且MIIC只能写数据不能读数据一般用于同时接入几个相同从设备,需要同步设定的情况
    外部上拉 I2C总线上必须要接外部上拉

    如下为I2C时序:


    图3-2 I2C时序

    MIIC支持配置的时序如下:

    时序
    说明
    t-SU-STA 起始信号建立时间
    t-HD-STA 起始信号保持时间
    t-SU-STO 结束信号建立时间
    t-HD-STO 结束信号保持时间
    t-LOW 时钟低电平时间
    t-HIGH 时钟高电平时间
    t-SU-DAT 数据信号建立时间
    t-HD-DAT 数据信号保持时间

    I2C将不同的通信速度按区间分成多种速度模式,如下:

    速度模式
    说明
    Standard-mode (Sm) 最大可达 100k bit/s
    Fast-mode (Fm) 最大可达 400k bit/s
    Fast-mode Plus (Fm+) 最大可达 1M bit/s
    High-speed mode (Hs-mode) 最大可达 3.4M bit/s
    Ultra Fast-mode (UFm) 最大可达 5M bit/s

    Sm/Fm/Fm+对时序要求如下图:


    图3-3 不同速度模式的时序要求

    4. 硬件连接介绍

    I2C为多主从架构,顾名思义一路总线上面可以有多个主设备与多个从设备,他们之间通过从设备地址与应答信号来建立彼此联系。

    SigmaStar的I2C,每一路总线上仅提供了一个MIIC(master iic)主设备,从设备个数无要求,根据使用需求自行设定。

    并且,遵从I2C标准协议,在总线的SDA与SCL上面必须要接入外部上拉,这是因为I2C通讯需要输出高电平的能力,而当器件输出为开漏输出时,是无法输出高电平的,这时就需要外部上拉的帮助,借此实现“线与”功能,决定最终电平。

    如下为I2C总线示例图:


    图4-1 I2C总线示例图

    5. UBoot使用说明

    5.1 UBoot config 配置

    在编译Uboot时需要选择的配置如下:

    #menuconfig
    
    Command line interface --->
        Device access commands --->
            [*] i2c
    [*] SigmaStar drivers --->
            [*] SigmaStar IIC
    

    5.2. Dts配置

    I2C DTS配置只需要在对应的chipname.dtsi中配置如下信息:

    i2c0: i2c0@1F222800 {
        compatible = "sstar,i2c";
        reg = <0x1F222800 0x200>;
        clock-frequency = <200000>;
        //dma-enable;
        group = <0>;
        //if u want set tSU/tHD, it should be set to a non-zero value, with units in ns
        t-su-sta = <0>;
        t-hd-sta = <0>;
        t-su-sto = <0>;
        t-hd-sto = <0>;
        t-su-dat = <0>;
        t-hd-dat = <0>;
        //1->open drain; 2->open drain + one push; 3->open drain + mult push; 4->push-pull
        output-mode = <2>;
        status = "okay";
    };
    
    属性 描述 设定值 备注
    compatible 用于匹配驱动进行驱动注册,需与代码中一致 “sstar,i2c” 禁止修改
    reg 用于指定IIC寄存器bank的地址 不需要修改
    clocks 用于指定使用的时钟源 不需要更改
    group 用于指定IIC外设编号序列号 不需要修改
    speed 用于选择IIC Speed,直接填写实际值 如:250000即250K 可根据需要修改
    dma-en 用于选择是否使用DMA模式 1: 开启;
    0: 关闭
    可根据需要修改
    rd-ack-delay 用于设定ACK前的间隔时间 ns value 可根据需要修改
    t-su-sta 用于设定起始信号建立时间 ns value 可根据需要修改
    t-hd-sta 用于设定起始信号保持时间 ns value 可根据需要修改
    t-su-sto 用于设定结束信号建立时间 ns value 可根据需要修改
    t-hd-sto 用于设定结束信号保持时间 ns value 可根据需要修改
    t-su-dat 用于设定数据信号建立时间 ns value 需要小于tlow,同时修改该值t-hd-dat时,
    以该值的修改为准
    t-hd-dat 用于设定数据信号保持时间 ns value 需要小于tlow,同时修改该值t-su-dat时,
    以后者的修改为准
    output-mode 用于输出方式选择 1:开漏输出;
    2:开漏推1T输出;
    3:开漏推多T强上拉;
    4:推挽输出
    可根据需要修改,1->4上升沿时间依次缩短
    status 用于选择是否使能IIC master驱动 可根据需要修改

    5.3. Uboot cmd参数说明

    1. 显示当前所有i2c bus信息和初始化指定bus

      i2c bus <bus_num>
      
      参数名称 描述
      bus_num 输入0~3选择想要初始化的i2c bus, 不输入则展示所有可用bus
    2. 选择i2c bus

      i2c dev <bus_num>
      
      参数名称 描述
      bus_num 输入0~3选择想要使用的i2c bus
    3. 扫描从设备

      i2c probe <address>
      
      参数名称 描述
      address 测试是否有地址为address的设备接入,若不指定, 会扫描0x00-0x7f的全部地址
    4. 写操作命令

      i2c mw chip address[.0, .1, .2] value <count>
      
      参数名称 描述
      chip 从设备地址
      address 寄存器地址.寄存器地址长度(单位byte)
      value 写入数据
      count 重复次数
    5. 读操作命令

      i2c md chip address[.0, .1, .2] <length>
      
      参数名称 描述
      chip 从设备地址
      address 寄存器地址.寄存器地址长度(单位byte)
      length 读取字节数,不指定默认16byte

    5.4. Uboot cmd 使用实例

    i2c bus → i2c bus //List all buses

    i2c dev → i2c dev 1 //specify I2C bus

    i2c probe → i2c probe 0x50 //detect the slave with address 0x50

    i2c mw → i2c mw 0x50 0x0000.2 0x12 0x1 //write 0x12 to slave 0x50

    i2c md → i2c md 0x50 0x0000.2 0x01 //read 1 byte from slave 0x50

    6. Kernel用法介绍

    6.1. Kernel Config配置

    在编译kernel时需要选择的配置如下:

    #menuconfig
    
    Device Drivers --->
        I2C support --->
            <*> I2C device interface
        Sstar SoC platform drivers --->
            <*> Sstar I2C driver
    

    6.2. Dts配置

    可以通过配置dtsi中i2c项设定i2c driver的基本参数, dtsi的参数展示如下:

    i2c0: i2c@1f222800 {
        compatible = "sstar,i2c";
        reg = <0x0 0x1F222800 0x0 0x200>;
        #address-cells = <1>;
        #size-cells = <0>;
        interrupts = <GIC_SPI INT_IRQ_MIIC IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&CLK_miic0>;
        group = <0>;
        dma-enable;
        speed = <200000>;
        //if u want set tSU/tHD, do not set 0, tSU = (t-su-* / i2c-srcclk)S, tHD = (t-hd-* / i2c-srcclk)S
        t-su-sta = <0>;
        t-hd-sta = <0>;
        t-su-sto = <0>;
        t-hd-sto = <0>;
        t-su-dat = <0>;
        t-hd-dat = <0>;
        //1->open drain; 2->open drain + one push; 3->open drain + one push + clock push; 4->push-pull
        output-mode = <2>;
        status = "ok";
    };
    

    如上所示, 各项参数释义分别为:

    参数 释义 备注
    compatible 用于匹配驱动进行驱动注册,需与代码中一致 禁止修改
    reg 用于指定IIC寄存器bank的地址 不需要修改
    interrupts 用于指定使用的硬件中断号及属性 不需要更改
    clocks 用于指定使用的时钟源 不需要更改
    #address-cells 用于指定子节点的地址位宽 不需要更改
    #size-cells 用于指定子节点的大小位宽 不需要更改
    group 用于指定IIC外设编号序列号 不需要修改
    speed 用于选择IIC Speed,直接填写实际值 可根据需要修改
    dma-enable 用于选择是否使用DMA模式 不配置即关闭dma功能
    t-su-sta 设定起始信号建立时间 可根据需要修改,单位 ns
    t-hd-sta 设定起始信号保持时间 可根据需要修改,单位 ns
    t-su-sto 设定结束信号建立时间 可根据需要修改,单位 ns
    t-hd-sto 设定结束信号保持时间 可根据需要修改,单位 ns
    t-su-dat 设定数据信号建立时间 可根据需要修改,单位 ns
    t-hd-dat 设定数据信号保持时间 可根据需要修改,单位 ns
    output-mode 用于输出方式选择 可根据需要修改,1->4上升沿时间依次缩短
    status 用于选择是否使能IIC master驱动 可根据需要修改

    6.3. Padmux配置

    I2C在Uboot及Kernel环境下的padmux配置方法一致,只需要根据选择的引脚在对应的padmux.dtsi中加入如下所示的代码:

    //I2C
    <PAD_GPIOE_00   PINMUX_FOR_I2C0_MODE_1    MDRV_PUSE_I2C0_SCL>,
    <PAD_GPIOE_01   PINMUX_FOR_I2C0_MODE_1    MDRV_PUSE_I2C0_SDA>,
    <PAD_GPIOE_04   PINMUX_FOR_I2C1_MODE_1    MDRV_PUSE_I2C1_SCL>,
    <PAD_GPIOE_05   PINMUX_FOR_I2C1_MODE_1    MDRV_PUSE_I2C1_SDA>,
    <PAD_GPIOE_21   PINMUX_FOR_I2C2_MODE_1    MDRV_PUSE_I2C2_SCL>,
    <PAD_GPIOE_22   PINMUX_FOR_I2C2_MODE_1    MDRV_PUSE_I2C2_SDA>,
    <PAD_GPIOE_23   PINMUX_FOR_I2C3_MODE_1    MDRV_PUSE_I2C3_SCL>,
    <PAD_GPIOE_24   PINMUX_FOR_I2C3_MODE_1    MDRV_PUSE_I2C3_SDA>,
    <PAD_GPIOD_01   PINMUX_FOR_I2C4_MODE_1    MDRV_PUSE_I2C4_SCL>,
    <PAD_GPIOD_02   PINMUX_FOR_I2C4_MODE_1    MDRV_PUSE_I2C4_SDA>,
    <PAD_PM_I2C_SDA   PINMUX_FOR_PM_I2CM0_MODE_1    MDRV_PUSE_I2C5_SCL>,
    <PAD_PM_I2C_SDA   PINMUX_FOR_PM_I2CM0_MODE_1    MDRV_PUSE_I2C5_SDA>,
    

    第一列为引脚索引号,可以在drivers/sstar/inlcude/{chipname}/gpio.h中查到;

    第二列为模式定义,在drivers/sstar/gpio/{chipname}/hal_pinmux.chal_gpio_st_padmux_info数组里,罗列了所有引脚的复用关系,查询该引脚支持哪些复用功能可以查询该数组;

    第三列为引脚及搭配模式的索引名称,可在drivers/sstar/include/drv_puse.h里查询;

    6.4. 模块使用介绍

    6.4.1 kernel调用框架

    kernel I2C整体调用框架如图6-1所示,从用户层开始调用,通过打开设备节点,获取I2C的struct file_operations,再通过ioctl系统调用,期间经过用户空间和内核空间的转换与数据传递,一路执行到SigmaStar I2C driver,对硬件主设备进行设定操作,实现与从设备之间的通信。


    图6-1 I2C kernel调用框架

    6.4.2. 用户态读写I2C

    通过标准系统调用来读写I2C,使用范例可以参考:

    kernel/drivers/sstar/i2c/ut/ut_i2cdev.c
    

    flags变量的bit[1]用来指代i2c通讯中restart之前是否发送stop信号,即当次i2c_msg传输是否发送STOP信号。

    一次ioctl下发信息中可以包含多个struct i2c_message信息,对于写操作,每个message发送完成之后都可以选择是否发送stop信号,但最后一个message必须发送stop信号对于读操作,每个message之后都必须发送stop信号。

    例如,当我们要读数据的时候,需要先写发送要读取的寄存器地址,此时我们可以通过flags的bit[1]来控制这次写发送是否要跟上stop信号:

    messages[0].flags = 0      // S+WR+RS+RD+P
    messages[0].flags |= 0x02 // S+WR+P+RS+RD+P
    

    6.4.3. 内核态读写I2C

    通过内核标准接口操作I2C,内核态的如下调用方式同样可以像用户态那样一次下发多个struct i2c_msg信息,同时也可以选择每个msg是否接stop信号,与用户态的说明是一样的,不做赘述。

    struct i2c_adapter* adpa = NULL;
    struct i2c_msg msg;
    u8 data[4] = {0};
    
    adpa = i2c_get_adapter(nr); // 获取i2c-0 adapter
    
    data[0] = reg & 0xff;
    data[1] = value & 0xff;
    
    msg.addr = slaveAddr>>1;
    msg.flags = 0;
    msg.buf = data;
    msg.len = 2;
    
    i2c_transfer(adpa, &msg, 1)
    

    6.5. Sample code

    使用标准linux i2c框架的接口,用法如下:

    static int set_i2c_register(int bus, unsigned int addr, unsigned int reg, unsigned char *buf, unsigned int len)
    {
        struct i2c_rdwr_ioctl_data ioctl_packets;
        struct i2c_msg             i2c_message[1];
        char                       i2c_name[32];
        unsigned char *            write_buf;
        int                        i2c_file;
        int                        i;
    
        // open i2c dev node
        if (!snprintf(i2c_name, sizeof(i2c_name), "/dev/i2c-%d", bus))
        {
            printf("set i2c name error\n");
            exit(1);
        }
        if ((i2c_file = open(i2c_name, O_RDWR)) < 0)
        {
            printf("unable to open i2c control file");
            exit(1);
        }
    
        write_buf = (unsigned char *)malloc(DOUBLE_BUF_DATA_LENGTH);
    
        i2c_message[0].addr  = addr;
        i2c_message[0].flags = 0;
        i2c_message[0].len   = len + 2;
        i2c_message[0].buf   = write_buf;
    
        write_buf[0] = (reg >> 8) & 0x00ff;
        write_buf[1] = reg & 0x00ff;
    
        /* The first byte indicates which register we‘ll write */
        /*
         * The second byte indicates the value to write.  Note that for many
         * devices, we can write multiple, sequential registers at once by
         * simply making outbuf bigger.
         */
        for (i = 0; i < len; i++)
        {
            write_buf[i + 2] = buf[i];
        }
    
        /* Transfer the i2c packets to the kernel and verify it worked */
        ioctl_packets.msgs  = i2c_message;
        ioctl_packets.nmsgs = 1;
        do
        {
            if (ioctl(file, I2C_RDWR, &ioctl_packets) < 0)
            {
                free(write_buf);
                return 1;
            }
        } while (0);
    
        free(write_buf);
        return 0;
    }
    

    如果在kernel space 下不想使用linux 标准api,也可以使用第7章节定义的api。

    7. API 参考

    该功能模块提供以下接口:

    API名 功能
    CamI2cOpen 创建设备句柄
    CamI2cTransfers 进行iic传输(同步)
    CamI2cAsyncTransfer 进行iic传输(异步)
    CamI2cSetAsyncCb 设置iic异步传输cb函数
    CamI2cWnWrite 进行iic传输(同步并切分数据)
    CamI2cWnAsyncWrite 进行iic传输(异步并切分数据)

    要使用这些API,需要先包含头文件 drivers/sstar/include/cam_drv_i2c.h。

    其中定义的数据结构如下:

    typedef struct i2cMsg
    {
        u16 addr; /* slave address */
        u16 flags;
    #define I2C_M_RD 0x0001           /* read data, from slave to master */
                                      /* I2C_M_RD is guaranteed to be 0x0001! */
    #define I2C_M_TEN      0x0010     /* this is a ten bit chip address */
    #define I2C_M_DMA_SAFE 0x0200     /* the buffer of this message is DMA safe */
                                      /* makes only sense in kernelspace */
                                      /* userspace buffers are copied anyway */
    #define I2C_M_RECV_LEN     0x0400 /* length will be first received byte */
    #define I2C_M_NO_RD_ACK    0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
    #define I2C_M_IGNORE_NAK   0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
    #define I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
    #define I2C_M_NOSTART      0x4000 /* if I2C_FUNC_NOSTART */
    #define I2C_M_STOP         0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
        u16 len;                      /* msg length */
        u8 *buf;                      /* pointer to msg data */
    } tI2cMsg;
    
    typedef s32 (*sstar_i2c_async_calbck)(char para_msg_done, void *reserved);
    
    typedef struct
    {
        s32   nPortNum;
        void *pAdapter;
    } tI2cHandle;
    

    7.1. CamI2cOpen

    • 功能

      创建设备句柄,返回到 pHandle。
      
    • 声明

      s32 CamI2cOpen(tI2cHandle *pHandle, u8 nPortNum)。
      
    • 形参

      参数名称 描述
      pHandle 设备信息
      nPortNum 总线号
    • 返回值

      返回值 描述
      0 成功
      other 失败

    7.2. CamI2cTransfers

    • 功能

      与 pHandle 对应iic channel进行一次同步的iic传输,使用 nMsgNum 个 pMsg 存储传输信息。
      
    • 声明

      s32 CamI2cTransfer(tI2cHandle *pHandle, tI2cMsg *pMsg, u32 nMsgNum);
      
    • 形参

      参数名称 描述
      pHandle 设备信息
      pMsg 通信内容
      nMsgNum 信息长度
    • 返回值

      返回值 描述
      负数 失败
      other 成功

    7.3. CamI2cAsyncTransfer

    • 功能

      与 pHandle 对应iic channel进行一次异步的iic传输,使用 nMsgNum 个 pMsg 存储传输信息。
      
    • 声明

      s32 CamI2cAsyncTransfer(tI2cHandle *pHandle, tI2cMsg *pMsg, u32 nMsgNum);
      
    • 形参

      参数名称 描述
      pHandle 设备信息
      pMsg 通信内容
      nMsgNum 信息长度
    • 返回值

      返回值 描述
      0 成功
      other 失败

    7.4. CamI2cSetAsyncCb

    • 功能

      设置iic异步传输的回调函数。
      
    • 声明

      s32 CamI2cSetAsyncCb(tI2cHandle *pHandle, sstar_i2c_async_calbck CalBck, void *pReserved);
      
    • 形参

      参数名称 描述
      pHandle 设备信息
      CalBck 回调函数指针
      pReserved 保留形参
    • 返回值

      返回值 描述
      0 成功
      other 失败

    7.5. CamI2cWnWrite

    • 功能

      与 pHandle 对应iic channel进行一次同步的iic传输,使用 pMsg 个 nMsgNum 存储传输信息,每传输 WnLen 个byte,就会加上 WaitCnt 的间隔。
      
    • 声明

      s32 CamI2cWnWrite(tI2cHandle *pHandle, tI2cMsg *pMsg, u32 nMsgNum, u32 WnLen, u16 WaitCnt);
      
    • 形参

      参数名称 描述
      pHandle 设备信息
      pMsg 通信内容
      nMsgNum 信息长度
      WnLen 数据会分割个若干WnLen byte的小块
      WaitCnt 每个小块传输后会有WaitCnt个cnt的间隔
    • 返回值

      返回值 描述
      0 成功
      other 失败

    7.6. CamI2cWnAsyncWrite

    • 功能

      与 pHandle 对应iic channel进行一次异步的iic传输,使用 nMsgNum 个 pMsg 存储传输信息,每传输 WnLen 个byte,就会加上 WaitCnt 的间隔。
      
    • 声明

      s32 CamI2cWnAsyncWrite(tI2cHandle *pHandle, tI2cMsg *pMsg, u32 nMsgNum, u32 WnLen, u16 WaitCnt);
      
    • 形参

      参数名称 描述
      pHandle 设备信息
      pMsg 通信内容
      nMsgNum 信息长度
      WnLen 数据会分割个若干WnLen byte的小块
      WaitCnt 每个小块传输后会有WaitCnt个cnt的间隔
    • 返回值

      返回值 描述
      0 成功
      other 失败

    8. 调试

    当出现通讯异常时,可以参考如下方面进行问题调试,提供了几种较为常见的排查方向,另调试过程建议抓取波形方便分析。

    排查方向
    常见问题
    备注
    外部上拉 1. 提示通讯超时错误信息;
    2. 抓取波形无变化,SCL始终为低电平;
    3. 波形读写的数据都为0x00
    padmux 1. 提示无ACK信号;
    2. 波形没有变化,电平一直维持
    参考PADMUX章节,或padmux模块说明
    通信速率 通讯失败,无ACK信号 可查找从设备手册,确认正常工作的通信速率范围
    时钟源 1. 提示通讯超时错误信息;
    2. 无波形
    参考CLKGEN模块说明
    时序 通讯无ACK信号 若从设备会对各部分详细时序有特定要求,可从设备手册查找确认
    从设备工作状态 通讯失败,无ACK 当从设备没有处在正常的工作状态的时候,无法对主设备发起的信号进行响应