Page 1 of 1

esp-idf-v5.1 lp_core_i2c 读取问题

Posted: Wed Sep 06, 2023 9:02 am
by fb_iceg

Code: Select all

/**
 * @brief Read from I2C device
 *
 * @note The LP I2C must have been initialized from the HP core using the lp_core_i2c_master_init() API
 * before invoking this API.
 *
 * @param lp_i2c_num    LP I2C port number
 * @param device_addr   I2C device address (7-bit)
 * @param data_rd       Buffer to hold data to be read
 * @param size          Size of data to be read in bytes
 * @param timeout       Operation timeout in CPU cycles. Set to -1 to wait forever.
 *
 * @return esp_err_t    ESP_OK when successful
 *
 * @note the LP I2C does not support 10-bit I2C device addresses.
 * @note the LP I2C port number is ignored at the moment.
 */
esp_err_t lp_core_i2c_master_read_from_device(i2c_port_t lp_i2c_num, uint16_t device_addr,
                                            uint8_t *data_rs, size_t size,
                                            int32_t ticks_to_wait);
问一下,寄存器地址咋搞?不支持带寄存器的芯片?

Re: esp-idf-v5.1 lp_core_i2c 读取问题

Posted: Fri Sep 08, 2023 2:57 am
by ESP_Penguin_Helper
你好,寄存器的地址需要从外设的技术规格书中获得。

拿 lp_i2c举例:https://github.com/espressif/esp-idf/tr ... ore/lp_i2c

这个例程中通过 i2c 控制 BH1750 传感器。通过阅读 BH1750 的技术规格书:https://www.mouser.com/datasheet/2/348/ ... 186247.pdf 了解到 BH1750 的一些寄存器地址以及它们的作用。
BH1750.png
BH1750.png (131.25 KiB) Viewed 2118 times
参考例程中的用法

Code: Select all

uint8_t data_rd[2];
    esp_err_t ret = lp_core_i2c_master_read_from_device(LP_I2C_NUM_0, BH1750_I2C_ADDR, data_rd, sizeof(data_rd), LP_I2C_TRANS_TIMEOUT_CYCLES);
    if (ret != ESP_OK) {
        // Skip this round of calculation and return
        return;
    }
其中,BH1750_I2C_ADDR 指的是寄存器地址,他在头文件中被设置为

Code: Select all

#define BH1750_I2C_ADDR                 0x23
参考 BH1750 的技术规格书对应的寄存器地址,0x23 = 00100011。这里使用了 One Time L-Resolution Mode

Re: esp-idf-v5.1 lp_core_i2c 读取问题

Posted: Fri Sep 08, 2023 9:08 am
by fb_iceg
问题已解决,分享+记录+备忘。
芯片:ina226
ina226_i2c.png
ina226_i2c.png (118.24 KiB) Viewed 2097 times
读写时序如上图所示。读写,都是需要指定寄存器地址的。
为啥一开始会有疑问呢,lp_core_i2c 提供三个函数接口
  • lp_core_i2c_master_write_to_device
  • lp_core_i2c_master_read_from_device
  • lp_core_i2c_master_write_read_device
三个函数都没提到寄存器。一开始就没搞明白。

解决办法:
1、写寄存器

Code: Select all

esp_err_t lp_core_i2c_master_write_to_device(i2c_port_t lp_i2c_num, uint16_t device_addr,
                                            const uint8_t *data_wr, size_t size,
                                            int32_t ticks_to_wait)
写的时候,寄存器数据 16位:

Code: Select all

uint8_t data_wr[3];
data_wr[0] = (uint8_t) reg_addr;  //寄存器地址
data_wr[1] = (uint8_t) (reg_date>> 8);
data_wr[2] = (uint8_t) reg_date;
2、读寄存器

Code: Select all

esp_err_t lp_core_i2c_master_write_to_device(i2c_port_t lp_i2c_num, uint16_t device_addr,
                                            const uint8_t *data_wr, size_t size,
                                            int32_t ticks_to_wait)

Code: Select all

esp_err_t lp_core_i2c_master_read_from_device(i2c_port_t lp_i2c_num, uint16_t device_addr,
                                            uint8_t *data_rd, size_t size,
                                            int32_t ticks_to_wait)
读的时候,要先写寄存器地址,1个字节的地址,再接着读两个字节的数据:

Code: Select all

uint8_t data_wr = reg_addr;
uint8_t data_rd[2];
再提一下 lp_core 和 主进程的数据交互。
https://docs.espressif.com/projects/esp ... _i2c_cfg_t
英语水平一般,不知道,看的不清不楚。就自己研究了一下
大体用法就是,在 lp_core/main.c 内声明变量 要用 volatile 做前缀,如 volatile uint32_t lux.
然后在 lp_core_main.h 内就会自动生成一个 extern uint32_t ulp_lux 的新变量.
这个 ulp_lux 就可以在主进程内直接用了, lp_core_main.h 已经自动被 include。

要注意的是 在 lp_core/main.c 声明的任意格式的变量,哪怕是 结构体,在主进程内都只能是 uint32_t 格式,需要再转换,尤其是结构体。