🏆 加入TuyaOpen AI硬件大赛!100天打造未来AI爆款硬件了解更多 →
跳到主要内容

tKl_i2c | I2C 驱动

简要说明

I2C (Inter-Integrated Circuit) 是一种串行的同步通信总线。 I2C 串行总线有两根信号线,一根是双向的数据线 SDA,另一根是时钟线 SCL。所有接到 I2C 总线设备上的串行数据 SDA 都接到总线的 SDA 上,各设备的时钟线 SCL 接到总线的 SCL 上。

I2C 典型接线方式如下:

image-20220406143504112

总线的通信由主机控制,即主机是数据的传送(发出启动信号)、发出时钟信号以及传送结束时发出停止信号的设备。被主机寻访的设备称为从机。每个接到 I2C 总线的设备都有一个唯一的地址,以便于主机寻访。主机和从机的数据传送,可以由主机发送数据到从机,也可以由从机发到主机。I2C 支持 7 位或者 10 位从设备地址模式。I2C 总线在开始条件后的首字节决定哪个被控器将被主控器选择,当主机输出一地址时,系统中的每一从设备都将开始条件后的地址和自己的地址进行比较,如果相同,该从机即认为自己被主机寻址。

索引

tkl_i2c_init

OPERATE_RET tkl_i2c_init(TUYA_I2C_NUM_E port, const TUYA_IIC_BASE_CFG_T *cfg);
  • 功能描述:

    • 通过端口号和基础配置初始化对应的 I2C 实例,返回初始化结果。
  • 参数:

    • port: 端口号。

    • cfg: I2C 基础配置,包含角色,速率,地址宽度 。

      typedef struct {
          TUYA_IIC_ROLE_E      role;
          TUYA_IIC_SPEED_E     speed;
          TUYA_IIC_ADDR_MODE_E addr_width;
      } TUYA_IIC_BASE_CFG_T;
      

      TUYA_IIC_ROLE_E:

      名字定义备注
      TUYA_IIC_MODE_MASTERI2C 主机模式
      TUYA_IIC_MODE_MASTERI2C 从机模式

      TUYA_IIC_SPEED_E:

      名字定义备注
      TUYA_IIC_BUS_SPEED_100KI2C 标准速度(100KHz)
      TUYA_IIC_BUS_SPEED_400KI2C 快速速度(400KHz)
      TUYA_IIC_BUS_SPEED_1MI2C 标准+速度(1MHz)
      TUYA_IIC_BUS_SPEED_3_4MI2C 高速速度(3.4MHz)

      TUYA_IIC_ADDR_MODE_E:

      名字定义备注
      TUYA_IIC_ADDRESS_7BIT7bit 地址模式
      TUYA_IIC_ADDRESS_10BIT10bit 地址模式
  • 返回值:

    • OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_deinit

OPERATE_RET tkl_i2c_deinit(TUYA_I2C_NUM_E port)
  • 功能描述:
    • I2C 实例反初始化。该接口会停止 I2C。
    • 实例正在进行的传输(如果有),并且释放相关的软硬件资源。
  • 参数:
    • port: 端口号。
  • 返回值:
    • OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_irq_init

OPERATE_RET tkl_i2c_irq_init(TUYA_I2C_NUM_E port, TUYA_I2C_IRQ_CB cb);
  • 功能描述:

    • I2C 中断初始化。
  • 参数:

    • port: 端口号。

    • cb: I2C 中断回调函数。

      回调函数类型 TUYA_I2C_IRQ_CB 定义如下:

      typedef void (*TUYA_I2C_IRQ_CB)(TUYA_I2C_NUM_E port, TUYA_I2C_IRQ_EVT_E event);
      

      其中 port 为端口号,event 为传给回调函数的事件类型。

      I2C 回调事件枚举类型 TUYA_I2C_IRQ_EVT_E 定义如下:

      名字定义备注
      TUYA_IIC_EVENT_TRANSFER_DONE传输完成事件
      TUYA_IIC_EVENT_TRANSFER_INCOMPLETE传输未完成事件
      TUYA_IIC_EVENT_SLAVE_TRANSMIT从设备发送操作请求事件
      TUYA_IIC_EVENT_SLAVE_RECEIVE从设备接收操作请求事件
      TUYA_IIC_EVENT_ADDRESS_NACK地址未应答事件
      TUYA_IIC_EVENT_GENERAL_CALL指示收到 general call(地址为0)事件
      TUYA_IIC_EVENT_ARBITRATION_LOST主机仲裁丢失事件
      TUYA_IIC_EVENT_BUS_ERROR总线错误事件
      TUYA_IIC_EVENT_BUS_CLEAR总线清除完成事件
  • 返回值:

    • OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_irq_enable

OPERATE_RET tkl_i2c_irq_enable(TUYA_I2C_NUM_E port);
  • 功能描述:
    • 打开 I2C 中断。
  • 参数:
    • port: 端口号。
  • 返回值:
    • OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_irq_disable

OPERATE_RET tkl_i2c_irq_disable(TUYA_I2C_NUM_E port);
  • 功能描述:
    • 关闭 I2C 中断。
  • 参数:
    • port: 端口号。
  • 返回值:
    • OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_master_send

OPERATE_RET tkl_i2c_master_send(TUYA_I2C_NUM_E port, uint16_t dev_addr, const void *data, uint32_t size, BOOL_T xfer_pending);
  • 功能描述:
    • I2C 作为主机时启动数据发送。
  • 参数:
    • port: 端口号。
    • dev_addr: Slave 设备地址。
    • data: 待发送数据的缓冲区地址。
    • size: 待发送数据的长度。
    • xfer_pending:
    • 发送完成后是否发送停止位。1-不发送停止位,0-发送停止位。
  • 返回值:
    • 错误码,OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_master_receive

OPERATE_RET tkl_i2c_master_receive(TUYA_I2C_NUM_E port, uint16_t dev_addr, void *data, uint32_t size, BOOL_T xfer_pending);
  • 功能描述:
  • 参数:
    • port: 端口号。
    • dev_addr: Slave 设备地址。
    • data: 待接收数据的缓冲区地址。
    • size: 待接收数据的长度。
    • xfer_pending:
    • 接收完成后是否发送停止位。1-不发送停止位,0-发送停止位。
  • 返回值:
    • 错误码,OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_set_slave_addr

OPERATE_RET tkl_i2c_set_slave_addr(TUYA_I2C_NUM_E port, uint16_t dev_addr);
  • 功能描述:
    • 配置 I2C 的从设备地址。
  • 参数:
    • port: 端口号。
    • dev_addr: I2C 从设备通信地址。
  • 返回值:
    • 错误码,OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_slave_send

OPERATE_RET tkl_i2c_slave_send(TUYA_I2C_NUM_E port, const void *data, uint32_t size);
  • 功能描述:
    • i2c作为从机时启动数据发送。
  • 参数:
    • port: 端口号。
    • data: 待发送数据的缓冲区地址。
    • size: 从机待发送数据的长度。
  • 返回值:
    • 错误码,OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_slave_receive

OPERATE_RET tkl_i2c_slave_receive(TUYA_I2C_NUM_E port, void *data, uint32_t size);
  • 功能描述:
    • i2c作为从机时启动数据接收。
  • 参数:
    • port: 端口号。
    • data: 待接收数据的缓冲区地址。
    • size: 待接收数据的长度。
  • 返回值:
    • 错误码,OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

tkl_i2c_get_status

TUYA_IIC_STATUS_T tkl_i2c_get_status(TUYA_I2C_NUM_E port);
  • 功能描述:
    • 获取当前时刻i2c 的状态。
  • 参数:
    • port: 端口号。
  • 返回值:
    • I2C 状态的结构体。I2C 的状态定义见 TUYA_I2C_STATUS_T

tkl_i2c_get_data_count

int32_t tkl_i2c_get_data_count(TUYA_I2C_NUM_E port);
  • 功能描述:
    • 获取 I2C 已传输得数据个数。
    • 针对 tkl_i2c_master_send,传输或发送的字节数。
    • 针对 tkl_i2c_master_receive,接收到的字节数。
    • 针对 tkl_i2c_slave_send,传输的字节数。
    • 针对 tkl_i2c_slave_receive,接收的字节数。
  • 参数:
    • port: 端口号
  • 返回值:
    • 已传输数据个数

TUYA_IIC_STATUS_T:

名字定义备注
busy : 1传输或发送忙状态位
mode : 1模式位。1-主,0-从
direction : 1传输方向:1-接收,0-发送
general_call : 1general call 指示
arbitration_lost : 1主机失去仲裁
bus_error : 1总线错误

tkl_i2c_reset

OPERATE_RET tkl_i2c_reset(TUYA_I2C_NUM_E port);
  • 功能描述:
    • 复位i2c。
  • 参数:
    • port: 端口号。
  • 返回值:
    • 错误码,OPRT_OK 成功,其他请参考文件 tuya_error_code.hOS_ADAPTER_I2C 定义部分。

示例

1.I2C 示例一

static uint16_t cb_transfer_flag = 0xff;

static void i2c_event_cb_fun(int32_t idx, TUYA_IIC_IRQ_EVT_E event)
{
    if (idx == I2C_NUM_0){
        cb_transfer_flag = event;
    }
}

void tuya_i2c_master_test(void)
{
    OPERATE_RET ret;
 	TUYA_IIC_BASE_CFG_T cfg;
    //receive buffer
    char rcv_buf[10] ;
    //data to send
    char send_buf[10] = {0,1,2,3,4,5,6,7,8,9};

    tkl_io_pinmux_config(TUYA_IO_PIN_0, TUYA_IIC0_SCL);
    tkl_io_pinmux_config(TUYA_IO_PIN_1, TUYA_IIC0_SDA);

    cfg.role = TUYA_IIC_MODE_MASTER;
    cfg.speed = TUYA_IIC_BUS_SPEED_100K;
    cfg.addr_width = TUYA_IIC_ADDRESS_7BIT;

    ret = tkl_i2c_init(I2C_NUM_0, &cfg);
    if (ret != OPRT_OK) {
        //fail
        return;
    }

    ret = tkl_i2c_irq_init(I2C_NUM_0, i2c_event_cb_fun);
    if (ret != OPRT_OK) {
        //fail
        return;
    }

    ret = tkl_i2c_irq_enable(I2C_NUM_0);
    if (ret != OPRT_OK) {
        //fail
        return;
    }

    ret = tkl_i2c_master_send(I2C_NUM_0, 0x57, send_buf, sizeof(send_buf), 0);
    if (ret < 0) {
        //failed
    }
    while (cb_transfer_flag == 0xff);

    //check transfer result
    if (cb_transfer_flag == IIC_EVENT_TRANSFER_DONE) {
        //transmit done
    } else {
        //failed
    }
    cb_transfer_flag = 0xff;

    ret = tkl_i2c_master_receive(I2C_NUM_0, 0x57, rcv_buf, sizeof(rcv_buf), 0);
    if (ret < 0) {
        //failed
    }

    while (cb_transfer_flag == 0xff);

    //check transfer result
    if (cb_transfer_flag == IIC_EVENT_TRANSFER_DONE) {
        //transmit done
    } else {
        //failed
    }

    ret = tkl_i2c_irq_disable(I2C_NUM_0);
    if (ret != OPRT_OK) {
        //fail
        return;
    }
    //uninitialize iic
    ret = tkl_i2c_deinit(I2C_NUM_0);
    if (ret != 0) {
       //failed
    }
}

1.I2C 示例二

void tuya_i2c_slave_test(void)
{
    OPERATE_RET ret;
 	TUYA_IIC_BASE_CFG_T cfg;
    TUYA_IIC_STATUS_T st;
    //receive buffer
    char rcv_buf[10] ;
    //data to send
    char send_buf[10] = {0,1,2,3,4,5,6,7,8,9};
    int32_t cnt = 100;

    tkl_io_pinmux_config(TUYA_IO_PIN_0, TUYA_IIC0_SCL);
    tkl_io_pinmux_config(TUYA_IO_PIN_1, TUYA_IIC0_SDA);

    cfg.role = TUYA_IIC_MODE_SLAVE;
    cfg.speed = TUYA_IIC_BUS_SPEED_100K;
    cfg.addr_width = TUYA_IIC_ADDRESS_7BIT;

    ret = tkl_i2c_init(I2C_NUM_0, &cfg);
    if (ret != OPRT_OK) {
        //fail
        return;
    }

    ret = tkl_i2c_set_slave_addr(I2C_NUM_0, 0x57);
    if (ret != OPRT_OK) {
        //fail
        return;
    }

    ret = tkl_i2c_slave_send(I2C_NUM_0, send_buf, sizeof(send_buf));
    if (ret < 0) {
        //failed
    }
    //wait send done, waiting for 100 ms max
    st.busy = 1;
    cnt = 100;
    while(cnt--) {
        tkl_system_sleep(1);
        //check status
        st = tkl_i2c_get_status(I2C_NUM_0);
        //transmit done
        if (st.busy == 0){
            break;
        }
    }

    ret = tkl_i2c_slave_receive(I2C_NUM_0, rcv_buf, sizeof(rcv_buf));
    if (ret < 0) {
        //failed
    }
    //wait send done, waiting for 100 ms max
    st.busy = 1;
    cnt = 100;
    while(cnt--) {
        tkl_system_sleep(1);
        //check status
        st = tkl_i2c_get_status(I2C_NUM_0);
        //transmit done
        if (st.busy == 0){
            break;
        }
    }

    //uninitialize iic
    ret = tkl_i2c_deinit(I2C_NUM_0);
    if (ret != 0) {
       //failed
    }

}