Add shared_i2c/main.c
This commit is contained in:
187
shared_i2c/main.c
Normal file
187
shared_i2c/main.c
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user