3.27_433:添加UART2调试打印、IO监控、指令解析和继电器控制模块。
能够接收UART2指令控制继电器开关,或向UART2发送四路IO输入状态,并使用轮询方式检测IO状态进行及时反馈。
This commit is contained in:
109
Core/Inc/cmd_parser.h
Normal file
109
Core/Inc/cmd_parser.h
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file cmd_parser.h
|
||||
* @brief ASCII指令解析模块头文件
|
||||
* @author Application Layer
|
||||
* @version 1.0
|
||||
******************************************************************************
|
||||
* @attention
|
||||
* 本模块实现ASCII文本指令的解析和处理
|
||||
* 指令格式: $CMD,param1,param2*CS\r\n
|
||||
* 支持异或校验,FF为调试特权后门
|
||||
* 包含完善的安全防护机制
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __CMD_PARSER_H
|
||||
#define __CMD_PARSER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CMD_MAX_LEN 8
|
||||
#define PARAM_MAX_LEN 32
|
||||
#define PARSE_TIMEOUT_MS 1000
|
||||
|
||||
typedef enum {
|
||||
CMD_CODE_UNKNOWN = 0,
|
||||
CMD_CODE_RL = 1,
|
||||
CMD_CODE_DI = 2,
|
||||
CMD_CODE_ECHO = 3,
|
||||
CMD_CODE_FWD = 4
|
||||
} cmd_code_t;
|
||||
|
||||
typedef struct {
|
||||
char cmd[CMD_MAX_LEN];
|
||||
char param1[PARAM_MAX_LEN];
|
||||
char param2[PARAM_MAX_LEN];
|
||||
uint8_t received_cs;
|
||||
uint8_t calculated_cs;
|
||||
bool valid;
|
||||
bool skip_checksum;
|
||||
} cmd_frame_t;
|
||||
|
||||
/**
|
||||
* @brief 初始化指令解析模块
|
||||
* @note 重置解析状态机,清空缓冲区
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void CmdParser_Init(void);
|
||||
|
||||
/**
|
||||
* @brief 指令解析任务处理函数
|
||||
* @note 在主循环中调用,处理已接收的完整指令帧
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void CmdParser_Task(void);
|
||||
|
||||
/**
|
||||
* @brief 喂入单字节数据到解析器
|
||||
* @note 通常在UART接收中断中调用
|
||||
* @param byte: 接收到的字节数据
|
||||
* @param current_tick: 当前系统tick(用于超时检测)
|
||||
* @retval 无
|
||||
*/
|
||||
void CmdParser_FeedByte(uint8_t byte, uint32_t current_tick);
|
||||
|
||||
/**
|
||||
* @brief 检查是否有完整的指令帧
|
||||
* @note 用于查询解析状态
|
||||
* @param frame: 输出参数,存储解析结果
|
||||
* @retval true: 有完整帧, false: 无
|
||||
*/
|
||||
bool CmdParser_HasCompleteFrame(cmd_frame_t *frame);
|
||||
|
||||
/**
|
||||
* @brief 确认指令已处理
|
||||
* @note 处理完指令后调用,重置解析器
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void CmdParser_Acknowledge(void);
|
||||
|
||||
/**
|
||||
* @brief 获取解析错误计数
|
||||
* @note 用于调试和诊断
|
||||
* @param 无
|
||||
* @retval 错误计数
|
||||
*/
|
||||
uint32_t CmdParser_GetErrorCount(void);
|
||||
|
||||
/**
|
||||
* @brief 获取接收到的有效指令计数
|
||||
* @note 用于调试和诊断
|
||||
* @param 无
|
||||
* @retval 有效指令计数
|
||||
*/
|
||||
uint32_t CmdParser_GetValidCount(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
82
Core/Inc/io_monitor.h
Normal file
82
Core/Inc/io_monitor.h
Normal file
@ -0,0 +1,82 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file io_monitor.h
|
||||
* @brief IO状态监控模块头文件
|
||||
* @author Application Layer
|
||||
* @version 1.0
|
||||
******************************************************************************
|
||||
* @attention
|
||||
* 本模块实现四路数字输入(DI1-DI4)的状态监控
|
||||
* 采用定时扫描+软件去抖方式检测IO状态变化
|
||||
* 状态变化时通过UART2_Print上报
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __IO_MONITOR_H
|
||||
#define __IO_MONITOR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define IO_CHANNEL_COUNT 4
|
||||
#define IO_SCAN_PERIOD_MS 10
|
||||
#define IO_DEBOUNCE_COUNT 3
|
||||
|
||||
/**
|
||||
* @brief 初始化IO监控模块
|
||||
* @note 初始化各通道状态,读取初始IO电平
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void IO_Monitor_Init(void);
|
||||
|
||||
/**
|
||||
* @brief IO监控任务处理函数
|
||||
* @note 在主循环中调用,每10ms扫描一次IO状态
|
||||
* 检测到状态变化时自动上报
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void IO_Monitor_Task(void);
|
||||
|
||||
/**
|
||||
* @brief 获取指定通道的IO状态
|
||||
* @note 返回经过去抖处理后的稳定状态
|
||||
* @param channel: 通道号(0-3对应DI1-DI4)
|
||||
* @retval 0: LOW, 1: HIGH
|
||||
*/
|
||||
uint8_t IO_Monitor_GetState(uint8_t channel);
|
||||
|
||||
/**
|
||||
* @brief 获取所有IO通道状态
|
||||
* @note 返回4位状态值,每位对应一个通道
|
||||
* @param 无
|
||||
* @retval 状态值 (bit0=DI1, bit1=DI2, bit2=DI3, bit3=DI4)
|
||||
*/
|
||||
uint8_t IO_Monitor_GetAllStates(void);
|
||||
|
||||
/**
|
||||
* @brief 启用/禁用IO状态变化上报
|
||||
* @note 禁用后状态变化不会触发上报,但状态仍会更新
|
||||
* @param enable: true=启用, false=禁用
|
||||
* @retval 无
|
||||
*/
|
||||
void IO_Monitor_EnableReport(bool enable);
|
||||
|
||||
/**
|
||||
* @brief 获取IO状态变化次数统计
|
||||
* @note 用于调试和诊断
|
||||
* @param channel: 通道号(0-3)
|
||||
* @retval 该通道的状态变化次数
|
||||
*/
|
||||
uint32_t IO_Monitor_GetChangeCount(uint8_t channel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
117
Core/Inc/protocol.h
Normal file
117
Core/Inc/protocol.h
Normal file
@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file protocol.h
|
||||
* @brief 简化的ASCII文本指令协议
|
||||
*
|
||||
* 协议格式: $SN,CMD,param1,param2*CS\r\n
|
||||
* - SN: 序列号(0-255),用于防丢包和重复
|
||||
* - CMD: 指令名称
|
||||
* - CS: CRC8校验(从$到*之间所有字符的CRC8值)
|
||||
*
|
||||
* 抗干扰/防丢失机制:
|
||||
* 1. CRC8校验 - 比XOR更强的检错能力
|
||||
* 2. 序列号 - 接收方可检测丢包和重复
|
||||
* 3. 应答机制 - 重要指令需要确认
|
||||
*/
|
||||
|
||||
#ifndef __PROTOCOL_H
|
||||
#define __PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 协议配置 */
|
||||
#define PROTOCOL_MAX_CMD_LEN 8
|
||||
#define PROTOCOL_MAX_PARAM_LEN 32
|
||||
#define PROTOCOL_MAX_PARAMS 4
|
||||
#define PROTOCOL_FRAME_TIMEOUT 1000 /* 帧超时/ms */
|
||||
|
||||
typedef struct {
|
||||
uint8_t sn; /* 序列号 */
|
||||
char cmd[PROTOCOL_MAX_CMD_LEN]; /* 指令名 */
|
||||
char params[PROTOCOL_MAX_PARAMS][PROTOCOL_MAX_PARAM_LEN];
|
||||
uint8_t param_count; /* 参数数量 */
|
||||
uint8_t checksum; /* CRC8校验和 */
|
||||
bool valid; /* 解析是否成功 */
|
||||
} protocol_frame_t;
|
||||
|
||||
typedef enum {
|
||||
PROTOCOL_OK = 0,
|
||||
PROTOCOL_ERROR_INVALID_FRAME,
|
||||
PROTOCOL_ERROR_CHECKSUM_FAIL,
|
||||
PROTOCOL_ERROR_TIMEOUT,
|
||||
PROTOCOL_ERROR_UNKNOWN_CMD,
|
||||
PROTOCOL_ERROR_PARAM_COUNT,
|
||||
PROTOCOL_ERROR_BUFFER_FULL
|
||||
} protocol_error_t;
|
||||
|
||||
typedef enum {
|
||||
PROTOCOL_CMD_RL, /* 继电器控制: RL,id,ON/OFF */
|
||||
PROTOCOL_CMD_DI, /* 查询IO: DI,id */
|
||||
PROTOCOL_CMD_DIA, /* 查询所有IO: DIA */
|
||||
PROTOCOL_CMD_FWD, /* 数据转发: FWD,port,data */
|
||||
PROTOCOL_CMD_ECHO, /* 心跳: ECHO */
|
||||
PROTOCOL_CMD_ACK, /* 应答: ACK,sn,result */
|
||||
PROTOCOL_CMD_STATUS, /* 状态查询: STATUS */
|
||||
PROTOCOL_CMD_UNKNOWN
|
||||
} protocol_cmd_t;
|
||||
|
||||
typedef struct {
|
||||
protocol_cmd_t cmd;
|
||||
uint8_t sn;
|
||||
bool need_ack; /* 是否需要应答 */
|
||||
uint32_t send_time; /* 发送时间 */
|
||||
uint8_t retry_count; /* 重试次数 */
|
||||
} protocol_pending_t;
|
||||
|
||||
#define PROTOCOL_MAX_PENDING 4
|
||||
|
||||
typedef struct {
|
||||
protocol_pending_t pending[PROTOCOL_MAX_PENDING];
|
||||
uint8_t pending_count;
|
||||
uint8_t next_sn;
|
||||
uint8_t last_rx_sn;
|
||||
} protocol_context_t;
|
||||
|
||||
/* 协议初始化 */
|
||||
void protocol_init(void);
|
||||
|
||||
/* 解析收到的指令 */
|
||||
protocol_error_t protocol_parse(const char *data, uint16_t length, protocol_frame_t *frame);
|
||||
|
||||
/* 构造发送帧 */
|
||||
protocol_error_t protocol_build(char *buffer, uint16_t buffer_size, uint16_t *out_length,
|
||||
protocol_cmd_t cmd, uint8_t sn,
|
||||
const char *params[], uint8_t param_count);
|
||||
|
||||
/* 构造应答帧 */
|
||||
protocol_error_t protocol_build_ack(char *buffer, uint16_t buffer_size, uint16_t *out_length,
|
||||
uint8_t sn, bool success, const char *msg);
|
||||
|
||||
/* 发送命令并等待应答 */
|
||||
protocol_error_t protocol_send_with_ack(protocol_cmd_t cmd, const char *params[], uint8_t param_count,
|
||||
uint32_t timeout_ms, uint8_t max_retries);
|
||||
|
||||
/* 协议任务处理(处理超时和重试) */
|
||||
void protocol_task(void);
|
||||
|
||||
/* CRC8计算 */
|
||||
uint8_t protocol_crc8(const uint8_t *data, uint16_t length);
|
||||
|
||||
/* 指令名转枚举 */
|
||||
protocol_cmd_t protocol_cmd_from_string(const char *cmd_str);
|
||||
|
||||
/* 枚举转指令名 */
|
||||
const char* protocol_cmd_to_string(protocol_cmd_t cmd);
|
||||
|
||||
/* 获取上一个错误 */
|
||||
protocol_error_t protocol_get_last_error(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __PROTOCOL_H */
|
||||
72
Core/Inc/relay_control.h
Normal file
72
Core/Inc/relay_control.h
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file relay_control.h
|
||||
* @brief 继电器控制模块头文件
|
||||
* @author Application Layer
|
||||
* @version 1.0
|
||||
******************************************************************************
|
||||
* @attention
|
||||
* 本模块提供继电器的安全控制接口
|
||||
* 当前硬件配置:PA15连接继电器控制端
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __RELAY_CONTROL_H
|
||||
#define __RELAY_CONTROL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define RELAY_COUNT 1
|
||||
#define RELAY_MIN_INTERVAL 100
|
||||
|
||||
/**
|
||||
* @brief 初始化继电器控制模块
|
||||
* @note 将继电器初始状态设为关闭
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void Relay_Init(void);
|
||||
|
||||
/**
|
||||
* @brief 设置继电器状态
|
||||
* @note 带最小间隔保护,防止频繁切换损坏继电器
|
||||
* @param relay_id: 继电器编号(1-4),当前硬件只有1
|
||||
* @param state: true=打开, false=关闭
|
||||
* @retval 无
|
||||
*/
|
||||
void Relay_SetState(uint8_t relay_id, bool state);
|
||||
|
||||
/**
|
||||
* @brief 获取继电器当前状态
|
||||
* @note 读取GPIO输出状态
|
||||
* @param relay_id: 继电器编号(1-4)
|
||||
* @retval true=打开, false=关闭
|
||||
*/
|
||||
bool Relay_GetState(uint8_t relay_id);
|
||||
|
||||
/**
|
||||
* @brief 翻转继电器状态
|
||||
* @note 带最小间隔保护
|
||||
* @param relay_id: 继电器编号(1-4)
|
||||
* @retval 无
|
||||
*/
|
||||
void Relay_Toggle(uint8_t relay_id);
|
||||
|
||||
/**
|
||||
* @brief 获取继电器切换次数
|
||||
* @note 用于调试和诊断
|
||||
* @param 无
|
||||
* @retval 切换次数
|
||||
*/
|
||||
uint32_t Relay_GetToggleCount(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
99
Core/Inc/uart2_print.h
Normal file
99
Core/Inc/uart2_print.h
Normal file
@ -0,0 +1,99 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file uart2_print.h
|
||||
* @brief UART2调试打印模块头文件
|
||||
* @author Application Layer
|
||||
* @version 1.0
|
||||
******************************************************************************
|
||||
* @attention
|
||||
* 本模块提供基于环形缓冲区的非阻塞调试信息输出功能
|
||||
* 支持printf风格的格式化输出
|
||||
* 支持中断安全调用
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef __UART2_PRINT_H
|
||||
#define __UART2_PRINT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define UART2_TX_BUFFER_SIZE 256
|
||||
|
||||
/**
|
||||
* @brief 初始化UART2打印模块
|
||||
* @note 清空发送缓冲区,重置状态标志
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void UART2_Print_Init(void);
|
||||
|
||||
/**
|
||||
* @brief 发送原始数据到UART2
|
||||
* @note 数据写入环形缓冲区,非阻塞返回
|
||||
* @param data: 待发送的数据指针
|
||||
* @param len: 数据长度
|
||||
* @retval 无
|
||||
*/
|
||||
void UART2_Print_Send(const uint8_t *data, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief 发送字符串到UART2
|
||||
* @note 自动计算字符串长度
|
||||
* @param str: 待发送的字符串指针
|
||||
* @retval 无
|
||||
*/
|
||||
void UART2_Print_String(const char *str);
|
||||
|
||||
/**
|
||||
* @brief 格式化打印到UART2
|
||||
* @note 支持printf风格的格式化输出
|
||||
* @param fmt: 格式化字符串
|
||||
* @param ...: 可变参数
|
||||
* @retval 无
|
||||
*/
|
||||
void UART2_Print_Printf(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief UART2打印任务处理函数
|
||||
* @note 在主循环中调用,处理发送缓冲区中的数据
|
||||
* 每次调用发送一个字节(中断方式)
|
||||
* @param 无
|
||||
* @retval 无
|
||||
*/
|
||||
void UART2_Print_Task(void);
|
||||
|
||||
/**
|
||||
* @brief 检查UART2是否正在发送
|
||||
* @note 用于查询当前发送状态
|
||||
* @param 无
|
||||
* @retval true: 正在发送, false: 空闲
|
||||
*/
|
||||
bool UART2_Print_IsBusy(void);
|
||||
|
||||
/**
|
||||
* @brief 获取发送缓冲区剩余空间
|
||||
* @note 用于检测缓冲区是否即将溢出
|
||||
* @param 无
|
||||
* @retval 剩余空间字节数
|
||||
*/
|
||||
uint16_t UART2_Print_Available(void);
|
||||
|
||||
/**
|
||||
* @brief UART2发送完成中断回调
|
||||
* @note 由HAL库调用,不应由用户直接调用
|
||||
* @param huart: UART句柄指针
|
||||
* @retval 无
|
||||
*/
|
||||
void UART2_Print_TxCpltCallback(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user