#ifndef BSP_MODBUS_MB_ #define BSP_MODBUS_MB_ #ifdef __cplusplus extern "C" { #endif #include #include #include #include "bsp_gate.h" #define MODBUS_MAX_TASK (300u) #define MODBUS_MAX_DEV (32u) #define MODBUS_GATE_FREE_ADDR (0xFFFF) /****************************************** * Helper Macros ******************************************/ #define READ_REGISTER_MAP_BEGIN() \ switch(index) \ { #define READ_REGISTER_MAP_END() \ default: \ data = 0x00; \ break; \ } #define READ_REGISTER_MAP_ITEM(INDEX, VARIABLE) \ case INDEX: \ data = VARIABLE; \ break; #define WRITE_REGISTER_MAP_BEGIN() \ switch(index) \ { #define WRITE_REGISTER_MAP_END() \ default: \ break; \ } #define WRITE_REGISTER_MAP_ITEM(INDEX, VARIABLE) WRITE_REGISTER_MAP_ITEM_EX(INDEX, VARIABLE, value) #define WRITE_REGISTER_MAP_ITEM_EX(INDEX, VARIABLE, VALUE) \ case INDEX: \ VARIABLE = VALUE; \ break; #define WRITE_REGISTER_MAP_STATEMENT(INDEX, STATEMENT) \ case INDEX: \ STATEMENT; \ break; #define WRITE_REGISTER_MAP_ITEM_CONFIG(INDEX, CONFIG) WRITE_REGISTER_MAP_ITEM_CONFIG_EX(INDEX, CONFIG, value) #define WRITE_REGISTER_MAP_ITEM_CONFIG_EX(INDEX, CONFIG, VALUE) \ case INDEX: \ config_save(CONFIG, VALUE); \ break; typedef enum { kModbusType_RTU, kModbusType_TCP, kModbusType_End }ModbusType; typedef enum { kModbusFun_0x01 = 0x01, kModbusFun_0x02 = 0x02, kModbusFun_0x03 = 0x03, kModbusFun_0x04 = 0x04, kModbusFun_0x05 = 0x05, kModbusFun_0x06 = 0x06, kModbusFun_0x0F = 0x0F, kModbusFun_0x10 = 0x10, kModbusFun_End, }ModbusFun; typedef enum { kBspMdEx_None = 0, kBspMdEx_InvalidFunc, kBspMdEx_InvalidAddr, kBspMdEx_InvalidRegNum, kBspMdEx_SlaveFault, kBspMdEx_Acknowledge, //从机确认命令但需要较长时间,需要上位机等待 kBspMdEx_SlaveBusy, }BspMdExCode; struct _ModbusItem; struct _ModbusTask; typedef BspMdExCode (*ModbusFunCall)(uint16_t start_addr, uint16_t reg_num, uint8_t *buf, uint16_t *len); typedef bool (*ModbusSendCall)(uint8_t comm_dev, uint8_t *buf, int32_t len); typedef void (*MB_FUNC_CALL)(struct _ModbusItem * mb_item, uint8_t cmd, uint16_t start_addr, uint8_t *buf, uint16_t len); typedef void (*HmiRxIntCtrlCall)(uint8_t comm_dev, bool is_en); typedef void (*MasterCall)(struct _ModbusItem * mb_item, uint32_t base_time); #define MODBUS_BUF_SIZE (280u) typedef struct { uint8_t slave_addr; uint8_t fun_code; uint16_t reg_addr; uint16_t reg_num; uint16_t time_out; }ModbusHead; typedef struct _ModbusTask { uint16_t tick; uint16_t buf_addr; ModbusHead *head; }ModbusTask; typedef struct _ModbusItem { uint8_t addr; uint8_t comm_dev; ModbusType type; bool is_master; uint16_t tcp_transaction; //事务元标识符 uint16_t buf_pos; uint16_t buf_size; uint16_t start_addr; uint16_t gate_write_data_absolute_addr; uint32_t tick; ModbusSendCall send_call; GateItem *gate; HmiRxIntCtrlCall ctrl_rx_int_call; MB_FUNC_CALL func_call; ModbusFunCall fun_call_array[kModbusFun_End]; MasterCall master_call; uint8_t buf[MODBUS_BUF_SIZE]; uint8_t task_cashe; uint8_t cur_task_idx; uint8_t task_num; bool is_read_write_data; uint8_t gate_write_dev_addr; uint8_t gate_write_try_cnt; int16_t gate_write_data_addr; uint16_t gate_write_data_value; uint16_t gate_write_data_start_addr; uint16_t gate_write_data_end_addr; uint16_t time_out[MODBUS_MAX_DEV]; ModbusHead *gate_write_data_head; ModbusTask *modbus_task; struct _ModbusItem *next_item; } ModbusItem; typedef struct { uint8_t call_idx; uint16_t max_task_num; uint16_t gate_write_data_cnt; ModbusItem *head_item; ModbusItem *lastest_item; MasterCall master_call_array[20]; ModbusTask modbus_task_buf[MODBUS_MAX_TASK]; }ModbusCommData; //#define MODBUS_STATIC_TASK(_name, _slave_addr, _reg_num, _start_addr, _rcv_buf) \ // ModbusTask _name = \ // { \ // (NULL), \ // (_slave_addr), \ // (_reg_num), \ // (_start_addr), \ // (_rcv_buf), \ // } #define MODBUS_STATIC_INIT(_name, _modbus_type, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _func_call) \ ModbusItem _name = \ { \ (_slave_addr), \ (_comm_dev), \ (_modbus_type),\ (false),\ 0, \ 0, \ MODBUS_BUF_SIZE, \ 0xFFFF, \ MODBUS_GATE_FREE_ADDR, \ 0, \ _send_call, \ _func_call, \ _ctrl_rx_int_call, \ } #define MODBUS_RTU_STATIC_INIT(_name, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) MODBUS_STATIC_INIT(_name, kModbusType_RTU, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) #define MODBUS_TCP_STATIC_INIT(_name, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) MODBUS_STATIC_INIT(_name, kModbusType_TCP, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) #define MODBUS_STATIC_INIT_CCM(_name, _modbus_type, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) \ ModbusItem _name __attribute__((section (".CCM_RAM"))) = \ { \ (_slave_addr), \ (_comm_dev), \ (_modbus_type),\ (false),\ 0, \ 0, \ MODBUS_BUF_SIZE, \ 0xFFFF, \ MODBUS_GATE_FREE_ADDR, \ 0, \ _send_call, \ _gate, \ _ctrl_rx_int_call, \ } #define MODBUS_RTU_STATIC_INIT_CCM(_name, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) MODBUS_STATIC_INIT_CCM(_name, kModbusType_RTU, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) #define MODBUS_TCP_STATIC_INIT_CCM(_name, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) MODBUS_STATIC_INIT_CCM(_name, kModbusType_TCP, _slave_addr, _comm_dev, _send_call, _ctrl_rx_int_call, _gate) void bsp_modbus_poll(ModbusItem * const item, bool is_enable_call); void bsp_modbus_pos_send(ModbusItem * const mb_item, uint16_t len); void bsp_modbus_neg_send(ModbusItem * const mb_item, BspMdExCode ex_code); void bsp_modbus_register_master_fun(ModbusItem * const item, MasterCall master_call); void bsp_modbus_register_fun(ModbusItem * const mb_item, ModbusFun fun_code, ModbusFunCall register_call); void bsp_modbus_set_slaver_addr(ModbusItem * const item, uint8_t addr); void bsp_modbus_push_data(ModbusItem * const mb_item, uint8_t *buf, uint16_t len); void bsp_modbus_slaver_send_read(ModbusItem * const item, uint8_t dev_addr, uint8_t fun_code, uint8_t *buf, uint16_t len); void bsp_modbus_master_read(ModbusItem * const item, uint8_t dev_addr, uint8_t fun_code, uint16_t start_addr, uint16_t reg_num); void bsp_modbus_master_single_write(ModbusItem * const item, uint8_t dev_addr, uint8_t fun_code, uint16_t start_addr, uint16_t value); void bsp_modbus_master_series_write(ModbusItem * const item, uint8_t dev_addr, uint8_t fun_code, uint16_t start_addr, uint16_t reg_num, uint8_t *buf); bool bsp_modbus_register_task(ModbusItem * const item, ModbusHead *head); uint16_t bsp_modbus_get_time_out(ModbusItem * const item, uint8_t addr); void bsp_modbus_poll_all(uint32_t base_time); void bsp_modbus_poll_call(uint32_t base_time); #ifdef __cplusplus } #endif #endif