跳到主要内容

tKl_i2c | I2C 驱动

简要说明

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

I2C 典型接线方式如下:

image-20220406143504112
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
}

}