/****************************************************************************** * @file app_th.c * @brief CBR3 温湿度采集实现 * @author cyWu <1917507415@qq.com> * @date 2026.08.29 * @version V1.0.0,首次发布 ******************************************************************************/ #include "app_th.h" #include "bsp_aht20.h" #include "board_pin.h" #include "system/includes.h" #define LOG_TAG_CONST APP #define LOG_TAG "[APP_TH]" #define LOG_ERROR_ENABLE #define LOG_INFO_ENABLE #include "debug.h" extern u32 timer_get_ms(void); extern void clr_wdt(void); /** 采样状态机 */ typedef enum { TH_ST_IDLE = 0, /**< 空闲,等待下一个采样周期 */ TH_ST_WAIT_DATA /**< 命令已发出,等 ≥80ms 后读数 */ } ThState_t; typedef struct { uint8_t inited; ThState_t state; uint16_t poll_ms; /**< 距上次采样的累计毫秒 */ uint32_t wait_t0; /**< 测量命令发出时刻 */ int16_t temp_x10; /**< 最近有效温度 ×10 */ uint8_t humi; /**< 最近有效湿度 % */ uint8_t valid; /**< 1=有有效采样 */ uint8_t fail_cnt; /**< 连续失败次数 */ uint8_t last_ok; /**< 最近一次采样是否成功(P2 条件引擎 8.4 用) */ } AppThCtx_t; static AppThCtx_t s_th; /** * @brief 初始化温湿度模块 * @return 无 */ void app_th_init(void) { #if !BOARD_TH_ENABLE log_info("th disabled\n"); return; #endif if (s_th.inited) { return; } bsp_aht20_init(); s_th.state = TH_ST_IDLE; s_th.poll_ms = 0; s_th.valid = 0; s_th.fail_cnt = 0; s_th.last_ok = 0; s_th.inited = 1; log_info("th init period=%ums\n", (unsigned)BOARD_TH_PERIOD_MS); } /** * @brief 业务节拍:内部 2s 才真正采一次;IO 分离后采集与显示互不干扰 * @param dt 距上次调用的毫秒数 * @return 无 */ void app_th_poll(uint16_t dt) { #if !BOARD_TH_ENABLE (void)dt; return; #endif if (!s_th.inited) { return; } if (s_th.state == TH_ST_IDLE) { s_th.poll_ms = (uint16_t)(s_th.poll_ms + dt); if (s_th.poll_ms >= BOARD_TH_PERIOD_MS) { s_th.poll_ms = 0; if (bsp_aht20_measure_start() == 0) { s_th.state = TH_ST_WAIT_DATA; s_th.wait_t0 = timer_get_ms(); } /* measure_start 非 0=通讯失败,跳过本次采样 */ } } else if (s_th.state == TH_ST_WAIT_DATA) { clr_wdt(); if ((timer_get_ms() - s_th.wait_t0) >= BOARD_AHT20_WAIT_MS) { int16_t t = 0; uint8_t h = 0; int8_t ret = bsp_aht20_measure_finish(&t, &h); /* IO 分离后无总线竞争,finish 不会返回 -2;0=成功,-1=通讯失败 */ s_th.state = TH_ST_IDLE; if (ret == 0) { s_th.temp_x10 = t; s_th.humi = h; s_th.fail_cnt = 0; s_th.valid = 1; s_th.last_ok = 1; log_info("th %d.%dC %d%%\n", (int)(t / 10), (int)((t < 0) ? (-t % 10) : (t % 10)), h); } else { s_th.fail_cnt++; s_th.last_ok = 0; log_error("th sample fail %d\n", s_th.fail_cnt); } } } } /** * @brief 是否已有有效采样 * @return 1=有效,0=从未成功 */ uint8_t app_th_get_valid(void) { return s_th.valid; } /** * @brief 最近一次有效温度 * @return 温度 ×10 */ int16_t app_th_get_temp_x10(void) { return s_th.temp_x10; } /** * @brief 最近一次有效湿度 * @return 湿度 0~100 整数 % */ uint8_t app_th_get_humi(void) { return s_th.humi; } /** * @brief 连续失败次数 * @return 连续失败次数 */ uint8_t app_th_get_fail_cnt(void) { return s_th.fail_cnt; } /** * @brief 传感器故障(连续失败 ≥ BOARD_TH_FAIL_MAX) * @return 1=故障(显示 --、fault_code=2),0=正常 */ uint8_t app_th_is_fault(void) { return (s_th.fail_cnt >= BOARD_TH_FAIL_MAX) ? 1 : 0; } /** * @brief 最近一次采样是否成功(P2 条件引擎 8.4:时长只在采样成功时累加) * @return 1=成功,0=失败/未采样过 */ uint8_t app_th_last_sample_ok(void) { return s_th.last_ok; }