156 lines
4.6 KiB
C
156 lines
4.6 KiB
C
|
#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;
|
||
|
}
|