#ifndef MODBUS_RTU_SLAVE_H #define MODBUS_RTU_SLAVE_H #include "stm32f4xx_hal.h" #ifdef __cplusplus extern "C" { #endif /* * 任务文档规定线圈和保持寄存器地址范围均为0~0x270F。 * 因此地址总数是0x2710,即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 /* * 供第一次与触摸屏联调使用的演示地址。 * TouchWin选择“起始地址为0”的Modbus RTU主站协议后,可直接访问这些地址。 */ #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 typedef struct { uint32_t rx_event_count; uint32_t valid_frame_count; uint32_t tx_frame_count; uint32_t crc_error_count; uint32_t ignored_address_count; uint32_t illegal_function_count; uint32_t illegal_address_count; uint32_t illegal_value_count; uint32_t dropped_frame_count; uint32_t uart_error_count; } ModbusSlaveStats; extern volatile ModbusSlaveStats g_modbus_slave_stats; /* * 初始化从站并启动USART DMA空闲接收。 * 必须在MX_USART1_UART_Init()和DMA初始化完成后调用。 */ HAL_StatusTypeDef ModbusSlave_Init(UART_HandleTypeDef *huart, uint8_t slave_address); /* * 在uC/OS-II任务中周期调用,用于校验并处理一帧请求。 * 中断只负责搬运数据,协议解析留在任务上下文中执行。 */ void ModbusSlave_Poll(void); /* 以下三个接口由STM32 HAL串口回调调用。 */ void ModbusSlave_OnRxEvent(UART_HandleTypeDef *huart, uint16_t size); void ModbusSlave_OnTxComplete(UART_HandleTypeDef *huart); void ModbusSlave_OnUartError(UART_HandleTypeDef *huart); /* 应用层访问保持寄存器和线圈的接口。返回0表示地址非法。 */ uint8_t ModbusSlave_SetHoldingRegister(uint16_t address, uint16_t value); uint8_t ModbusSlave_GetHoldingRegister(uint16_t address, uint16_t *value); uint8_t ModbusSlave_SetCoil(uint16_t address, uint8_t state); uint8_t ModbusSlave_GetCoil(uint16_t address, uint8_t *state); /* * 在timeout_ms时间内收到过有效请求即认为触摸屏在线。 * 该状态适用于实现任务要求中的连接/断线判断。 */ uint8_t ModbusSlave_IsConnected(uint32_t timeout_ms); #ifdef __cplusplus } #endif #endif