Files
433_STM32/Core/Src/relay_control.c
zhongxuanzhen 0eea5c1424 3.27_433:实验并验证485发送数据透传至RF433模块,并在外部设备成功接收
- 新增协议识别器状态机,实现指令与透传数据的自动识别
2026-03-27 19:58:20 +08:00

185 lines
6.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
******************************************************************************
* @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;
}