esp32 在ulp模式下定期读取sht30的温湿度参数的完整代码
时间: 2024-02-25 12:58:20 浏览: 196
以下是 ESP32 在 ULP 模式下定期读取 SHT30 温湿度参数的完整代码:
```
#include "esp_sleep.h"
#include "driver/rtc_io.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "soc/soc_ulp.h"
RTC_DATA_ATTR static struct {
uint16_t humi;
uint16_t temp;
} sht30_data;
static RTC_DATA_ATTR const uint16_t sht30_cmd = 0x2400; // SHT30读取命令
static const uint16_t sht30_crc_table[] = { //CRC校验表
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef
};
// 计算 SHT30 数据的 CRC 校验值
static uint16_t sht30_crc(uint8_t *data, int len)
{
uint16_t crc = 0xffff;
for (int i = 0; i < len; i++) {
crc = (crc << 8) ^ sht30_crc_table[(crc >> 8) ^ data[i]];
}
return crc;
}
// ULP 程序
static const ulp_insn_t ulp_prog[] = {
I_MOVI(R2, sht30_cmd),
I_WR_REG(R2, SENS_SHT3XD_ADDR, SENS_SHT3XD_CMD, 0),
I_DELAY(1000), // 等待 1000us
I_RD_REG(R2, SENS_SHT3XD_ADDR, SENS_SHT3XD_DATA_H, 0),
I_WR_REG(R3, SENS_SHT3XD_ADDR, SENS_SHT3XD_CMD, 1),
I_DELAY(1000), // 等待 1000us
I_RD_REG(R3, SENS_SHT3XD_ADDR, SENS_SHT3XD_DATA_L, 0),
I_HALT()
};
void setup()
{
rtc_gpio_init(GPIO_NUM_4); // SHT30 的 SDA 引脚连接到 GPIO4
rtc_gpio_set_direction(GPIO_NUM_4, RTC_GPIO_MODE_INPUT_OUTPUT); // 设置为输入输出模式
rtc_gpio_set_level(GPIO_NUM_4, 1); // 默认拉高
// 配置 ULP 程序
ulp_process_macros_and_load(0, ulp_prog, sizeof(ulp_prog) / sizeof(ulp_insn_t));
ulp_set_wakeup_period(0, 1000000); // 设置 ULP 睡眠时间为 1s
ulp_run(0); // 启动 ULP 程序
}
void loop()
{
esp_sleep_enable_ulp_wakeup(); // 允许 ULP 唤醒主CPU
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); // 打开 RTC 性能域
esp_light_sleep_start(); // 进入浅度睡眠
if (sht30_data.humi != 0 && sht30_data.temp != 0) {
// 发送温湿度数据到服务器等
}
}
// 中断处理函数,当 ULP 程序执行完毕后会调用此函数
void IRAM_ATTR ulp_isr(void *arg)
{
uint8_t data[2];
data[0] = ulp_reg_read(SENS_SHT3XD_DATA_H_REG);
data[1] = ulp_reg_read(SENS_SHT3XD_DATA_L_REG);
if (sht30_crc(data, 2) == ((data[0] << 8) | data[1])) { // 验证 CRC 校验值
sht30_data.humi = ((data[0] << 8) | data[1]) * 100 / 65535;
data[0] = ulp_reg_read(SENS_SHT3XD_DATA_H_REG + 1);
data[1] = ulp_reg_read(SENS_SHT3XD_DATA_L_REG + 1);
if (sht30_crc(data, 2) == ((data[0] << 8) | data[1])) {
sht30_data.temp = ((data[0] << 8) | data[1]) * 175 / 65535 - 45;
}
}
ulp_set_wakeup_period(0, 1000000); // 设置 ULP 睡眠时间为 1s
ulp_run(0); // 启动 ULP 程序
}
// 主函数
void app_main()
{
setup();
// 注册 ULP 中断处理函数
esp_err_t ret = esp_sleep_enable_timer_wakeup(1000000); // 设置主CPU睡眠时间为 1s
ret = esp_sleep_isr_register(&ulp_isr, NULL, ESP_SLEEP_ISR_FLAG_DEFAULT);
while (1) {
loop();
}
}
```
需要注意的是,上述代码涉及到 SHT30 的读取、CRC 校验等细节,具体可以参考 SHT30 的数据手册。同时,为了防止 ULP 程序占用主CPU资源,需要在 ULP 程序执行完毕后立即进入浅度睡眠,并在 ULP 中断处理函数中重新启动 ULP 程序。
阅读全文