Add shared_i2c/main.c

This commit is contained in:
2025-07-09 12:29:01 -04:00
parent 4eb7961a96
commit a01ef13dbd

187
shared_i2c/main.c Normal file
View File

@@ -0,0 +1,187 @@
---
## `main/main.c`
```c
#include <stdio.h>
#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);
}