/** ****************************************************************************** * @file relay_control.c * @brief 继电器控制模块实现 * @author Application Layer * @version 1.1 ****************************************************************************** * @attention * 本模块实现继电器的安全控制 * 关键特性: * 1. 最小切换间隔保护,防止频繁切换损坏继电器 * 2. 状态记录,支持诊断 * 3. 调试日志输出 * * 修订历史: * v1.1 - 修复审查报告中危-9/10:对齐RELAY_COUNT与参数校验逻辑 ****************************************************************************** */ #include "relay_control.h" #include "uart2_print.h" #include "main.h" #define DEBUG_RELAY 1 #if DEBUG_RELAY #define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[RELAY] " fmt "\r\n", ##__VA_ARGS__) #else #define DEBUG_LOG(fmt, ...) #endif #define MAX_RELAY_ID 4 static bool current_states[MAX_RELAY_ID] = {false, false, false, false}; static uint32_t last_toggle_tick = 0; static uint32_t toggle_count = 0; void Relay_Init(void) { HAL_GPIO_WritePin(RL_Control_GPIO_Port, RL_Control_Pin, GPIO_PIN_RESET); for (int i = 0; i < MAX_RELAY_ID; i++) { current_states[i] = false; } last_toggle_tick = 0; toggle_count = 0; DEBUG_LOG("Init OK, state=OFF"); } void Relay_SetState(uint8_t relay_id, bool state) { if (relay_id < 1 || relay_id > MAX_RELAY_ID) { DEBUG_LOG("Invalid relay ID: %d", relay_id); return; } uint32_t current_tick = HAL_GetTick(); if (current_tick - last_toggle_tick < RELAY_MIN_INTERVAL) { DEBUG_LOG("Toggle too fast, ignored"); return; } uint8_t idx = relay_id - 1; if (current_states[idx] == state) { DEBUG_LOG("State unchanged: %s", state ? "ON" : "OFF"); return; } if (relay_id == 1) { HAL_GPIO_WritePin(RL_Control_GPIO_Port, RL_Control_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); } current_states[idx] = state; last_toggle_tick = current_tick; toggle_count++; DEBUG_LOG("Relay %d -> %s (count=%lu)", relay_id, state ? "ON" : "OFF", toggle_count); } bool Relay_GetState(uint8_t relay_id) { if (relay_id < 1 || relay_id > MAX_RELAY_ID) { return false; } return current_states[relay_id - 1]; } void Relay_Toggle(uint8_t relay_id) { if (relay_id < 1 || relay_id > MAX_RELAY_ID) { return; } Relay_SetState(relay_id, !current_states[relay_id - 1]); } uint32_t Relay_GetToggleCount(void) { return toggle_count; }