ESP32 开发笔记(十四)ESP32 I2C Slave 实现

本文介绍了如何使用ESP32作为I2C Slave实现Random Read/Write和Sequential Read/Write时序。由于esp-idf的API延迟问题,导致无法直接支持Random Read。解决方案是通过自定义中断处理程序,在特定中断中将数据预加载到硬件FIFO。文章详细讲解了所需的中断类型,如I2C_SLAVE_TRAN_COMP_INT、I2C_TRANS_COMPLETE_INT等,并提供了一个完整的ESP32-I2C-Slave工程实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

这篇文章将介绍使用 ESP32 作为 I2C 实现 Random Read/Write 和 Sequential Read/Write 时序。

首先通过下面的图了解下 Random Read 时序,I2C Master 通过这个时序读取任意数据地址开始的数据。
Random Read

___________________________________________________________________________________________________________________________________________________
| start | slave_addr + write_bit + ack | data address |start | slave_addr + read_bit + ack |  read n-1 bytes + ack | read 1 byte + nack | stop |

RANDOM READ: A random read requires a “dummy” byte write sequence to load in the data word address. Once the device address word and data word address are clocked in and acknowledged by the EEPROM, the microcontroller must generate another start condition.
The microcontroller now initiates a current address read by sending a device address with the read/write select bit high. The EEPROM acknowledges the device address and serially clocks out the data word. The microcontroller does not respond with a zero but does generate a following stop condition

  • 现有的 I2C Slave 无法实现类似 Random Read 时序
    • 原因分析:esp-idf 提供的 i2c_slave_write_buffer i2c_slave_read_buffer API 都是操作 RingBuffer 实现,而 Random Read 需要 Slave 在 接收到 slave_addr + read_bit + data address 前将数据放入 I2C 的硬件 FIFO 中。若是通过 API 进行判断当前 Master 想要操作的 数据地址,会因为这个 API 都是操作 RingBuffer 而有所延迟,导致 Master 接收到错误的数据(因为此时硬件 FIFO 还没有数据)。
    • 解决办法:
      • 在接收到 slave_addr + write_bit + data address 时将可能需要发送到主机的数据放入 TX FIFO 中,当主机继续发送 slave_addr + read_bit + data address 并 提供读数据时钟 时,I2C Slave 硬件会将 TX FIFO 中的数据发送到 Master。若主机不再发送 slave_addr + read_bit + data address,就将 FIFO 清空避免在之后的操作中造成错误。
      • 通过自定义中断处理程序,在相应的中断中进行处理

I2C 中断介绍

  1. 想要针对某个 I2C 或者 某种模式,使用自定义的中断处理程序,需要修改 esp-idf/components/driver/i2c.c 中的代码,这里仅仅针对 master 使用驱动中提供的中断处理程序,当模式为 Slave 时,使用自定义的中断处理程序。

在 release/3.2 中,无法直接使用 i2c_isr_register 覆盖之前的中断处理程序。通过简单修改驱动源文件,并在应用程序中调用 i2c_isr_register 实现使用自定义的中断处理程序。

修改 esp-idf/components/driver/i2c.c 文件中 i2c_driver_install 函数中的这段代码:

if (mode == I2C_MODE_MASTER) {
   
    //hook isr handler
    i2c_isr_register(i2c_num, i2c_isr_handler_default, p_i2c_obj[i2c_num], intr_alloc_flags, &p_i2c_obj[i2c_num]->intr_handle);
}

在应用程序中使用自定义的中断处理程序:

static void IRAM_ATTR i2c_slave_isr_handler_default(void* arg)
{
   
	…
	…
	…
}

/**
 * @brief i2c slave initialization
 */
static esp_err_t i2c_slave_init()
{
   
    int i2c_slave_port = I2C_SLAVE_NUM;
    i2c_config_t conf_slave;
    conf_slave.sda_io_num = I2C_SLAVE_SDA_IO;
    conf_slave.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf_slave.scl_io_num = I2C_SLAVE_SCL_IO;
    conf_slave.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf_slave
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值