ESP8266集成开发HLW8032电量采集功能
2025/10/12大约 9 分钟
ESP8266集成开发HLW8032电量采集功能
HLW8032_ESP.h
#ifndef HLW8032_h
#define HLW8032_h
#include "driver/gpio.h"
void hw8032_init(void);
void hw8032_deinit(void);
void reset_energy_data(void);
#endifHLW8032_ESP.c
#include "HLW8032_ESP82.h"
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "lwrb.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "nvs_config.h"
#include "esp_err.h"
#include <time.h>
#include "iot_mqtt.h"
lwrb_t lwrb_hlw8032; // 定义环形缓冲区对象
volatile uint8_t lwrb_hlw8032_buffer[2048 + 1]; // 定义缓冲区内存空间
// 宏定义原型 (通常在esp_err.h中定义)
#define ESP_RETURN_ON_ERROR(x, tag, msg) \
do \
{ \
esp_err_t __err_rc = (x); \
if (__err_rc != ESP_OK) \
{ \
ESP_LOGE(tag, "%s: %s", msg, esp_err_to_name(__err_rc)); \
return __err_rc; \
} \
} while (0)
#define UART_PORT_NUM UART_NUM_0
#define RX_BUF_SIZE 1024
#define BAUD_RATE 4800
uint16_t old_reg = 0;
uint32_t k = 0;
TaskHandle_t hlw8032_parser_taskHandle = NULL;
TaskHandle_t hlw8032_taskHandle = NULL;
TaskHandle_t u_mqtt_taskHandle = NULL;
// HLW8032寄存器定义
typedef struct
{
uint8_t state_reg;
uint32_t voltage_param;
uint32_t voltage_val;
float real_voltage_val;
uint32_t current_param;
uint32_t current_val;
float real_current_val;
uint32_t power_param; // 功率参数寄存器 5313000
uint32_t power_val;
float active_power; // 有功功率
uint8_t data_update;
uint32_t pf_counter;
uint8_t checksum;
} hlw8032_frame_t;
static hlw8032_frame_t frame;
static void parse_hlw8032_data(uint8_t *data, hlw8032_frame_t *frame_p);
static uint32_t calculate_pulse_delta(uint32_t current, uint32_t last);
static uint32_t calculate_pulse_per_kwh(hlw8032_frame_t *frame_p);
// 解析成功标识位
volatile uint8_t parse_success = 0;
// 在文件顶部添加宏定义
#define HLW8032_COUNTER_MAX 0xFFFFFFFF // 24位计数器最大值(16,777,215)
#define MAX_REASONABLE_DELTA 10000 // 合理增量阈值(根据实际用电情况调整)
static QueueHandle_t uart_queue;
static const char *TAG = "HLW_P";
// static const uint32_t SAVE_INTERVAL = 3600000; // 1小时保存一次到NVS(毫秒)
static const uint32_t SAVE_INTERVAL = 60000; // 1分钟保存一次到NVS(毫秒)
// 1. 优化全局变量定义区
typedef struct
{
float voltage_coef; // 电压系数
float current_coef; // 电流系数
float daily_energy; // 当日用电量(kWh)
float total_energy; // 累计总用电量(kWh)
uint32_t last_pulse; // 上次脉冲计数值
uint32_t last_day_check; // 上次日期检查时间
uint8_t current_day; // 当前日期(1-31)
uint32_t last_save; // 上次保存时间
bool initialized; // 初始化标志
} hlw8032_ctx_t;
static hlw8032_ctx_t ctx = {
.voltage_coef = 1.88f,
.current_coef = 1.0f,
.total_energy = 0.0f,
.initialized = false};
// 2. 优化NVS存储函数
static esp_err_t hlw8032_save_energy()
{
nvs_handle_t handle;
ESP_RETURN_ON_ERROR(nvs_open("hlw8032", NVS_READWRITE, &handle), TAG, "NVS open failed");
// 获取当前时间戳作为版本号
uint32_t version = (uint32_t)time(NULL);
// 主备份存储
ESP_RETURN_ON_ERROR(nvs_set_blob(handle, "energy_main", &ctx.total_energy, sizeof(ctx.total_energy)), TAG, "Save main failed");
// 保存ctx.daily_energy
ESP_RETURN_ON_ERROR(nvs_set_blob(handle, "daily_energy", &ctx.daily_energy, sizeof(ctx.daily_energy)), TAG, "Save daily energy failed");
// 保存
ESP_RETURN_ON_ERROR(nvs_set_u32(handle, "energy_ver", version), TAG, "Save main version failed");
// 次备份存储
ESP_RETURN_ON_ERROR(nvs_set_blob(handle, "energy_backup", &ctx.total_energy, sizeof(ctx.total_energy)), TAG, "Save backup failed");
// 保存ctx.daily_energy
ESP_RETURN_ON_ERROR(nvs_set_blob(handle, "daily_energy_bk", &ctx.daily_energy, sizeof(ctx.daily_energy)), TAG, "Save backup daily energy failed");
ESP_RETURN_ON_ERROR(nvs_set_u32(handle, "energy_ver_bk", version), TAG, "Save backup version failed");
ESP_RETURN_ON_ERROR(nvs_commit(handle), TAG, "Commit failed");
nvs_close(handle);
return ESP_OK;
}
// 修改加载函数实现双备份恢复
static esp_err_t hlw8032_load_energy(void)
{
nvs_handle_t handle;
ESP_RETURN_ON_ERROR(nvs_open("hlw8032", NVS_READWRITE, &handle), TAG, "_________________NVS open failed");
float main_energy = 0.0f;
float daily_energy = 0.0f;
float backup_energy = 0.0f;
float daily_energy_bk = 0.0f;
uint32_t main_ver = 0;
uint32_t backup_ver = 0;
uint32_t version = time(NULL);
// 读取主备份
size_t len = sizeof(main_energy);
esp_err_t main_ret = nvs_get_blob(handle, "energy_main", &main_energy, &len);
if (main_ret == ESP_ERR_NVS_NOT_FOUND)
{
ESP_LOGW(TAG, "Energy data not found in NVS, initializing to 0.0");
ctx.total_energy = 0.0f;
// 尝试写入初始值
esp_err_t main_ret_init = nvs_set_blob(handle, "energy_main", &ctx.total_energy, sizeof(ctx.total_energy));
if (main_ret_init == ESP_OK)
{
main_ret_init = nvs_commit(handle);
if (main_ret_init != ESP_OK)
{
ESP_LOGE(TAG, "Failed to commit initial energy value: 0x%x (%s)",
main_ret_init, esp_err_to_name(main_ret_init));
}
}
else
{
ESP_LOGE(TAG, "Failed to write initial energy value: 0x%x (%s)",
main_ret_init, esp_err_to_name(main_ret_init));
}
}
else
{
ESP_LOGE(TAG, "load energy_main data: 0x%x (%s)", main_ret, esp_err_to_name(main_ret));
}
// 读取ctx.daily_energy
len = sizeof(daily_energy);
esp_err_t daily_ret = nvs_get_blob(handle, "daily_energy", &daily_energy, &len);
if (daily_ret == ESP_ERR_NVS_NOT_FOUND)
{
ESP_LOGW(TAG, "Daily energy data not found in NVS, initializing to 0.0");
// 尝试写入初始值
esp_err_t daily_ret_init = nvs_set_blob(handle, "daily_energy", &daily_energy, sizeof(daily_energy));
if (daily_ret_init == ESP_OK)
{
daily_ret_init = nvs_commit(handle);
if (daily_ret_init != ESP_OK)
{
ESP_LOGE(TAG, "Failed to commit initial daily energy value: 0x%x (%s)",
daily_ret_init, esp_err_to_name(daily_ret_init));
}
}
else
{
ESP_LOGE(TAG, "Failed to write initial daily energy value: 0x%x (%s)",
daily_ret_init, esp_err_to_name(daily_ret_init));
}
}
else
{
ESP_LOGE(TAG, "load daily energy data: 0x%x (%s)", daily_ret, esp_err_to_name(daily_ret));
}
// 读取主备份版本
esp_err_t main_ver_ret = nvs_get_u32(handle, "energy_ver", &main_ver);
if (main_ver_ret == ESP_ERR_NVS_NOT_FOUND)
{
ESP_LOGW(TAG, "energy_ver data not found in NVS, initializing to 0.0");
// 尝试写入初始值
esp_err_t main_ret_init = nvs_set_u32(handle, "energy_ver", version);
if (main_ret_init == ESP_OK)
{
main_ret_init = nvs_commit(handle);
if (main_ret_init != ESP_OK)
{
ESP_LOGE(TAG, "Failed to commit initial energy value: 0x%x (%s)",
main_ret_init, esp_err_to_name(main_ret_init));
}
}
else
{
ESP_LOGE(TAG, "Failed to write initial energy value: 0x%x (%s)",
main_ret_init, esp_err_to_name(main_ret_init));
}
}
else
{
ESP_LOGE(TAG, "load energy_ver: 0x%x (%s)", main_ret, esp_err_to_name(main_ret));
}
// 读取次备份
len = sizeof(backup_energy);
esp_err_t backup_ret = nvs_get_blob(handle, "energy_backup", &backup_energy, &len);
if (backup_ret == ESP_ERR_NVS_NOT_FOUND)
{
ESP_LOGW(TAG, "Backup energy data not found in NVS, initializing to 0.0");
ctx.total_energy = 0.0f;
// 尝试写入初始值
esp_err_t backup_ret_init = nvs_set_blob(handle, "energy_backup", &ctx.total_energy, sizeof(ctx.total_energy));
if (backup_ret_init == ESP_OK)
{
backup_ret_init = nvs_commit(handle);
if (backup_ret_init != ESP_OK)
{
ESP_LOGE(TAG, "Failed to commit initial backup energy value: 0x%x (%s)",
backup_ret_init, esp_err_to_name(backup_ret_init));
}
}
else
{
ESP_LOGE(TAG, "Failed to write initial backup energy value: 0x%x (%s)",
backup_ret_init, esp_err_to_name(backup_ret_init));
}
}
else
{
ESP_LOGE(TAG, "load backup energy data: 0x%x (%s)", backup_ret, esp_err_to_name(backup_ret));
}
// 读取次备份日用电量
len = sizeof(daily_energy_bk);
esp_err_t daily_bk_ret = nvs_get_blob(handle, "daily_energy_bk", &daily_energy_bk, &len);
if (daily_bk_ret == ESP_ERR_NVS_NOT_FOUND)
{
ESP_LOGW(TAG, "Backup daily energy data not found in NVS, initializing to 0.0");
// 尝试写入初始值
esp_err_t daily_bk_ret_init = nvs_set_blob(handle, "daily_energy_bk", &daily_energy_bk, sizeof(daily_energy_bk));
if (daily_bk_ret_init == ESP_OK)
{
daily_bk_ret_init = nvs_commit(handle);
if (daily_bk_ret_init != ESP_OK)
{
ESP_LOGE(TAG, "Failed to commit initial backup daily energy value: 0x%x (%s)",
daily_bk_ret_init, esp_err_to_name(daily_bk_ret_init));
}
}
else
{
ESP_LOGE(TAG, "Failed to write initial backup daily energy value: 0x%x (%s)",
daily_bk_ret_init, esp_err_to_name(daily_bk_ret_init));
}
}
else
{
ESP_LOGE(TAG, "load backup daily energy data: 0x%x (%s)", daily_bk_ret, esp_err_to_name(daily_bk_ret));
}
esp_err_t backup_ver_ret = nvs_get_u32(handle, "energy_ver_bk", &backup_ver);
if (backup_ver_ret == ESP_ERR_NVS_NOT_FOUND)
{
ESP_LOGW(TAG, "Backup energy version data not found in NVS, initializing to 0.0");
// 尝试写入初始值
esp_err_t backup_ret_init = nvs_set_u32(handle, "energy_ver_bk", version);
if (backup_ret_init == ESP_OK)
{
backup_ret_init = nvs_commit(handle);
if (backup_ret_init != ESP_OK)
{
ESP_LOGE(TAG, "Failed to commit initial backup energy value: 0x%x (%s)",
backup_ret_init, esp_err_to_name(backup_ret_init));
}
}
else
{
ESP_LOGE(TAG, "Failed to write initial backup energy value: 0x%x (%s)",
backup_ret_init, esp_err_to_name(backup_ret_init));
}
}
else
{
ESP_LOGE(TAG, "load backup energy version data: 0x%x (%s)", backup_ver_ret, esp_err_to_name(backup_ver_ret));
}
// 选择最新有效数据
if (main_ret == ESP_OK && backup_ret == ESP_OK)
{
ctx.total_energy = (main_ver >= backup_ver) ? main_energy : backup_energy;
}
else if (main_ret == ESP_OK)
{
ctx.total_energy = main_energy;
}
else if (backup_ret == ESP_OK)
{
ctx.total_energy = backup_energy;
}
else
{
ctx.total_energy = 0.0f;
ESP_LOGW(TAG, "No valid energy data found, initialized to 0");
}
if (daily_ret == ESP_OK && daily_bk_ret == ESP_OK)
{
ctx.daily_energy = (main_ver >= backup_ver) ? daily_energy : daily_energy_bk;
}
else if (daily_ret == ESP_OK)
{
ctx.daily_energy = daily_energy;
}
else if (daily_bk_ret == ESP_OK)
{
ctx.daily_energy = daily_energy_bk;
}
else
{
ctx.daily_energy = 0.0f;
ESP_LOGW(TAG, "No valid daily energy data found, initialized to 0");
}
ESP_LOGI(TAG, "Loaded total energy: %d.%04d kWh, daily energy: %d.%04d kWh",
(int)ctx.total_energy, (int)(ctx.total_energy * 10000) % 10000,
(int)ctx.daily_energy, (int)(ctx.daily_energy * 10000) % 10000);
nvs_close(handle);
ctx.initialized = true;
return ESP_OK;
}
// 3. 优化数据解析任务
void hlw8032_task(void *pvParameters)
{
uint8_t buf[24];
// 初始化日用电量统计
time_t now;
time(&now);
struct tm *timeinfo = localtime(&now);
ctx.current_day = timeinfo->tm_mday;
while (1)
{
static int32_t res = -1;
if (lwrb_get_full(&lwrb_hlw8032) >= sizeof(buf))
{
lwrb_peek(&lwrb_hlw8032, 0, buf, sizeof(buf));
// 协议头验证 (0x5A after non-0xAA)
if (buf[0] != 0xAA && buf[1] == 0x5A)
{
// 校验和验证
uint8_t checksum = 0;
for (int i = 2; i < 23; i++)
checksum += buf[i];
if ((checksum & 0xFF) == buf[23])
{
// 解析有效数据
parse_hlw8032_data(buf, &frame);
// 处理脉冲计数
if (ctx.initialized)
{
uint32_t delta = calculate_pulse_delta(frame.pf_counter, ctx.last_pulse);
float energy_delta = (float)delta / (float)calculate_pulse_per_kwh(&frame);
ctx.total_energy += energy_delta;
ctx.daily_energy += energy_delta; // 仅内存计算
ctx.last_pulse = frame.pf_counter;
// 每日电量统计检查 (每1分钟检查一次)
if (xTaskGetTickCount() - ctx.last_day_check >= pdMS_TO_TICKS(60000))
{
time_t now;
time(&now);
struct tm *timeinfo = localtime(&now);
if (timeinfo->tm_mday != ctx.current_day)
{
ESP_LOGI(TAG, "New day detected, reset daily energy. Yesterday: %d.%02d kWh", (int)ctx.daily_energy, (int)(ctx.daily_energy * 100) % 100);
char __post_str[100] = {0};
memset(__post_str, 0, sizeof(__post_str));
int daily_energy_int = (int)(ctx.daily_energy * 10000);
snprintf(__post_str, sizeof(__post_str), "{\"default:day_energy\":%d.%04d}",
daily_energy_int / 10000, abs(daily_energy_int % 10000)); // 日用电量 (0.0001kWh));
res = _send_property_post(dm_handle, __post_str);
if (res >= 0)
{
res = -1;
ctx.daily_energy = 0.0f;
hlw8032_save_energy();
ctx.current_day = timeinfo->tm_mday;
}
}
ctx.last_day_check = xTaskGetTickCount();
}
// 定期保存
if (xTaskGetTickCount() * portTICK_PERIOD_MS - ctx.last_save >= SAVE_INTERVAL)
{
ESP_LOGI(TAG, "%d.%04d kWh", (int)ctx.total_energy, (int)(ctx.total_energy * 10000) % 10000);
hlw8032_save_energy();
ctx.last_save = xTaskGetTickCount() * portTICK_PERIOD_MS;
}
}
lwrb_skip(&lwrb_hlw8032, sizeof(buf));
continue;
}
else
{
lwrb_skip(&lwrb_hlw8032, 1);
ESP_LOGW(TAG, "checksum skipping 1 byte");
}
}
else
{
lwrb_skip(&lwrb_hlw8032, 1);
ESP_LOGW(TAG, "start skipping 1 byte");
}
// 延时1ms
vTaskDelay(pdMS_TO_TICKS(1));
}
}
}
void reset_energy_data(void)
{
// 重置ctx.total_energy和ctx.daily_energy
ctx.total_energy = 0.0f;
ctx.daily_energy = 0.0f;
ctx.last_pulse = 0;
ctx.last_day_check = 0;
ctx.current_day = 1; // 重置为1号
ctx.last_save = 0;
// 保存到NVS
hlw8032_save_energy();
ESP_LOGI(TAG, "Energy data reset to zero.");
}
// 4. 新增辅助函数
static uint32_t calculate_pulse_delta(uint32_t current, uint32_t last)
{
return (current >= last) ? (current - last) : (HLW8032_COUNTER_MAX - last + current + 1);
}
static uint32_t calculate_pulse_per_kwh(hlw8032_frame_t *frame_p)
{
return ((100000 * 3600) / (frame_p->power_param * ctx.voltage_coef * ctx.current_coef)) * 10000; // 360416
}
static void parse_hlw8032_data(uint8_t *data, hlw8032_frame_t *frame_p)
{
frame_p->voltage_param = (data[2] << 16) | (data[3] << 8) | data[4];
frame_p->voltage_val = (data[5] << 16) | (data[6] << 8) | data[7];
frame_p->real_voltage_val = ((float)frame_p->voltage_param / (float)frame_p->voltage_val) * ctx.voltage_coef; // 计算电压值,1.88为电压系数,根据所采用的分压电阻大小来确定
frame_p->current_param = (data[8] << 16) | (data[9] << 8) | data[10];
frame_p->current_val = (data[11] << 16) | (data[12] << 8) | data[13];
frame_p->real_current_val = ((float)frame_p->current_param / (float)frame_p->current_val) * ctx.current_coef; // 计算电流值,1.88为电流系数,根据所采用的分压电阻大小来确定
// ESP_LOGI(TAG, "v v: %d.%02dV; c v: %d.%02dA", (int)frame->real_voltage_val, (int)(frame->real_voltage_val * 100) % 100, (int)frame->real_current_val, (int)(frame->real_current_val * 100) % 100);
if (data[0] > 0xf0) // 判断实时功率是否未溢出
{
ESP_LOGI(TAG, "no e"); //
}
else
{
frame_p->power_param = (data[14] << 16) | (data[15] << 8) | data[16]; // 计算功率参数寄存
frame_p->power_val = (data[17] << 16) | (data[18] << 8) | data[19]; // 计算功率寄存器
frame_p->active_power = (frame_p->power_param / frame_p->power_val) * ctx.voltage_coef * ctx.current_coef; // 计算有效功率
// ESP_LOGI(TAG, "a p: %d.%02dW", (int)frame_p->active_power, (int)(frame_p->active_power * 100) % 100);
}
uint16_t reggg = (data[20] & 0x80);
if (reggg != old_reg) // 判断数据更新寄存器最高位有没有翻转
{
k++;
old_reg = reggg;
}
frame_p->pf_counter = (k << 16) | (data[21] << 8) | data[22];
// uint32_t pulse_per_kwh = calculate_pulse_per_kwh(frame_p);
// double E_con = ((frame_p->pf_counter*10000.0f)/pulse_per_kwh) / 10000.0f; // 计算累计用电量,单位为kWh
// ESP_LOGI(TAG, "%d,%d,%d,e=%d.%04d kWh",pulse_per_kwh,frame_p->power_param,frame_p->pf_counter, (uint32_t)E_con, (uint32_t)(E_con * 10000) % 10000);
}
// 修改u_mqtt_task函数以发送累计用电量
void u_mqtt_task(void *pvParameters)
{
char __post_str[500] = {0};
while (1)
{
if (ctx.initialized)
{
memset(__post_str, 0, sizeof(__post_str));
// 1. 将浮点值转换为整数(单位:0.0001A, 0.01V, 0.0001W, 0.0001kWh)
int current_int = (int)(frame.real_current_val * 10000);
int voltage_int = (int)(frame.real_voltage_val * 100);
int power_int = (int)(frame.active_power * 10000);
int daily_energy_int = (int)(ctx.daily_energy * 10000);
int total_energy_int = (int)(ctx.total_energy * 10000);
// 2. 构建JSON字符串
int len = snprintf(__post_str, sizeof(__post_str),
"{\"default:current\":%d.%04d,\"default:voltage\":%d.%02d,"
"\"default:active_power\":%d.%04d,\"default:day_use_energy\":%d.%04d,"
"\"default:total_energy\":%d.%04d}",
current_int / 10000, abs(current_int % 10000), // 电流 (0.0001A)
voltage_int / 100, abs(voltage_int % 100), // 电压 (0.01V)
power_int / 10000, abs(power_int % 10000), // 功率 (0.0001W)
daily_energy_int / 10000, abs(daily_energy_int % 10000), // 日用电量 (0.0001kWh)
total_energy_int / 10000, abs(total_energy_int % 10000) // 总用电量 (0.0001kWh)
);
if (len >= sizeof(__post_str))
{
ESP_LOGW(TAG, "MQTT message truncated! Required:%d, Available:%zu", len, sizeof(__post_str));
}
_send_property_post(dm_handle, __post_str);
}
vTaskDelay(pdMS_TO_TICKS(4000));
}
}
// 数据包解析任务
void hlw8032_parser_task(void *pvParameters)
{
uart_event_t event;
uint8_t dtmp[RX_BUF_SIZE] = {0};
while (1)
{
if (xQueueReceive(uart_queue, (void *)&event, portMAX_DELAY))
{
bzero(dtmp, RX_BUF_SIZE);
switch (event.type)
{
// Event of UART receving data
// We'd better handler data event fast, there would be much more data events than
// other types of events. If we take too much time on data event, the queue might be full.
case UART_DATA:
{
// ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
lwrb_sz_t available = lwrb_get_free(&lwrb_hlw8032);
if (available >= event.size)
{
int read_bytes = uart_read_bytes(UART_PORT_NUM, dtmp, event.size, portMAX_DELAY);
if (read_bytes > 0)
{
lwrb_sz_t written = lwrb_write(&lwrb_hlw8032, dtmp, read_bytes);
}
}
}
break;
// Event of HW FIFO overflow detected
case UART_FIFO_OVF:
// ESP_LOGI(TAG, "hw fifo overflow");
// If fifo overflow happened, you should consider adding flow control for your application.
// The ISR has already reset the rx FIFO,
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(UART_PORT_NUM);
xQueueReset(uart_queue);
break;
// Event of UART ring buffer full
case UART_BUFFER_FULL:
// ESP_LOGI(TAG, "ring buffer full");
// If buffer full happened, you should consider encreasing your buffer size
// As an example, we directly flush the rx buffer here in order to read more data.
uart_flush_input(UART_PORT_NUM);
xQueueReset(uart_queue);
break;
case UART_PARITY_ERR:
// ESP_LOGI(TAG, "uart parity error");
break;
// Event of UART frame error
case UART_FRAME_ERR:
// ESP_LOGI(TAG, "uart frame error");
break;
// Others
default:
// ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
}
void hw8032_init(void)
{
// 初始化UART
uart_config_t uart_config = {
.baud_rate = BAUD_RATE,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_EVEN,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
};
hlw8032_load_energy();
// 初始化lwrb
uint8_t ret = lwrb_init(&lwrb_hlw8032, lwrb_hlw8032_buffer, sizeof(lwrb_hlw8032_buffer));
ESP_LOGI(TAG, "lwrb init %d", ret);
uart_param_config(UART_PORT_NUM, &uart_config);
uart_driver_install(UART_PORT_NUM, RX_BUF_SIZE * 2, RX_BUF_SIZE * 2, 10, &uart_queue, 0);
// 创建解析任务
xTaskCreate(&hlw8032_parser_task, "hlw8032_parser", 2048, NULL, 1, &hlw8032_parser_taskHandle);
// 创建一个解析任务
xTaskCreate(&hlw8032_task, "hlw8032", 2048, NULL, 0, &hlw8032_taskHandle);
// 新建一个任务定期上传数据到mqtt平台
xTaskCreate(&u_mqtt_task, "u_mqtt_task", 2048, NULL, 0, &u_mqtt_taskHandle);
}
void hw8032_deinit(void)
{
// 删除解析任务
vTaskDelete(hlw8032_parser_taskHandle);
// 删除数据处理任务
vTaskDelete(hlw8032_taskHandle);
// 删除MQTT上传任务
vTaskDelete(u_mqtt_taskHandle);
}