| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- /*
- * Hardware Detection Module - v2.3
- *
- * 功能:检测硬件外设状态
- * - 倾倒开关(PB10引脚下降沿中断检测,100ms轮询)
- * - 雨控检测(PC0输出高电平,PC1输入检测,每30秒检测一次)
- * - 单线程设计,优先级9,确保倾倒检测及时响应
- *
- * Version: 2.3.0
- */
- /*********************↓ include ↓************************/
- #define DBG_TAG "HW"
- #define DBG_LVL DBG_INFO
- #include <rtdbg.h>
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include "ecode.h"
- #include "ym310_protecl.h" /* for sys_sta and sys_sta */
- /*********************↑ include ↑************************/
- /*********************↓ define ↓************************/
- /* 倾倒开关配置 */
- #define TILT_SWITCH_PIN GET_PIN(B, 10) /* PB10引脚 */
- #define TILT_IRQ_MODE PIN_IRQ_MODE_FALLING /* 下降沿触发 */
- #define TILT_DEBOUNCE_MS 50 /* 防抖时间(毫秒) */
- #define TILT_CLEAR_TIMEOUT_MS (60 * 1000) /* 保护清除时间(毫秒)- 60秒 */
- #define TILT_POLL_INTERVAL_MS 100 /* 轮询周期(毫秒) */
- #define TILT_TRIGGER_MS 1000 /* 持续触发时间(毫秒)- 1秒 */ //
- /* 雨控检测配置 */
- #define RAIN_OUT_PIN GET_PIN(C, 0) /* PC0 输出引脚 */
- #define RAIN_IN_PIN GET_PIN(C, 1) /* PC1 输入引脚 */
- #define RAIN_DETECT_INTERVAL_MS (20 * 1000) /* 检测间隔(毫秒)- 30秒 */
- #define RAIN_CLEAR_TIMEOUT_MS (3 * 60 * 1000) /* 保护清除时间(毫秒)- 3分钟 */
- #define RAIN_POWER_ON_DELAY_MS (10 * 1000) /* 上电后延迟(毫秒) */
- /*********************↑ define ↑************************/
- /*********************↓ 静态变量 ↓************************/
- /* 倾倒开关相关 */
- static rt_tick_t s_tilt_last_tick = 0; /* 上次触发时间 */
- static rt_tick_t s_tilt_start_tick = 0; /* 当前倾倒开始时间 */
- static struct rt_semaphore tilt_sem; /* 中断信号量 */
- static rt_tick_t s_tilt_trigger_start = 0; /* 倾倒持续开始时间(新增)*/
- /* 雨控检测相关 */
- static rt_tick_t s_rain_last_detect_tick = 0; /* 上次检测时间 */
- static rt_tick_t s_rain_start_tick = 0; /* 雨控开始时间 */
- /* 线程相关 */
- static rt_thread_t s_hw_thread = RT_NULL; /* 工作线程句柄 */
- static rt_bool_t s_hw_running = RT_FALSE; /* 线程运行标志 */
- /*********************↑ 静态变量 ↑************************/
- extern SYS_STATUS sys_sta;
- extern void report_now(void);
- /*********************↓ 倾倒开关函数 ↓***********************/
- /**
- * @brief 倾倒开关中断服务函数
- */
- static void tilt_isr(void *args)
- {
- rt_tick_t current_tick = rt_tick_get();
- /* 防抖处理 */
- if ((current_tick - s_tilt_last_tick) < rt_tick_from_millisecond(TILT_DEBOUNCE_MS))
- {
- return;
- }
- s_tilt_last_tick = current_tick;
- /* 通知工作线程处理 */
- rt_sem_release(&tilt_sem);
- }
- /**
- * @brief 处理倾倒开关检测(持续1秒才触发保护)
- */
- static void tilt_process(void)
- {
- int pin_level;
- uint32_t now_ms;
- uint32_t elapsed;
- pin_level = rt_pin_read(TILT_SWITCH_PIN);
- now_ms = rt_tick_get_millisecond();
- /* ========== 触发逻辑:持续1秒触发保护 ========== */
- if (pin_level == PIN_LOW)
- {
- /* 倾倒状态:开始计时或继续计时 */
- if (s_tilt_trigger_start == 0)
- {
- s_tilt_trigger_start = now_ms;
- LOG_D("[TILT] Tilt detected, start counting...");
- }
- elapsed = now_ms - s_tilt_trigger_start;
- if (elapsed >= TILT_TRIGGER_MS)
- {
- /* 持续倾倒超过1秒,触发保护 */
- if (sys_sta.tilt_protect != VALID)
- {
- sys_sta.tilt_protect = VALID;
- s_tilt_start_tick = now_ms; /* 记录保护触发时间 */
- LOG_W("[TILT] Triggered! Tilt持续 %lu ms, protect = VALID", elapsed);
- Recode_e_code(e_tilt_trigger, 1, "倾倒开关触发");
- gpio_lamp_ctrl(0);
- gpio_hv_ctrl(0);
- report_now();
- }
- /* 保护已触发,不需要额外操作 */
- }
- }
- else
- {
- /* 非倾倒状态:重置触发计时器 */
- if (s_tilt_trigger_start != 0)
- {
- LOG_D("[TILT] Tilt cleared, reset counter");
- s_tilt_trigger_start = 0;
- }
- }
- /* ========== 清除逻辑:倾倒恢复后60秒清除保护 ========== */
- if (sys_sta.tilt_protect == VALID)
- {
- if (pin_level != PIN_LOW)
- {
- /* 当前未倾倒,开始或继续清除计时 */
- if (s_tilt_start_tick == 0)
- {
- /* 刚恢复,开始计时 */
- s_tilt_start_tick = now_ms;
- LOG_D("[TILT] Recovered, start clear countdown");
- }
- elapsed = now_ms - s_tilt_start_tick;
- if (elapsed >= TILT_CLEAR_TIMEOUT_MS)
- {
- /* 恢复时间达到60秒,清除保护 */
- sys_sta.tilt_protect = 0;
- s_tilt_start_tick = 0;
- s_tilt_trigger_start = 0;
- LOG_I("[TILT] Protect cleared after %d sec", TILT_CLEAR_TIMEOUT_MS / 1000);
- Recode_e_code(e_tilt_restore, 0, "倾倒保护清除");
- rt_thread_mdelay(1000);
- report_now();
- }
- }
- else
- {
- /* 当前仍在倾倒,重置清除计时器(不清除保护)*/
- if (s_tilt_start_tick != 0)
- {
- LOG_D("[TILT] Still tilted, reset clear timer");
- s_tilt_start_tick = 0;
- }
- }
- }
- }
- /**
- * @brief 初始化倾倒开关
- */
- static void tilt_init(void)
- {
- rt_err_t ret;
- int pin_level;
- // LOG_I("[TILT] Initializing on PB10...");
- ret = rt_sem_init(&tilt_sem, "tilt_sem", 0, RT_IPC_FLAG_FIFO);
- if (ret != RT_EOK)
- {
- LOG_E("[TILT] Failed to init semaphore");
- return;
- }
- rt_pin_mode(TILT_SWITCH_PIN, PIN_MODE_INPUT_PULLUP);
- pin_level = rt_pin_read(TILT_SWITCH_PIN);
- if (pin_level == PIN_LOW)
- {
- LOG_W("[TILT] Initially TRIGGERED!");
- sys_sta.tilt_protect = VALID;
- s_tilt_start_tick = rt_tick_get();
- Recode_e_code(e_tilt_trigger, 1, "倾倒开关初始状态为触发");
- gpio_lamp_ctrl(0);
- gpio_hv_ctrl(0);
- report_now();
- }
- else
- {
- // LOG_I("[TILT] Initially normal");
- sys_sta.tilt_protect = 0;
- s_tilt_start_tick = 0;
- }
- ret = rt_pin_attach_irq(TILT_SWITCH_PIN, TILT_IRQ_MODE, tilt_isr, NULL);
- if (ret != RT_EOK)
- {
- LOG_E("[TILT] Failed to attach IRQ");
- return;
- }
- ret = rt_pin_irq_enable(TILT_SWITCH_PIN, PIN_IRQ_ENABLE);
- if (ret != RT_EOK)
- {
- LOG_E("[TILT] Failed to enable IRQ");
- return;
- }
- // LOG_I("[TILT] Initialized (poll %dms, clear after %d sec)",
- // TILT_POLL_INTERVAL_MS, TILT_CLEAR_TIMEOUT_MS / 1000);
- }
- /*********************↑ 倾倒开关函数 ↑***********************/
- /*********************↓ 雨控检测函数 ↓***********************/
- /**
- * @brief 执行一次雨控检测
- * @return 1:有雨,0:无雨
- */
- static int rain_detect_once(void)
- {
- int result = 0;
- int in_level = rt_pin_read(RAIN_IN_PIN);
- if (in_level == PIN_LOW)
- {
- result = 1;
- LOG_D("[RAIN] Detected! PC1=LOW");
- }
- else
- {
- LOG_D("[RAIN] No rain, PC1=HIGH");
- }
- rt_pin_mode(RAIN_OUT_PIN, PIN_MODE_INPUT);
- return result;
- }
- /**
- * @brief 处理雨控检测
- */
- static void rain_process(void)
- {
- int has_rain;
- rt_tick_t now = rt_tick_get();
- static rt_tick_t ready = 0;
- if ((now - s_rain_last_detect_tick) < rt_tick_from_millisecond(RAIN_DETECT_INTERVAL_MS))
- {
- return;
- }
- if (ready == 0)
- {
- // LOG_I(" RAIN:time take ");
- ready = now;
- }
- rt_pin_mode(RAIN_OUT_PIN, PIN_MODE_OUTPUT);
- rt_pin_write(RAIN_OUT_PIN, PIN_HIGH);
- rt_pin_mode(RAIN_IN_PIN, PIN_MODE_INPUT_PULLUP);
- if ((now - ready) < rt_tick_from_millisecond(RAIN_POWER_ON_DELAY_MS))
- {
- return;
- }
- // LOG_I(" RAIN:time start ");
- ready = 0;
- s_rain_last_detect_tick = now;
- has_rain = rain_detect_once();
- if (has_rain)
- {
- if (sys_sta.rain_protect != VALID)
- {
- sys_sta.rain_protect = VALID;
- s_rain_start_tick = now;
- // LOG_W("[RAIN] Detected! protect = VALID");
- Recode_e_code(e_rain_trigger, 1, "雨控触发");
- rt_thread_mdelay(1000);
- report_now();
- }
- else
- {
- s_rain_start_tick = now;
- LOG_D("[RAIN] Persists, protect extended");
- }
- }
- else
- {
- if (sys_sta.rain_protect == VALID && s_rain_start_tick != 0)
- {
- if ((now - s_rain_start_tick) >= rt_tick_from_millisecond(RAIN_CLEAR_TIMEOUT_MS))
- {
- sys_sta.rain_protect = 0;
- s_rain_start_tick = 0;
- LOG_I("[RAIN] Protect cleared after %d min", RAIN_CLEAR_TIMEOUT_MS / 60000);
- Recode_e_code(e_rain_restore, 0, "雨控保护清除");
- rt_thread_mdelay(1000);
- report_now();
- }
- }
- }
- }
- /**
- * @brief 初始化雨控检测
- */
- static void rain_init(void)
- {
- // LOG_I("[RAIN] Initializing...");
- rt_pin_mode(RAIN_OUT_PIN, PIN_MODE_INPUT);
- rt_pin_mode(RAIN_IN_PIN, PIN_MODE_INPUT_PULLUP);
- int has_rain = rain_detect_once();
- if (has_rain)
- {
- LOG_W("[RAIN] Initially detected!");
- sys_sta.rain_protect = VALID;
- s_rain_start_tick = rt_tick_get();
- Recode_e_code(e_rain_trigger, 1, "雨控初始状态为触发");
- }
- else
- {
- // LOG_I("[RAIN] Initially normal");
- sys_sta.rain_protect = 0;
- s_rain_start_tick = 0;
- }
- s_rain_last_detect_tick = rt_tick_get();
- // LOG_I("[RAIN] Initialized (detect every %d sec, clear after %d min)",
- // RAIN_DETECT_INTERVAL_MS / 1000, RAIN_CLEAR_TIMEOUT_MS / 60000);
- }
- /*********************↑ 雨控检测函数 ↑***********************/
- /*********************↓ 工作线程 ↓***********************/
- /**
- * @brief 硬件检测工作线程(优先级9,确保倾倒及时响应)
- */
- static void hw_work_handler(void *parameter)
- {
- // LOG_I("Hardware monitor thread started (priority 9)");
- while (1)
- {
- if (rt_sem_take(&tilt_sem, rt_tick_from_millisecond(TILT_POLL_INTERVAL_MS)) == RT_EOK)
- {
- tilt_process();
- }
- tilt_process();
- rain_process();
- rt_thread_mdelay(30);
- }
- LOG_I("Hardware monitor thread stopped");
- }
- /**
- * @brief 启动硬件检测
- */
- static void hw_monitor_start(void)
- {
- if (s_hw_thread != RT_NULL)
- {
- LOG_D("Hardware monitor already running");
- return;
- }
- tilt_init();
- rain_init();
- s_hw_running = RT_TRUE;
- s_hw_thread = rt_thread_create("hw_mon", hw_work_handler, NULL,
- 1024, 9, 10);
- if (s_hw_thread == RT_NULL)
- {
- LOG_E("Failed to create hardware monitor thread");
- s_hw_running = RT_FALSE;
- return;
- }
- rt_thread_startup(s_hw_thread);
- // LOG_I("Hardware monitor started (priority 9)");
- }
- /*********************↑ 工作线程 ↑***********************/
- /*********************↓ 自动初始化 ↓***********************/
- static int hw_detect_auto_init(void)
- {
- hw_monitor_start();
- return 0;
- }
- INIT_APP_EXPORT(hw_detect_auto_init);
- /*********************↑ 自动初始化 ↑***********************/
- /*********************↓ MSH命令 ↓***********************/
- /**
- * @brief MSH命令:查看倾倒开关状态
- */
- static void cmd_tilt_status(int argc, char **argv)
- {
- rt_kprintf("\n========== TILT SWITCH ==========\n");
- rt_kprintf("Protect: %s\n", sys_sta.tilt_protect == VALID ? "ACTIVE" : "INACTIVE");
- rt_kprintf("Pin level: %s\n", rt_pin_read(TILT_SWITCH_PIN) == PIN_LOW ? "LOW" : "HIGH");
- rt_kprintf("Poll interval: %d ms\n", TILT_POLL_INTERVAL_MS);
- rt_kprintf("Clear timeout: %d sec\n", TILT_CLEAR_TIMEOUT_MS / 1000);
- if (sys_sta.tilt_protect == VALID && s_tilt_start_tick != 0)
- {
- rt_tick_t elapsed = rt_tick_get() - s_tilt_start_tick;
- rt_kprintf("Duration: %d sec\n", elapsed / RT_TICK_PER_SECOND);
- }
- rt_kprintf("================================\n");
- if (argc >= 2 && strcmp(argv[1], "clear") == 0)
- {
- if (sys_sta.tilt_protect == VALID)
- {
- sys_sta.tilt_protect = 0;
- s_tilt_start_tick = 0;
- LOG_I("[TILT] Manually cleared");
- Recode_e_code(e_tilt_restore, 0, "倾倒保护手动清除");
- rt_kprintf("Protect cleared\n");
- }
- else
- {
- rt_kprintf("Protect not active\n");
- }
- }
- }
- MSH_CMD_EXPORT(cmd_tilt_status, Show tilt status.Usage : cmd_tilt_status[clear]);
- /**
- * @brief MSH命令:查看雨控检测状态
- */
- static void cmd_rain_status(int argc, char **argv)
- {
- rt_kprintf("\n========== RAIN SENSOR ==========\n");
- rt_kprintf("Protect: %s\n", sys_sta.rain_protect == VALID ? "ACTIVE" : "INACTIVE");
- rt_kprintf("Detect interval: %d sec\n", RAIN_DETECT_INTERVAL_MS / 1000);
- rt_kprintf("Clear timeout: %d min\n", RAIN_CLEAR_TIMEOUT_MS / 60000);
- if (sys_sta.rain_protect == VALID && s_rain_start_tick != 0)
- {
- rt_tick_t elapsed = rt_tick_get() - s_rain_start_tick;
- rt_kprintf("Duration: %d sec\n", elapsed / RT_TICK_PER_SECOND);
- }
- rt_kprintf("================================\n");
- if (argc >= 2 && strcmp(argv[1], "detect") == 0)
- {
- int result = rain_detect_once();
- rt_kprintf("Manual detect: %s\n", result ? "RAIN DETECTED" : "NO RAIN");
- }
- if (argc >= 2 && strcmp(argv[1], "clear") == 0)
- {
- if (sys_sta.rain_protect == VALID)
- {
- sys_sta.rain_protect = 0;
- s_rain_start_tick = 0;
- LOG_I("[RAIN] Manually cleared");
- Recode_e_code(e_rain_restore, 0, "雨控保护手动清除");
- rt_kprintf("Protect cleared\n");
- }
- else
- {
- rt_kprintf("Protect not active\n");
- }
- }
- }
- MSH_CMD_EXPORT(cmd_rain_status, Show rain status.Usage : cmd_rain_status[detect | clear]);
- /*********************↑ MSH命令 ↑***********************/
|