modbus_master.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /**
  2. * @Author: 李建
  3. * @Date: 2025/4/27 15:35
  4. * Description: 实现485主站
  5. * Copyright: Copyright (©) 2025 永续绿建. All rights reserved.
  6. */
  7. #include <esp_err.h>
  8. #include "modbus_master.h"
  9. #include "mbcontroller.h"
  10. #define OPTS(min_val, max_val, step_val) { .opt1 = min_val, .opt2 = max_val, .opt3 = step_val }
  11. static const char *TAG = "MODBUS_MASTER";
  12. enum {
  13. // 热泵主机从站号
  14. MB_DEVICE_HP_ADDR = 1,
  15. // 分集水器集控盒站
  16. MB_DEVICE_FJSQ_ADDR = 5,
  17. };
  18. static void *master_handle = NULL;
  19. #define STR(fieldname) ((const char *)( fieldname ))
  20. const mb_parameter_descriptor_t device_parameters[] = {
  21. // { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
  22. {CID_HP_SET_MODE, STR("mode"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_HOLDING,
  23. HP_SET_MODE_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  24. {CID_HP_COOL_SET_TEMP, STR("c_temp"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_HOLDING,
  25. HP_COOL_SET_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  26. {CID_HP_HEAT_SET_TEMP, STR("h_temp"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_HOLDING,
  27. HP_HEAT_SET_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  28. {CID_HP_OUTDOOR_TEMP, STR("o_temp"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_HOLDING,
  29. HP_OUTDOOR_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ},
  30. {CID_HP_OUT_WATER_TEMP, STR("out"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_HOLDING,
  31. HP_OUT_WATER_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ},
  32. {CID_HP_IN_WATER_TEMP, STR("in"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_HOLDING,
  33. HP_IN_WATER_TEMP_REG_ADDRESS, 1, 0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ},
  34. {CID_HP_POWER, STR("power"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_COIL, 0, 1,0, PARAM_TYPE_U8, 1, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  35. {CID_HP_ERROR, STR("error"), STR(""), MB_DEVICE_HP_ADDR, MB_PARAM_COIL, 40, 1,0, PARAM_TYPE_U8, 1, OPTS(0, 0, 0), PAR_PERMS_WRITE},
  36. {CID_RELAY_1_STATUS, STR("r1"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_1_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  37. {CID_RELAY_2_STATUS, STR("r2"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_2_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  38. {CID_RELAY_3_STATUS, STR("r3"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_3_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  39. {CID_RELAY_4_STATUS, STR("r4"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_4_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  40. {CID_RELAY_5_STATUS, STR("r5"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_5_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  41. {CID_RELAY_6_STATUS, STR("r6"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_6_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  42. {CID_RELAY_7_STATUS, STR("r7"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_7_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  43. {CID_RELAY_8_STATUS, STR("r8"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, RELAY_8_STATUS_REG_ADDRESS, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  44. {CID_MODIFY_COMMUNICATION_ADDRESS, STR("md"), STR(""), MB_DEVICE_FJSQ_ADDR, MB_PARAM_HOLDING, MODIFY_COMMUNICATION_ADDRESS_REGISTER, 1,0, PARAM_TYPE_U16, 2, OPTS(0, 0, 0), PAR_PERMS_READ_WRITE},
  45. };
  46. // Calculate number of parameters in the table
  47. const uint16_t num_device_parameters = (sizeof(device_parameters) / sizeof(device_parameters[0]));
  48. IRAM_ATTR static esp_err_t master_init() {
  49. // Initialize Modbus controller
  50. mb_communication_info_t comm = {
  51. .ser_opts.port = MB_PORT_NUM,
  52. .ser_opts.mode = MB_RTU,
  53. .ser_opts.baudrate = MB_DEV_SPEED,
  54. .ser_opts.parity = MB_PARITY_NONE,
  55. .ser_opts.response_tout_ms = 1000,
  56. .ser_opts.data_bits = UART_DATA_8_BITS,
  57. .ser_opts.stop_bits = UART_STOP_BITS_1
  58. };
  59. ESP_LOGI(TAG, "Modbus controller initialized...");
  60. esp_err_t err = mbc_master_create_serial(&comm, &master_handle);
  61. MB_RETURN_ON_FALSE((master_handle != NULL), ESP_ERR_INVALID_STATE, TAG,
  62. "mb controller initialization fail.");
  63. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  64. "mb controller initialization fail, returns(0x%x).", (int) err);
  65. // Set UART pin numbers
  66. err = uart_set_pin(MB_PORT_NUM, MB_GPIO_TX, MB_GPIO_RX,
  67. UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
  68. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  69. "mb serial set pin failure, uart_set_pin() returned (0x%x).", (int) err);
  70. err = mbc_master_start(master_handle);
  71. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  72. "mb controller start fail, returned (0x%x).", (int) err);
  73. // Set driver mode to Half Duplex
  74. err = uart_set_mode(MB_PORT_NUM, UART_MODE_UART);
  75. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  76. "mb serial set mode failure, uart_set_mode() returned (0x%x).", (int) err);
  77. vTaskDelay(5);
  78. err = mbc_master_set_descriptor(master_handle, &device_parameters[0], num_device_parameters);
  79. MB_RETURN_ON_FALSE((err == ESP_OK), ESP_ERR_INVALID_STATE, TAG,
  80. "mb controller set descriptor fail, returns(0x%x).", (int) err);
  81. ESP_LOGI(TAG, "Modbus master stack initialized...");
  82. return err;
  83. }
  84. //static void *master_get_param_data(const mb_parameter_descriptor_t *param_descriptor)
  85. //{
  86. // assert(param_descriptor != NULL);
  87. // void *instance_ptr = NULL;
  88. // if (param_descriptor->param_offset != 0) {
  89. // switch(param_descriptor->mb_param_type)
  90. // {
  91. // case MB_PARAM_HOLDING:
  92. // instance_ptr = ((void *)&holding_reg_params + param_descriptor->param_offset - 1);
  93. // break;
  94. // default:
  95. // instance_ptr = NULL;
  96. // break;
  97. // }
  98. // } else {
  99. // ESP_LOGE(TAG, "Wrong parameter offset for CID #%u", (unsigned)param_descriptor->cid);
  100. // assert(instance_ptr != NULL);
  101. // }
  102. // return instance_ptr;
  103. //}
  104. void modbus_master_task(void *arg) {
  105. vTaskDelay(5000 / portTICK_PERIOD_MS);
  106. ESP_LOGI(TAG, "Modbus master task started...");
  107. esp_err_t err = ESP_OK;
  108. uint8_t temp_data[2] = {0}; // temporary buffer to hold maximum CID size
  109. uint8_t type = 0;
  110. const mb_parameter_descriptor_t *param_descriptor = NULL;
  111. for (;;) {
  112. for (uint16_t cid = 0; (err != ESP_ERR_NOT_FOUND) && cid < 16; cid++) {
  113. err = mbc_master_get_cid_info(master_handle, cid, &param_descriptor);
  114. if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
  115. err = mbc_master_get_parameter(master_handle, param_descriptor->cid, (uint8_t *) temp_data, &type);
  116. if (err == ESP_OK) {
  117. ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = %d read successful.",
  118. param_descriptor->cid,
  119. (char *) param_descriptor->param_key,
  120. (char *) param_descriptor->param_units,
  121. *(uint16_t *) temp_data);
  122. } else {
  123. ESP_LOGE(TAG, "Characteristic #%d (%s) read fail, err = 0x%x (%s).",
  124. param_descriptor->cid,
  125. (char *) param_descriptor->param_key,
  126. (int) err,
  127. (char *) esp_err_to_name(err));
  128. }
  129. }
  130. vTaskDelay(1000 / portTICK_PERIOD_MS);
  131. }
  132. vTaskDelay(5000 / portTICK_PERIOD_MS);
  133. }
  134. }
  135. void modbus_master_init() {
  136. ESP_LOGI(TAG, "Modbus master init...");
  137. ESP_ERROR_CHECK(master_init());
  138. //vTaskDelay(10);
  139. //xTaskCreatePinnedToCore(modbus_master_task, "modbus_master_task", 4 * 1024, NULL, 5, NULL, 1);
  140. }
  141. esp_err_t mm_set_param(uint16_t cid, uint8_t *value) {
  142. uint8_t type = PARAM_TYPE_U16;
  143. return mbc_master_set_parameter(master_handle, cid, value, &type);
  144. }
  145. esp_err_t mm_get_param(uint16_t cid, uint8_t *value) {
  146. uint8_t type = PARAM_TYPE_U16;
  147. return mbc_master_get_parameter(master_handle, cid, value, &type);
  148. }
  149. esp_err_t send_request(mb_param_request_t *request, void *data_prt) {
  150. return mbc_master_send_request(master_handle, request, data_prt);
  151. }
  152. void modbus_master_destroy() {
  153. mbc_master_delete(master_handle);
  154. }