乐鑫技术交流
直播中

LL-LING宁

8年用户 1312经验值
擅长:电源/新能源
私信 关注
[问答]

为什么无法在ESP32之间进行I2C通信?

我的项目是测量水箱的水位。因为我使用了 3 个以上的 UART,所以我想使用 2 个 ESP32。

Slave ESP32:从水位传感器获取数据,通过I2C发送给Master ESP32。

Master ESP32:收集数据并将其传递给 NodeRED 进行处理和可视化。

我的问题:我无法在 ESP32 之间进行 I2C 通信

我的基本代码在这里:

从代码:
代码:全选
#include

#include "esp_log.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "driver/i2c.h"
#include "driver/gpio.h"

static const char *TAG = "i2c-slave";

#define _I2C_NUMBER(num) I2C_NUM_##num
#define I2C_NUMBER(num) _I2C_NUMBER(num)

#define DATA_LENGTH 512                  /*!< Data buffer length of test buffer */
#define RW_TEST_LENGTH 128               /*!< Data length for r/w test, [0,DATA_LENGTH] */
#define DELAY_TIME_BETWEEN_ITEMS_MS 1000 /*!< delay time between different test items */

#define I2C_SLAVE_SCL_IO 14                    /*!< gpio number for i2c slave clock */
#define I2C_SLAVE_SDA_IO 12                    /*!< gpio number for i2c slave data */
#define I2C_SLAVE_NUM I2C_NUMBER(0)            /*!< I2C port number for slave dev */
#define I2C_SLAVE_TX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave tx buffer size */
#define I2C_SLAVE_RX_BUF_LEN (2 * DATA_LENGTH) /*!< I2C slave rx buffer size */
#define I2C_SLAVE_ADDR 0x45                    /*!< I2C slave address */

typedef struct tankData
{
    int tankID;
    int waterLevel;
} tankData;

tankData tankOne;

/**
* @brief i2c slave initialization
*/
static esp_err_t i2c_slave_init(void)
{
    int i2c_slave_port = I2C_SLAVE_NUM;
    i2c_config_t conf_slave = {
        .sda_io_num = I2C_SLAVE_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_SLAVE_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .mode = I2C_MODE_SLAVE,
        .slave.addr_10bit_en = 0,
        .slave.slave_addr = I2C_SLAVE_ADDR,
        .slave.maximum_speed = 100000,
    };
    esp_err_t err = i2c_param_config(i2c_slave_port, &conf_slave);
    if (err != ESP_OK)
    {
        return err;
    }
    return i2c_driver_install(i2c_slave_port, conf_slave.mode, I2C_SLAVE_RX_BUF_LEN, I2C_SLAVE_TX_BUF_LEN, 0);
}

void app_main(void)
{
    int counter = 0;
    int i2c_data = 0;

    ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_slave_init());

    while (true)
    {
        tankOne.tankID = counter++;
        tankOne.waterLevel = (counter % 100);
        ESP_LOGI(TAG, "Tank ID: %d | Water Level: %d", tankOne.tankID, tankOne.waterLevel);
        i2c_data = i2c_slave_write_buffer(I2C_SLAVE_NUM, (uint8_t *)&tankOne, sizeof(tankOne), (1000 / portTICK_RATE_MS));

        if (i2c_data != ESP_FAIL)
        {
            ESP_LOGI(TAG, "I2C Data Length: %d Bytes", i2c_data);
        }
        else
        {
            ESP_LOGE(TAG, "Failed to generate data");
        }

        vTaskDelay(10000 / portTICK_RATE_MS);
    }
}

主码:
代码:全选
#include
#include

#include "esp_log.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "driver/i2c.h"

static const char *TAG = "i2c-master";

#define _I2C_NUMBER(num) I2C_NUM_##num
#define I2C_NUMBER(num) _I2C_NUMBER(num)

#define DATA_LENGTH 512                  /*!< Data buffer length of test buffer */
#define RW_TEST_LENGTH 128               /*!< Data length for r/w test, [0,DATA_LENGTH] */
#define DELAY_TIME_BETWEEN_ITEMS_MS 1000 /*!< delay time between different test items */

#define I2C_MASTER_SCL_IO 25         /*!< gpio number for I2C master clock */
#define I2C_MASTER_SDA_IO 27         /*!< gpio number for I2C master data  */
#define I2C_MASTER_NUM I2C_NUMBER(0) /*!< I2C port number for master dev */
#define I2C_MASTER_FREQ_HZ 100000    /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0  /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0  /*!< I2C master doesn't need buffer */
#define ESP_SLAVE_ADDR 0x45          /*!< I2C slave address */

#define WRITE_BIT I2C_MASTER_WRITE              /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ                /*!< I2C master read */
#define ACK_CHECK_EN 0x1                        /*!< I2C master will check ack from slave*/
#define ACK_CHECK_DIS 0x0                       /*!< I2C master will not check ack from slave */
#define ACK_VAL 0x0                             /*!< I2C ack value */
#define NACK_VAL 0x1                            /*!< I2C nack value */

typedef struct tankData
{
    int tankID;
    int waterLevel;
} tankData;

tankData tankOne;

/**
* @brief i2c master initialization
*/
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };
    esp_err_t err = i2c_param_config(i2c_master_port, &conf);
    if (err != ESP_OK)
    {
        return err;
    }
    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

static esp_err_t __attribute__((unused)) i2c_master_read_slave(i2c_port_t i2c_num, uint8_t *data_rd, size_t size)
{
    if (size == 0) {
        return ESP_OK;
    }
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | READ_BIT, ACK_CHECK_EN);
    if (size > 1) {
        i2c_master_read(cmd, data_rd, size - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_rd + size - 1, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

void app_main(void)
{
    uint8_t *data = (uint8_t *)malloc(DATA_LENGTH);
    esp_err_t i2c_read_err;

    ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_init());

    while (true)
    {
        // i2c_read_err = i2c_master_read_from_device(I2C_MASTER_NUM, ESP_SLAVE_ADDR, data, sizeof(data), (1000 / portTICK_RATE_MS));

        i2c_read_err = i2c_master_read_slave(I2C_NUM_0, data, DATA_LENGTH);

        if (i2c_read_err == ESP_OK)
        {
            memcpy(&tankOne, data, sizeof(tankOne));
            ESP_LOGI(TAG, "tankID: %d", tankOne.tankID);
            ESP_LOGI(TAG, "waterLevel: %d", tankOne.waterLevel);
        }
        else
        {
            ESP_LOGE(TAG, "[%d] I2C Error: %s", i2c_read_err, esp_err_to_name(i2c_read_err));
        }

        vTaskDelay(10000 / portTICK_RATE_MS);
    }
}

更多回帖

发帖
×
20
完善资料,
赚取积分