/** * @Author: 李建 * @Date: 2025/8/21 10:45 * Description: MODBUS 从站 * Copyright: Copyright (©) 2025 永续绿建. All rights reserved. */ #include #include "modbus_slave.h" #include "esp_modbus_common.h" #include "esp_modbus_slave.h" #include "mb_endianness_utils.h" #include "lvgl_port.h" #define MB_PAR_INFO_GET_TOUT (10) #define MB_READ_MASK (MB_EVENT_INPUT_REG_RD \ | MB_EVENT_HOLDING_REG_RD \ | MB_EVENT_DISCRETE_RD \ | MB_EVENT_COILS_RD) #define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR \ | MB_EVENT_COILS_WR) #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK) #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK) static uint16_t holding_reg_area[MB_REG_HOLD_CNT] = {0}; #define MB_SLAVE_ADDR (1) static const char *TAG = "MODBUS_SLAVE"; mb_param_info_t reg_info; static void *mbc_slave_handle = NULL; static uint8_t communication_status = 0; // 通讯状态累加值 static void setup_modbus_regs() { holding_reg_area[SLAVE_FAN_LEVEL_REG_ADDRESS] = 2; } IRAM_ATTR static esp_err_t slave_init() { mb_register_area_descriptor_t reg_area = {0}; // Initialize Modbus controller mb_communication_info_t comm_config = { .ser_opts.port = MB_PORT_NUM, .ser_opts.mode = MB_RTU, .ser_opts.baudrate = MB_DEV_SPEED, .ser_opts.parity = MB_PARITY_NONE, .ser_opts.uid = system_setting.inner_addr, .ser_opts.data_bits = UART_DATA_8_BITS, .ser_opts.stop_bits = UART_STOP_BITS_1 }; ESP_LOGI(TAG, "Modbus controller initialized..."); esp_err_t err = mbc_slave_create_serial(&comm_config, &mbc_slave_handle); // Initialization of Modbus controller MB_RETURN_ON_FALSE((mbc_slave_handle != NULL), ESP_ERR_INVALID_STATE, TAG, "mb controller initialization fail."); MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb controller initialization fail, returns(0x%x).", (int) err); reg_area.type = MB_PARAM_HOLDING; // Set type of register area reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol reg_area.address = (void *) &holding_reg_area[0]; // Set pointer to storage instance reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes err = mbc_slave_set_descriptor(mbc_slave_handle, reg_area); // setup modbus regs setup_modbus_regs(); // Set UART pin numbers err = uart_set_pin(MB_PORT_NUM, MB_GPIO_TX, MB_GPIO_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb serial set pin failure, uart_set_pin() returned (0x%x).", (int) err); // Set driver mode to Half Duplex err = uart_set_mode(MB_PORT_NUM, UART_MODE_UART); MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb serial set mode failure, uart_set_mode() returned (0x%x).", (int) err); vTaskDelay(5); err = mbc_slave_start(mbc_slave_handle); MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG, "mb controller start fail, returned (0x%x).", (int) err); ESP_LOGI(TAG, "Modbus slave stack initialized..."); return err; } void modbus_slave_task(void *pv) { for (;;) { (void) mbc_slave_check_event(mbc_slave_handle, MB_READ_WRITE_MASK); ESP_ERROR_CHECK(mbc_slave_get_param_info(mbc_slave_handle, ®_info, MB_PAR_INFO_GET_TOUT)); const char *rw_str = (reg_info.type & MB_READ_MASK) ? "READ" : "WRITE"; if (reg_info.type & MB_EVENT_HOLDING_REG_RD) { communication_status = 0; (void) mbc_slave_lock(mbc_slave_handle); holding_reg_area[SLAVE_COMMUNICATION_STATUS_REG_ADDRESS] = 1; (void) mbc_slave_unlock(mbc_slave_handle); } } } static void communication_status_check_task(void *pv) { for (;;) { if (communication_status == 0 && guider_ui.screen_main) { lvgl_port_lock(0); lv_obj_remove_flag(guider_ui.screen_main_label_xf_conn, LV_OBJ_FLAG_HIDDEN); system_setting.xf_have=1; lvgl_port_unlock(); } communication_status++; if (communication_status > 30) { communication_status = 30; } if (communication_status >= 30) { holding_reg_area[SLAVE_COMMUNICATION_STATUS_REG_ADDRESS] = 0; lvgl_port_lock(0); lv_obj_add_flag(guider_ui.screen_main_label_xf_conn, LV_OBJ_FLAG_HIDDEN); system_setting.xf_have=0; lvgl_port_unlock(); } vTaskDelay(pdTICKS_TO_MS(1000)); } } void modbus_slave_init() { ESP_LOGI(TAG, "Modbus slave init..."); ESP_ERROR_CHECK(slave_init()); vTaskDelay(10); xTaskCreate(modbus_slave_task, "modbus_slave_task", 4 * 1024, NULL, 5, NULL); xTaskCreate(communication_status_check_task, "check_task", 2 * 1024, NULL, 5, NULL); } uint16_t modbus_get_reg(uint16_t address) { uint16_t value = 0; if (address < MB_REG_HOLD_CNT) { // ESP_LOGE(TAG, "Modbus slave address %d\n",address); value = holding_reg_area[address]; } return value; } void modbus_set_reg(uint16_t address, uint16_t value) { if (address < MB_REG_HOLD_CNT) { holding_reg_area[address] = value; } }