From a01ef13dbd1b1927d0b0fdfdb0b11c3cc98df8e9 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 9 Jul 2025 12:29:01 -0400 Subject: [PATCH] Add shared_i2c/main.c --- shared_i2c/main.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 shared_i2c/main.c diff --git a/shared_i2c/main.c b/shared_i2c/main.c new file mode 100644 index 0000000..de31b2a --- /dev/null +++ b/shared_i2c/main.c @@ -0,0 +1,187 @@ +--- + +## `main/main.c` + +```c +#include +#include "esp_log.h" +#include "driver/i2c.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" // For mutex + +static const char *TAG = "I2C_SHARED_BUS"; + +// --- I2C Configuration --- +#define I2C_MASTER_SCL_IO GPIO_NUM_22 /*!< GPIO number for I2C master clock */ +#define I2C_MASTER_SDA_IO GPIO_NUM_21 /*!< GPIO number for I2C master data */ +#define I2C_MASTER_NUM I2C_NUM_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 tx buffer size */ +#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master rx buffer size */ +#define I2C_MASTER_TIMEOUT_MS 1000 /*!< I2C master timeout in ms */ + +// --- Sensor Addresses (Replace with your actual sensor addresses) --- +#define SENSOR_A_SLAVE_ADDR 0x68 // Example address for Sensor A +#define SENSOR_B_SLAVE_ADDR 0x76 // Example address for Sensor B + +// --- FreeRTOS Mutex for I2C Bus --- +SemaphoreHandle_t xI2CMutex; + +/** + * @brief Initialize the I2C master bus. + */ +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, + .scl_io_num = I2C_MASTER_SCL_IO, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .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); +} + +/** + * @brief Generic function to read data from an I2C sensor. + * This function acquires and releases the I2C mutex. + * @param slave_addr I2C slave address of the sensor. + * @param reg_addr Register address to read from. + * @param data Buffer to store the read data. + * @param len Length of data to read. + * @return ESP_OK on success, otherwise an error code. + */ +esp_err_t i2c_sensor_read(uint8_t slave_addr, uint8_t reg_addr, uint8_t *data, size_t len) +{ + esp_err_t ret = ESP_FAIL; + + if (xSemaphoreTake(xI2CMutex, portMAX_DELAY) == pdTRUE) { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, reg_addr, true); + i2c_master_start(cmd); // Repeated start for reading + i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_READ, true); + if (len > 1) { + i2c_master_read(cmd, data, len - 1, I2C_MASTER_ACK); + } + i2c_master_read_byte(cmd, data + len - 1, I2C_MASTER_NACK); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + + xSemaphoreGive(xI2CMutex); + } else { + ESP_LOGE(TAG, "Failed to acquire I2C mutex for read from 0x%02X", slave_addr); + } + return ret; +} + +/** + * @brief Generic function to write data to an I2C sensor. + * This function acquires and releases the I2C mutex. + * @param slave_addr I2C slave address of the sensor. + * @param reg_addr Register address to write to. + * @param data Data to write. + * @param len Length of data to write. + * @return ESP_OK on success, otherwise an error code. + */ +esp_err_t i2c_sensor_write(uint8_t slave_addr, uint8_t reg_addr, const uint8_t *data, size_t len) +{ + esp_err_t ret = ESP_FAIL; + + if (xSemaphoreTake(xI2CMutex, portMAX_DELAY) == pdTRUE) { + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); + i2c_master_start(cmd); + i2c_master_write_byte(cmd, (slave_addr << 1) | I2C_MASTER_WRITE, true); + i2c_master_write_byte(cmd, reg_addr, true); + i2c_master_write(cmd, (uint8_t *)data, len, true); + i2c_master_stop(cmd); + ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS); + i2c_cmd_link_delete(cmd); + + xSemaphoreGive(xI2CMutex); + } else { + ESP_LOGE(TAG, "Failed to acquire I2C mutex for write to 0x%02X", slave_addr); + } + return ret; +} + +/** + * @brief Task for Sensor A. + */ +void sensor_a_task(void *pvParameters) +{ + uint8_t sensor_a_data[2]; // Example: reading 2 bytes + uint8_t sensor_a_reg = 0x00; // Example register + + while (1) { + ESP_LOGI(TAG, "Sensor A: Attempting to read data..."); + esp_err_t ret = i2c_sensor_read(SENSOR_A_SLAVE_ADDR, sensor_a_reg, sensor_a_data, sizeof(sensor_a_data)); + if (ret == ESP_OK) { + ESP_LOGI(TAG, "Sensor A: Read successful. Data: 0x%02X 0x%02X", sensor_a_data[0], sensor_a_data[1]); + } else { + ESP_LOGE(TAG, "Sensor A: Read failed (0x%X)", ret); + } + vTaskDelay(pdMS_TO_TICKS(2000)); // Read every 2 seconds + } +} + +/** + * @brief Task for Sensor B. + */ +void sensor_b_task(void *pvParameters) +{ + uint8_t sensor_b_data[4]; // Example: reading 4 bytes + uint8_t sensor_b_reg = 0x10; // Example register + uint8_t write_data = 0x55; // Example data to write + + while (1) { + // Example: Write to Sensor B + ESP_LOGI(TAG, "Sensor B: Attempting to write data..."); + esp_err_t ret_write = i2c_sensor_write(SENSOR_B_SLAVE_ADDR, sensor_b_reg, &write_data, 1); + if (ret_write == ESP_OK) { + ESP_LOGI(TAG, "Sensor B: Write successful."); + } else { + ESP_LOGE(TAG, "Sensor B: Write failed (0x%X)", ret_write); + } + + vTaskDelay(pdMS_TO_TICKS(500)); // Small delay between write and read + + // Example: Read from Sensor B + ESP_LOGI(TAG, "Sensor B: Attempting to read data..."); + esp_err_t ret_read = i2c_sensor_read(SENSOR_B_SLAVE_ADDR, sensor_b_reg, sensor_b_data, sizeof(sensor_b_data)); + if (ret_read == ESP_OK) { + ESP_LOGI(TAG, "Sensor B: Read successful. Data: 0x%02X 0x%02X 0x%02X 0x%02X", + sensor_b_data[0], sensor_b_data[1], sensor_b_data[2], sensor_b_data[3]); + } else { + ESP_LOGE(TAG, "Sensor B: Read failed (0x%X)", ret_read); + } + vTaskDelay(pdMS_TO_TICKS(3000)); // Read/Write every 3 seconds + } +} + +void app_main(void) +{ + ESP_LOGI(TAG, "Initializing I2C master"); + ESP_ERROR_CHECK(i2c_master_init()); + ESP_LOGI(TAG, "I2C master initialized successfully"); + + // Create the I2C mutex + xI2CMutex = xSemaphoreCreateMutex(); + if (xI2CMutex == NULL) { + ESP_LOGE(TAG, "Failed to create I2C mutex"); + return; + } + + // Create tasks for each sensor + xTaskCreate(&sensor_a_task, "sensor_a_task", 4096, NULL, 5, NULL); + xTaskCreate(&sensor_b_task, "sensor_b_task", 4096, NULL, 5, NULL); +} \ No newline at end of file