2026-01-20 16:55:17 +08:00

143 lines
5.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "IIC.h"
#include "driver/i2c.h"
#include "esp_log.h"
// 日志标签,用于输出日志信息
#define TAG "I2C操作"
// 辅助函数:构建 I2C 命令句柄,用于指定设备地址和寄存器地址
static i2c_cmd_handle_t build_i2c_cmd(uint8_t dev_addr, uint8_t reg_addr) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, reg_addr, true);
return cmd;
}
// 辅助函数:执行 I2C 命令句柄并释放资源
static esp_err_t execute_i2c_cmd(i2c_cmd_handle_t cmd) {
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
/**
* @brief 初始化 I2C 主设备
* @return esp_err_t 初始化结果ESP_OK 表示成功,其他值表示失败
*/
esp_err_t i2c_master_init(void) {
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER, // 设置为 I2C 主设备模式
.sda_io_num = I2C_MASTER_SDA_IO, // 指定 SDA 引脚
.scl_io_num = I2C_MASTER_SCL_IO, // 指定 SCL 引脚
.sda_pullup_en = GPIO_PULLUP_ENABLE, // 启用 SDA 引脚的上拉电阻
.scl_pullup_en = GPIO_PULLUP_ENABLE, // 启用 SCL 引脚的上拉电阻
.master.clk_speed = I2C_MASTER_FREQ_HZ, // 设置 I2C 时钟频率
};
// 配置 I2C 参数
i2c_param_config(i2c_master_port, &conf);
// 安装 I2C 驱动
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
void i2c_scan(void) {
esp_err_t err;
i2c_cmd_handle_t cmd;
ESP_LOGI(TAG, "开始扫描 I2C 总线...");
for (int addr = 0; addr < 128; addr++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
err = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
if (err == ESP_OK) {
ESP_LOGI(TAG, "在地址 0x%02X 发现设备", addr);
}
i2c_cmd_link_delete(cmd);
}
ESP_LOGI(TAG, "扫描完成。");
}
/**
* @brief 从 I2C 设备读取单个字节数据的函数
* @param dev_addr I2C 设备的 7 位地址
* @param reg_addr 要读取数据的寄存器地址
* @param data 用于存储读取到的单个字节数据的指针
* @return esp_err_t 操作结果ESP_OK 表示成功,其他值表示失败
*/
static esp_err_t my_i2c_master_read_byte(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data) {
i2c_cmd_handle_t cmd = build_i2c_cmd(dev_addr, reg_addr);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (dev_addr << 1) | I2C_MASTER_READ, true);
i2c_master_read_byte(cmd, data, I2C_MASTER_NACK);
i2c_master_stop(cmd);
return execute_i2c_cmd(cmd);
}
/*
* 功能:从 8 位地址的寄存器读取一个字节数据
* 参数:
* addr寄存器的内部地址
* *Data数据存储地址
* 返回值:(1 = 成功, 0 = 失败)
*/
unsigned char i2cread(unsigned char addr, unsigned char *Data) {
esp_err_t ret = my_i2c_master_read_byte(Device_Address, addr, Data);
return (ret == ESP_OK) ? 1 : 0;
}
/**
* @brief 从 Device_Address 的指定寄存器地址开始读取多个字节的数据
* @param addr I2C 设备Device_Address内部寄存器的起始地址
* @param length 要读取的数据字节长度
* @param Data 用于存储读取到的数据的缓冲区地址
* @return unsigned char 操作状态1 表示读取成功0 表示读取失败
*/
unsigned char i2creads(uint8_t addr, uint8_t length, uint8_t *Data) {
i2c_cmd_handle_t cmd = build_i2c_cmd(Device_Address, addr);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (Device_Address << 1) | I2C_MASTER_READ, true);
if (length > 1) {
i2c_master_read(cmd, Data, length - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, Data + length - 1, I2C_MASTER_NACK);
i2c_master_stop(cmd);
esp_err_t ret = execute_i2c_cmd(cmd);
return (ret == ESP_OK) ? 1 : 0;
}
/**
* @brief 向 8 位地址的寄存器写入一个字节数据
* @param addr 寄存器的内部地址
* @param Data 要写入的数据
* @return unsigned char 操作结果1 表示成功0 表示失败
*/
unsigned char i2cwrite(uint8_t addr, uint8_t Data) {
i2c_cmd_handle_t cmd = build_i2c_cmd(Device_Address, addr);
i2c_master_write_byte(cmd, Data, true);
i2c_master_stop(cmd);
esp_err_t ret = execute_i2c_cmd(cmd);
return (ret == ESP_OK) ? 1 : 0;
}
/**
* @brief 向 Device_Address 的指定寄存器地址开始写入多个字节的数据
* @param addr I2C 设备Device_Address内部寄存器的起始地址
* @param length 要写入的数据字节长度
* @param Data 要写入的数据缓冲区地址
* @return unsigned char 操作状态1 表示写入成功0 表示写入失败
*/
unsigned char i2cwrites(uint8_t addr, uint8_t length, const uint8_t *Data) {
i2c_cmd_handle_t cmd = build_i2c_cmd(Device_Address, addr);
for (uint8_t i = 0; i < length; i++) {
i2c_master_write_byte(cmd, Data[i], true);
}
i2c_master_stop(cmd);
esp_err_t ret = execute_i2c_cmd(cmd);
return (ret == ESP_OK) ? 1 : 0;
}