modbus_slave.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /**
  2. * @Author: 李建
  3. * @Date: 2025/8/21 10:45
  4. * Description: MODBUS 从站
  5. * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
  6. */
  7. #include <esp_attr.h>
  8. #include "modbus_slave.h"
  9. #include "esp_modbus_common.h"
  10. #include "esp_modbus_slave.h"
  11. #include "mb_endianness_utils.h"
  12. #include "lvgl_port.h"
  13. #define MB_PAR_INFO_GET_TOUT (10)
  14. #define MB_READ_MASK (MB_EVENT_INPUT_REG_RD \
  15. | MB_EVENT_HOLDING_REG_RD \
  16. | MB_EVENT_DISCRETE_RD \
  17. | MB_EVENT_COILS_RD)
  18. #define MB_WRITE_MASK (MB_EVENT_HOLDING_REG_WR \
  19. | MB_EVENT_COILS_WR)
  20. #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
  21. #define MB_READ_WRITE_MASK (MB_READ_MASK | MB_WRITE_MASK)
  22. static uint16_t holding_reg_area[MB_REG_HOLD_CNT] = {0};
  23. #define MB_SLAVE_ADDR (1)
  24. static const char *TAG = "MODBUS_SLAVE";
  25. mb_param_info_t reg_info;
  26. static void *mbc_slave_handle = NULL;
  27. static uint8_t communication_status = 0; // 通讯状态累加值
  28. static void setup_modbus_regs() {
  29. holding_reg_area[SLAVE_FAN_LEVEL_REG_ADDRESS] = 2;
  30. }
  31. IRAM_ATTR static esp_err_t slave_init() {
  32. mb_register_area_descriptor_t reg_area = {0};
  33. // Initialize Modbus controller
  34. mb_communication_info_t comm_config = {
  35. .ser_opts.port = MB_PORT_NUM,
  36. .ser_opts.mode = MB_RTU,
  37. .ser_opts.baudrate = MB_DEV_SPEED,
  38. .ser_opts.parity = MB_PARITY_NONE,
  39. .ser_opts.uid = system_setting.inner_addr,
  40. .ser_opts.data_bits = UART_DATA_8_BITS,
  41. .ser_opts.stop_bits = UART_STOP_BITS_1
  42. };
  43. ESP_LOGI(TAG, "Modbus controller initialized...");
  44. esp_err_t err = mbc_slave_create_serial(&comm_config, &mbc_slave_handle); // Initialization of Modbus controller
  45. MB_RETURN_ON_FALSE((mbc_slave_handle != NULL), ESP_ERR_INVALID_STATE, TAG,
  46. "mb controller initialization fail.");
  47. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  48. "mb controller initialization fail, returns(0x%x).", (int) err);
  49. reg_area.type = MB_PARAM_HOLDING; // Set type of register area
  50. reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol
  51. reg_area.address = (void *) &holding_reg_area[0]; // Set pointer to storage instance
  52. reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes
  53. err = mbc_slave_set_descriptor(mbc_slave_handle, reg_area);
  54. // setup modbus regs
  55. setup_modbus_regs();
  56. // Set UART pin numbers
  57. err = uart_set_pin(MB_PORT_NUM, MB_GPIO_TX, MB_GPIO_RX,
  58. UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  59. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  60. "mb serial set pin failure, uart_set_pin() returned (0x%x).", (int) err);
  61. // Set driver mode to Half Duplex
  62. err = uart_set_mode(MB_PORT_NUM, UART_MODE_UART);
  63. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  64. "mb serial set mode failure, uart_set_mode() returned (0x%x).", (int) err);
  65. vTaskDelay(5);
  66. err = mbc_slave_start(mbc_slave_handle);
  67. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  68. "mb controller start fail, returned (0x%x).", (int) err);
  69. ESP_LOGI(TAG, "Modbus slave stack initialized...");
  70. return err;
  71. }
  72. void modbus_slave_task(void *pv) {
  73. for (;;) {
  74. (void) mbc_slave_check_event(mbc_slave_handle, MB_READ_WRITE_MASK);
  75. ESP_ERROR_CHECK(mbc_slave_get_param_info(mbc_slave_handle, &reg_info, MB_PAR_INFO_GET_TOUT));
  76. const char *rw_str = (reg_info.type & MB_READ_MASK) ? "READ" : "WRITE";
  77. if (reg_info.type & MB_EVENT_HOLDING_REG_RD) {
  78. communication_status = 0;
  79. (void) mbc_slave_lock(mbc_slave_handle);
  80. holding_reg_area[SLAVE_COMMUNICATION_STATUS_REG_ADDRESS] = 1;
  81. (void) mbc_slave_unlock(mbc_slave_handle);
  82. }
  83. }
  84. }
  85. static void communication_status_check_task(void *pv) {
  86. for (;;) {
  87. if (communication_status == 0 && guider_ui.screen_main) {
  88. lvgl_port_lock(0);
  89. lv_obj_remove_flag(guider_ui.screen_main_label_xf_conn, LV_OBJ_FLAG_HIDDEN);
  90. system_setting.xf_have=1;
  91. lvgl_port_unlock();
  92. }
  93. communication_status++;
  94. if (communication_status > 30) {
  95. communication_status = 30;
  96. }
  97. if (communication_status >= 30) {
  98. holding_reg_area[SLAVE_COMMUNICATION_STATUS_REG_ADDRESS] = 0;
  99. lvgl_port_lock(0);
  100. lv_obj_add_flag(guider_ui.screen_main_label_xf_conn, LV_OBJ_FLAG_HIDDEN);
  101. system_setting.xf_have=0;
  102. lvgl_port_unlock();
  103. }
  104. vTaskDelay(pdTICKS_TO_MS(1000));
  105. }
  106. }
  107. void modbus_slave_init() {
  108. ESP_LOGI(TAG, "Modbus slave init...");
  109. ESP_ERROR_CHECK(slave_init());
  110. vTaskDelay(10);
  111. xTaskCreate(modbus_slave_task, "modbus_slave_task", 4 * 1024, NULL, 5, NULL);
  112. xTaskCreate(communication_status_check_task, "check_task", 2 * 1024, NULL, 5, NULL);
  113. }
  114. uint16_t modbus_get_reg(uint16_t address) {
  115. uint16_t value = 0;
  116. if (address < MB_REG_HOLD_CNT) {
  117. // ESP_LOGE(TAG, "Modbus slave address %d\n",address);
  118. value = holding_reg_area[address];
  119. }
  120. return value;
  121. }
  122. void modbus_set_reg(uint16_t address, uint16_t value) {
  123. if (address < MB_REG_HOLD_CNT) {
  124. holding_reg_area[address] = value;
  125. }
  126. }