143 lines
5.2 KiB
C
143 lines
5.2 KiB
C
#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;
|
||
} |