187 lines
6.8 KiB
C
187 lines
6.8 KiB
C
---
|
|
|
|
## `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);
|
|
} |