/** * @file modbus_rtu_slave.h * @brief Modbus RTU 从站模块公开接口。 */ #ifndef MODBUS_RTU_SLAVE_H #define MODBUS_RTU_SLAVE_H #include "stm32f4xx_hal.h" #ifdef __cplusplus extern "C" { #endif /** * @brief Modbus 数据模型的最大地址。 * * 任务要求规定线圈和保持寄存器地址范围均为 0~0x270F, * 因此每种数据共有 10000 项。 */ #define MODBUS_MAP_LAST_ADDRESS (0x270FU) #define MODBUS_MAP_ITEM_COUNT (0x2710U) #define MODBUS_SLAVE_DEFAULT_ADDRESS (1U) #define MODBUS_CONNECTION_TIMEOUT_MS (1000U) /** * @brief 与 TouchWin 触摸屏联调使用的演示地址。 * * 可以直接访问以下地址。 */ #define HMI_REG_DEVICE_ID (0U) #define HMI_REG_UPTIME_SECONDS (1U) #define HMI_REG_RX_FRAME_COUNT (2U) #define HMI_REG_WRITE_TEST (10U) #define HMI_COIL_WRITE_TEST (0U) /** * @brief Modbus 从站通信统计信息。 */ typedef struct { uint32_t rxEventCount; ///< 串口接收事件总数。 uint32_t validFrameCount; ///< CRC 和从站地址均有效的帧数。 uint32_t txFrameCount; ///< 成功启动 DMA 发送的帧数。 uint32_t crcErrorCount; ///< CRC 校验错误帧数。 uint32_t ignoredAddressCount; ///< 因从站地址不匹配而忽略的帧数。 uint32_t illegalFunctionCount; ///< 非法功能码计数。 uint32_t illegalAddressCount; ///< 非法数据地址计数。 uint32_t illegalValueCount; ///< 非法数据值计数。 uint32_t droppedFrameCount; ///< 接收槽占用或长度错误导致的丢帧数。 uint32_t uartErrorCount; ///< HAL 串口错误计数。 } MODBUS_SLAVE_STATS; /** @brief Modbus 从站通信统计数据。 */ extern volatile MODBUS_SLAVE_STATS ModbusSlaveStatistics; /** * @brief 初始化 Modbus 从站并启动 USART DMA 空闲接收。 * @param[in] huart 已由 HAL 初始化完成的串口句柄。 * @param[in] slaveAddress 从站地址,有效范围为 1~247。 * @retval HAL_OK 初始化成功且 DMA 接收已启动。 * @retval HAL_ERROR 输入参数无效。 * @retval HAL_BUSY 串口或 DMA 当前忙。 */ HAL_StatusTypeDef ModbusSlaveInit(UART_HandleTypeDef *huart, uint8_t slaveAddress); /** * @brief 校验并处理一帧待处理请求。 * * 本函数应在 uC/OS-II 任务中周期调用。中断只负责接收数据, * CRC 校验、协议解析和响应发送均在任务上下文中执行。 */ void ModbusSlavePoll(void); /** * @brief 处理 HAL 串口 DMA 接收事件。 * @param[in] huart 产生接收事件的串口句柄。 * @param[in] size 本次接收到的字节数。 */ void ModbusSlaveOnRxEvent(UART_HandleTypeDef *huart, uint16_t size); /** * @brief 处理 HAL 串口 DMA 发送完成事件。 * @param[in] huart 完成发送的串口句柄。 */ void ModbusSlaveOnTxComplete(UART_HandleTypeDef *huart); /** * @brief 处理 HAL 串口错误事件并恢复接收。 * @param[in] huart 发生错误的串口句柄。 */ void ModbusSlaveOnUartError(UART_HandleTypeDef *huart); /** * @brief 写入一个保持寄存器。 * @param[in] address 保持寄存器地址。 * @param[in] value 待写入的 16 位数据。 */ uint8_t ModbusSlaveSetHoldingRegister(uint16_t address, uint16_t value); /** * @brief 读取一个保持寄存器。 * @param[in] address 保持寄存器地址。 * @param[out] value 用于保存读取结果的指针。 */ uint8_t ModbusSlaveGetHoldingRegister(uint16_t address, uint16_t *value); /** * @brief 设置一个线圈的状态。 * @param[in] address 线圈地址。 * @param[in] state 0 表示复位,非 0 表示置位。 */ uint8_t ModbusSlaveSetCoil(uint16_t address, uint8_t state); /** * @brief 读取一个线圈的状态。 * @param[in] address 线圈地址。 * @param[out] state 用于保存线圈状态的指针,结果为 0 或 1。 */ uint8_t ModbusSlaveGetCoil(uint16_t address, uint8_t *state); /** * @brief 判断指定时间内是否收到过有效请求。 * @param[in] timeoutMs 连接超时时间,单位为毫秒。 * @retval 1 从站在指定时间内收到过有效请求。 * @retval 0 尚未收到有效请求或连接已经超时。 */ uint8_t ModbusSlaveIsConnected(uint32_t timeoutMs); #ifdef __cplusplus } #endif #endif /* MODBUS_RTU_SLAVE_H */