#include "hmi_server.h" #include "et_log.h" #include "etk_utils.h" #include "mb_command.h" #include "mb_interface.h" nmbs_t nmbs; static rt_uint8_t mb_hmi_stack[HMI_THREAD_STACK_SIZE]; struct rt_thread mb_hmi_thread; static nmbs_error server_read_input_registers(uint16_t address, uint16_t quantity, uint16_t *registers_out, uint8_t unit_id, void *arg); static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t *registers_out, uint8_t unit_id, void *arg); static nmbs_error server_write_single_register(uint16_t address, uint16_t value, uint8_t unit_id, void *arg); static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t *registers, uint8_t unit_id, void *arg); static nmbs_error nmbs_server_init(nmbs_t *nmbs) { nmbs_platform_conf conf; nmbs_callbacks cb; nmbs_platform_conf_create(&conf); conf.transport = NMBS_TRANSPORT_RTU; conf.read = pm_hmi_uart_read; conf.write = pm_hmi_uart_write; nmbs_callbacks_create(&cb); cb.read_coils = NULL; cb.read_holding_registers = server_read_holding_registers; cb.write_single_coil = NULL; cb.write_multiple_coils = NULL; cb.write_single_register = server_write_single_register; cb.write_multiple_registers = server_write_multiple_registers; cb.read_input_registers = server_read_input_registers; nmbs_error status = nmbs_server_create(nmbs, MB_SLAVE_ID, &conf, &cb); if (status != NMBS_ERROR_NONE) { return status; } nmbs_set_byte_timeout(nmbs, 100); nmbs_set_read_timeout(nmbs, 1000); return NMBS_ERROR_NONE; } static nmbs_error server_read_input_registers(uint16_t address, uint16_t quantity, uint16_t *registers_out, uint8_t unit_id, void *arg) { ETK_UNUSED(unit_id); ETK_UNUSED(arg); return mb_handle_read_input_registers(address, quantity, registers_out); } static nmbs_error server_read_holding_registers(uint16_t address, uint16_t quantity, uint16_t *registers_out, uint8_t unit_id, void *arg) { ETK_UNUSED(unit_id); ETK_UNUSED(arg); // 直接从底层寄存器区读取 if (address + quantity > REG_BUF_SIZE) { ET_ERR("Read holding registers out of range: addr=%u, qty=%u", address, quantity); return NMBS_ERROR_INVALID_REQUEST; } mb_command_t *cmd = get_command_instance(); if (cmd == RT_NULL) { ET_ERR("Failed to get command instance"); return NMBS_ERROR_INVALID_ARGUMENT; } mb_command_t *get_command_instance(void); for (uint16_t i = 0; i < quantity; ++i) { registers_out[i] = cmd->regs[address + i]; ET_DBG("Read holding register[%u] = 0x%04X", address + i, registers_out[i]); } return NMBS_ERROR_NONE; } // function: 0x06 Write Single Register static nmbs_error server_write_single_register(uint16_t address, uint16_t value, uint8_t unit_id, void *arg) { ETK_UNUSED(unit_id); ETK_UNUSED(arg); uint16_t reg = value; return server_write_multiple_registers(address, 1, ®, unit_id, arg); } static nmbs_error server_write_multiple_registers(uint16_t address, uint16_t quantity, const uint16_t *registers, uint8_t unit_id, void *arg) { ETK_UNUSED(unit_id); ETK_UNUSED(arg); return mb_handle_write_holding_registers(address, quantity, registers); } static void mb_hmi_thread_entry(void *parameter) { RT_UNUSED(parameter); while (1) { nmbs_server_poll(&nmbs); rt_thread_mdelay(20); } } int hmi_server_start(void) { rt_err_t result; result = rt_thread_init(&mb_hmi_thread, "HMI", mb_hmi_thread_entry, RT_NULL, mb_hmi_stack, sizeof(mb_hmi_stack), HMI_THREAD_PRIORITY, 50); if (result == RT_EOK) { ET_INFO("servo thread init success."); rt_thread_startup(&mb_hmi_thread); } else { ET_ERR("servo thread init failed.%d", result); return -1; } return 0; } int hmi_server_handler_register(hmi_server_t *hmi, mb_cmd_handler_t *handler) { hmi->cmd.handler = handler; return 0; } int hmi_server_init(hmi_server_t *hmi) { if (pm_mb_hmi_init() != 0) { ET_ERR("Failed to initialize Modbus HMI"); return -1; } mb_command_init(&hmi->cmd); mb_interface_init(); nmbs_server_init(&nmbs); return 0; }