185 lines
6.3 KiB
C
185 lines
6.3 KiB
C
/**
|
||
******************************************************************************
|
||
* @file relay_control.c
|
||
* @brief 继电器控制模块实现
|
||
* @author Application Layer
|
||
* @version 2.0
|
||
******************************************************************************
|
||
* @attention
|
||
* 本模块实现单路继电器的安全控制
|
||
* 关键特性:
|
||
* 1. 最小切换间隔保护,防止频繁切换损坏继电器
|
||
* 2. 状态记录
|
||
* 3. 调试日志输出
|
||
*
|
||
* 修订历史:
|
||
* v2.0 - 精简为单路继电器控制,移除冗余功能
|
||
******************************************************************************
|
||
*/
|
||
|
||
#include "relay_control.h"
|
||
#include "uart2_print.h"
|
||
#include "main.h"
|
||
|
||
/*==============================================================================
|
||
* 调试宏定义
|
||
*============================================================================*/
|
||
/* DEBUG_RELAY: 调试日志开关,置1时启用继电器控制过程日志输出 */
|
||
#define DEBUG_RELAY 1
|
||
|
||
#if DEBUG_RELAY
|
||
/* 调试日志宏,带模块前缀"[RELAY]"方便过滤日志 */
|
||
#define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[RELAY] " fmt "\r\n", ##__VA_ARGS__)
|
||
#else
|
||
#define DEBUG_LOG(fmt, ...)
|
||
#endif
|
||
|
||
/*==============================================================================
|
||
* 全局变量定义
|
||
*============================================================================*/
|
||
/**
|
||
* @brief 继电器当前状态
|
||
* @note 记录继电器的开关状态
|
||
*
|
||
* 状态含义:
|
||
* - false: 继电器处于断开状态(OFF)
|
||
* - true: 继电器处于闭合状态(ON)
|
||
*
|
||
* 初始化说明:
|
||
* 初始化为false,表示系统上电后继电器默认断开
|
||
*/
|
||
static bool current_state = false;
|
||
|
||
/**
|
||
* @brief 上一次切换操作的时间戳
|
||
* @note 用于实现继电器最小切换间隔保护
|
||
*
|
||
* 设计目的:
|
||
* 继电器是机械开关,频繁切换会缩短其使用寿命。
|
||
* 通过记录上次切换时间,可以强制两次切换之间必须间隔
|
||
* 最小时间(RELAY_MIN_INTERVAL),防止频繁操作。
|
||
*
|
||
* 单位说明:
|
||
* 毫秒(ms),与HAL_GetTick()返回值单位一致
|
||
*/
|
||
static uint32_t last_toggle_tick = 0;
|
||
|
||
/*==============================================================================
|
||
* 公共函数实现
|
||
*============================================================================*/
|
||
/**
|
||
* @brief 继电器模块初始化
|
||
* @note 在系统启动时调用,复位继电器到安全初始状态
|
||
*
|
||
* @param 无
|
||
* @return 无
|
||
*
|
||
* 功能说明:
|
||
* 1. 硬件控制引脚设置为低电平,强制确保继电器断开
|
||
* 2. 重置状态变量为false
|
||
* 3. 重置切换时间戳为0
|
||
*
|
||
* 初始化安全:
|
||
* - 此函数应尽早调用,确保系统启动时继电器处于受控状态
|
||
* - 继电器初始状态设为OFF是考虑到故障安全(fail-safe)设计
|
||
*/
|
||
void Relay_Init(void)
|
||
{
|
||
/*----------------------------------------------------------
|
||
* 硬件层面:将继电器控制引脚设置为低电平
|
||
* RL_Control_GPIO_Port和RL_Control_Pin定义在main.h或引脚配置中
|
||
*----------------------------------------------------------*/
|
||
HAL_GPIO_WritePin(RL_Control_GPIO_Port, RL_Control_Pin, GPIO_PIN_RESET);
|
||
|
||
/*----------------------------------------------------------
|
||
* 软件层面:初始化继电器状态为OFF
|
||
*----------------------------------------------------------*/
|
||
current_state = false;
|
||
|
||
/*----------------------------------------------------------
|
||
* 重置切换保护相关计时器
|
||
*----------------------------------------------------------*/
|
||
last_toggle_tick = 0;
|
||
|
||
DEBUG_LOG("Init OK, state=OFF");
|
||
}
|
||
|
||
/**
|
||
* @brief 设置继电器状态
|
||
* @note 核心控制函数,实现继电器开关操作及保护逻辑
|
||
*
|
||
* @param state: 目标状态,false=关闭(OFF),true=打开(ON)(输入)
|
||
* @return 无
|
||
*
|
||
* 功能说明:
|
||
* 1. 切换间隔保护检查(防频繁操作)
|
||
* 2. 状态变更判断(避免重复操作)
|
||
* 3. 硬件GPIO操作
|
||
* 4. 状态记录和统计更新
|
||
*
|
||
* 算法说明 - 切换间隔保护:
|
||
* if (current_tick - last_toggle_tick < RELAY_MIN_INTERVAL)
|
||
* return; // 切换过于频繁,直接丢弃
|
||
*
|
||
* 这个检查确保两次继电器操作之间至少间隔RELAY_MIN_INTERVAL毫秒,
|
||
* 防止程序错误或通信干扰导致继电器被频繁开关。
|
||
*
|
||
* 注意/异常:
|
||
* - 切换间隔太短时静默忽略,防抖处理
|
||
* - 状态与当前相同时静默忽略,不重复操作
|
||
*/
|
||
void Relay_SetState(bool state)
|
||
{
|
||
/*----------------------------------------------------------
|
||
* 获取当前时间,判断与上次操作的时间间隔
|
||
*----------------------------------------------------------*/
|
||
uint32_t current_tick = HAL_GetTick();
|
||
|
||
/*----------------------------------------------------------
|
||
* 切换间隔保护检查
|
||
*----------------------------------------------------------*/
|
||
if (current_tick - last_toggle_tick < RELAY_MIN_INTERVAL) {
|
||
DEBUG_LOG("Toggle too fast, ignored");
|
||
return;
|
||
}
|
||
|
||
/*----------------------------------------------------------
|
||
* 状态变更判断:避免重复设置相同状态
|
||
*----------------------------------------------------------*/
|
||
if (current_state == state) {
|
||
DEBUG_LOG("State unchanged: %s", state ? "ON" : "OFF");
|
||
return;
|
||
}
|
||
|
||
/*----------------------------------------------------------
|
||
* 硬件控制:设置GPIO引脚电平
|
||
*----------------------------------------------------------*/
|
||
HAL_GPIO_WritePin(RL_Control_GPIO_Port, RL_Control_Pin,
|
||
state ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||
|
||
/*----------------------------------------------------------
|
||
* 更新软状态和记录切换时间
|
||
*----------------------------------------------------------*/
|
||
current_state = state;
|
||
last_toggle_tick = current_tick;
|
||
|
||
DEBUG_LOG("Relay -> %s", state ? "ON" : "OFF");
|
||
}
|
||
|
||
/**
|
||
* @brief 获取继电器当前状态
|
||
* @note 返回继电器的开关状态
|
||
*
|
||
* @param 无
|
||
* @return bool: 继电器状态,false=关闭(OFF),true=打开(ON)
|
||
*
|
||
* 使用示例:
|
||
* if (Relay_GetState()) {
|
||
* // 继电器当前处于闭合状态
|
||
* }
|
||
*/
|
||
bool Relay_GetState(void)
|
||
{
|
||
return current_state;
|
||
}
|