modbus.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. #include "at32f403a_407.h"
  2. #include "common_config.h"
  3. #include "modbus.h"
  4. #include "update.h"
  5. #include "FreeRTOS.h"
  6. #include "task.h"
  7. #include "mb.h"
  8. #include "mbport.h"
  9. #include "mbrtu.h"
  10. #include "tim_delay.h"
  11. #include "modbus_params.h"
  12. #include "common_gpio.h"
  13. #include "io_utils.h"
  14. #include "log_api.h"
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdbool.h>
  18. #define REG_HOLDING_START ( 1 )
  19. #define REG_HOLDING_NREGS ( 5 )
  20. #undef DBG
  21. #define DBG if(1)
  22. static USHORT usRegHoldingStart = REG_HOLDING_START;
  23. extern UCHAR rcvAddress;
  24. //osThreadId modbus_task_handle;
  25. static void modbus_task(void *params);
  26. //osThreadId modbus_params_handle;
  27. static void modbus_params(void *params);
  28. //osTimerId reset_timer_handle;
  29. //osTimerId settings_timer_handle;
  30. //osTimerId modbus_timer_handle;
  31. mb_delay_action_t mb_action = MB_NO_ACTION;
  32. uint8_t new_slave_addr;
  33. bool mb_package_flag = false;
  34. //
  35. void mb_init(void)
  36. {
  37. uint32_t baud = 115200;
  38. eMBParity par = MB_PAR_NONE;
  39. UCHAR mb_addr = gpio_get_mbaddr();
  40. unsigned int stop_bits = 1;
  41. const UCHAR ucSlaveID[] = {0xAA, 0xBB, 0xCC};
  42. mb_init_params();
  43. mb_helper_tim_init(baud);
  44. eMBInit(MB_RTU, mb_addr, 4, baud, par, stop_bits);
  45. eMBSetSlaveID(0x34, TRUE, ucSlaveID, 3);
  46. eMBEnable();
  47. xTaskCreate(modbus_task, "modbus_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  48. xTaskCreate(modbus_params, "modbus_params", 4*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
  49. // Таймер для перехода в IAP
  50. update_create_timer();
  51. #if 0
  52. osTimerDef(vResetTimer, modbus_reset);
  53. reset_timer_handle = osTimerCreate(osTimer(vResetTimer), osTimerOnce, NULL);
  54. osTimerDef(vSettingsTimer, settings_timer);
  55. settings_timer_handle = osTimerCreate(osTimer(vSettingsTimer), osTimerOnce, NULL);
  56. osTimerDef(vModbusTimer, modbus_port_timer);
  57. modbus_timer_handle = osTimerCreate(osTimer(vModbusTimer), osTimerOnce, NULL);
  58. #endif
  59. }
  60. //
  61. void modbus_task(void *params)
  62. {
  63. (void)params;
  64. for (;;)
  65. {
  66. eMBPoll();
  67. }
  68. }
  69. //
  70. void modbus_params(void *params)
  71. {
  72. for (;;)
  73. {
  74. if (mb_action != MB_NO_ACTION)
  75. {
  76. switch (mb_action)
  77. {
  78. // Установка нового адреса
  79. case MB_CHANGE_ADDR :
  80. //settings.com_settings.mb_addr = new_slave_addr;
  81. eMBSetSlaveAddr(new_slave_addr);
  82. break;
  83. case MB_CHANGE_PORT_SETTINGS :
  84. #if 0
  85. osDelay(200);
  86. eMBRTUStop();
  87. settings_set_modbus_params(temp_modbus_port);
  88. settings_init_mb_port(settings.com_settings.mb_addr);
  89. MBDBG settings_print_modbus();
  90. eMBRTUStart();
  91. eMBEnable();
  92. mb_package_flag = false;
  93. osTimerStart(modbus_timer_handle, 9800);
  94. #endif
  95. break;
  96. // Полное восстановление дефолтных настроек
  97. case MB_DEF_SETTINGS :
  98. #if 0
  99. settings_set_default(true);
  100. settings_save();
  101. #endif
  102. break;
  103. // Частичное восстановление дефолтных настроек
  104. case MB_PART_DEF_SETTINGS :
  105. #if 0
  106. settings_set_default(false);
  107. settings_save();
  108. #endif
  109. break;
  110. case MB_SAVE_SETTINGS :
  111. #if 0
  112. settings_save();
  113. #endif
  114. break;
  115. case MB_SAVE_SYS_SETTINGS :
  116. #if 0
  117. if (set_sys_settings_flag) {
  118. memcpy(&sys_settings, &temp_sys_settings, sizeof(sys_settings));
  119. sys_settings_save();
  120. }
  121. #endif
  122. break;
  123. case MB_RESET :
  124. vTaskDelay(100);
  125. NVIC_SystemReset();
  126. break;
  127. default : break;
  128. }
  129. mb_action = MB_NO_ACTION;
  130. }
  131. vTaskDelay(10);
  132. }
  133. }
  134. // Отложенная перезагрузка в Bootloader
  135. void modbus_reset(void const * params)
  136. {
  137. #if 0
  138. MBDBG printf("Switch to bootloader!\r\n");
  139. rtc_set_load_mode(1);
  140. HAL_NVIC_SystemReset();
  141. #endif
  142. }
  143. // Запуск таймера на изменение системных настроек
  144. void settings_timer(void const * params)
  145. {
  146. #if 0
  147. set_sys_settings_flag = false;
  148. psw_ok = false;
  149. #endif
  150. }
  151. // Запуск таймера для изменение настроек modbus
  152. void modbus_port_timer(void const * params)
  153. {
  154. #if 0
  155. eMBRTUStop();
  156. // Были транзакции по modbus с новыми настройками.
  157. // Нужно сохранить новые настройки.
  158. if (mb_package_flag)
  159. {
  160. settings.com_settings.mb_port = temp_modbus_port;
  161. settings_set_modbus_params(settings.com_settings.mb_port);
  162. settings_init_mb_port(settings.com_settings.mb_addr);
  163. settings_save();
  164. }
  165. // Нужно вернуть старые настройки
  166. else
  167. {
  168. temp_modbus_port = settings.com_settings.mb_port;
  169. settings_set_modbus_params(settings.com_settings.mb_port);
  170. settings_init_mb_port(settings.com_settings.mb_addr);
  171. }
  172. MBDBG settings_print_modbus();
  173. eMBRTUStart();
  174. eMBEnable();
  175. #endif
  176. }
  177. // ------------------------------------------------------------------- //
  178. // Modbus callback's
  179. // ------------------------------------------------------------------- //
  180. //
  181. // 65 (0x41) Read Input Registers
  182. eMBErrorCode
  183. eMBUpdateCB( UCHAR * pucFrame, USHORT * usLen)
  184. {
  185. eMBErrorCode eStatus = MB_ENOERR;
  186. mb_package_flag = true;
  187. // Команда перехода в bootloader.
  188. if (pucFrame[1] == 0x01) {
  189. update_tim_start();
  190. }
  191. return eStatus;
  192. }
  193. eMBErrorCode
  194. eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
  195. {
  196. return MB_ENOREG;
  197. }
  198. // 03 (0x03) Read Holding Registers
  199. // чтение N регистров управления и уставок
  200. // 16 (0x10) Write Multiple registers
  201. // запись N регистров управления и уставок (0x10)
  202. eMBErrorCode
  203. eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )
  204. {
  205. eMBErrorCode eStatus = MB_ENOERR;
  206. int iRegIndex;
  207. mb_delay_action_t mb_act = MB_NO_ACTION;
  208. uint16_t regs_cnt = usNRegs;
  209. uint16_t index_param;
  210. uint8_t *ptr_buf = pucRegBuffer;
  211. uint16_t size;
  212. /*
  213. printf("usAddress: 0x%X\r\n", usAddress);
  214. printf("usNRegs: %u\r\n", usNRegs);
  215. printf("eMode: %u\r\n", eMode);
  216. printf("pucRegBuffer :%X\r\n", pucRegBuffer[0]);
  217. */
  218. save_mode_reset_cnt();
  219. mb_package_flag = true;
  220. iRegIndex = (int)(usAddress - usRegHoldingStart);
  221. #if 1
  222. switch (eMode)
  223. {
  224. case MB_REG_READ :
  225. while (regs_cnt)
  226. {
  227. // Поиск регистра
  228. if (!mb_find_param(iRegIndex, &index_param, &size))
  229. {
  230. return MB_ENOREG; // нет запрашиваемого регистра
  231. }
  232. else
  233. {
  234. MBDBG printf("reg: %X, index: %u, size: %u\r\n", iRegIndex, index_param, size);
  235. MBDBG printf("reg: %X\r\n", iRegIndex);
  236. mb_get_param(ptr_buf, index_param); // Вызов функции записи
  237. iRegIndex += size;
  238. ptr_buf += 2*size;
  239. regs_cnt -= size;
  240. }
  241. }
  242. break;
  243. case MB_REG_WRITE :
  244. while (regs_cnt)
  245. {
  246. // Поиск регистра
  247. if (!mb_find_param(iRegIndex, &index_param, &size))
  248. {
  249. return MB_ENOREG; // нет запрашиваемого регистра
  250. }
  251. else
  252. {
  253. MBDBG printf("reg: %X, index: %u, size: %u\r\n", iRegIndex, index_param, size);
  254. mb_act = mb_set_param(ptr_buf, index_param); // Вызов функции записи
  255. if (mb_act != MB_NO_ACTION)
  256. mb_action = mb_act;
  257. iRegIndex += size;
  258. ptr_buf += 2*size;
  259. regs_cnt -= size;
  260. if (mb_act == MB_PAS_ERR)
  261. return MB_EINVAL;
  262. }
  263. }
  264. break;
  265. }
  266. #endif
  267. return eStatus;
  268. }
  269. // 17 (0x11) Report Slave ID (Serial Line only)
  270. // чтение информации об устройстве (0x11)
  271. eMBException
  272. eMBFuncReportSlaveID( UCHAR * pucFrame, USHORT * usLen )
  273. {
  274. #if 1
  275. mb_package_flag = true;
  276. //*usLen = mb_get_info(&pucFrame[1]) + 3;
  277. #endif
  278. return MB_EX_NONE;
  279. }
  280. // чтение/запись значений из нескольких регистров флагов (Coil Status).
  281. // чтения N регистров параметров
  282. eMBErrorCode
  283. eMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils, eMBRegisterMode eMode )
  284. {
  285. return MB_ENOREG;
  286. }
  287. eMBErrorCode
  288. eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )
  289. {
  290. return MB_ENOREG;
  291. }
  292. // 0x42
  293. // Запрос на изменение адреса
  294. // Если запрос широковещательный, то нужно проверить присланный ID.
  295. eMBException
  296. eMBSetAddrIdCB( UCHAR * pucFrame, USHORT * usLen )
  297. {
  298. #if 0
  299. mb_package_flag = true;
  300. if (rcvAddress == MB_ADDRESS_BROADCAST)
  301. {
  302. if (mb_set_addr_id(&pucFrame[1], &new_slave_addr))
  303. mb_action = MB_CHANGE_ADDR;
  304. }
  305. // Адресный запрос. ID не проверяем
  306. else
  307. {
  308. if (mb_set_addr(&pucFrame[1], &new_slave_addr))
  309. {
  310. pucFrame[1] = new_slave_addr;
  311. mb_action = MB_CHANGE_ADDR;
  312. }
  313. else
  314. pucFrame[1] = MB_BOOT_ERR_WRONG_CONTENT;
  315. }
  316. *usLen = 2;
  317. #endif
  318. return MB_EX_NONE;
  319. }
  320. // 0x43
  321. eMBException
  322. eMBSetAddrSerialCB( UCHAR * pucFrame, USHORT * usLen )
  323. {
  324. #if 0
  325. mb_package_flag = true;
  326. if (rcvAddress == MB_ADDRESS_BROADCAST)
  327. {
  328. if (mb_set_addr_serial(&pucFrame[1], &new_slave_addr))
  329. mb_action = MB_CHANGE_ADDR;
  330. }
  331. // Адресный запрос. ID не проверяем
  332. else
  333. {
  334. if (mb_set_addr(&pucFrame[1], &new_slave_addr))
  335. {
  336. pucFrame[1] = new_slave_addr;
  337. mb_action = MB_CHANGE_ADDR;
  338. }
  339. else
  340. pucFrame[1] = MB_BOOT_ERR_WRONG_CONTENT;
  341. }
  342. *usLen = 2;
  343. #endif
  344. return MB_EX_NONE;
  345. }
  346. eMBException
  347. eMBFuncReadFileRecordCB( UCHAR * pucFrame, USHORT * usLen )
  348. {
  349. uint8_t byte_count;
  350. uint8_t reference_type;
  351. uint16_t record_index = 0;
  352. uint16_t record_num = 0;
  353. #if 0
  354. DBG printf("Recived: ");
  355. for (int i = 0; i < *usLen; i++)
  356. {
  357. DBG printf("%X ", pucFrame[i]);
  358. }
  359. DBG printf("\r\n");
  360. #endif
  361. byte_count = pucFrame[1];
  362. reference_type = pucFrame[2];
  363. record_index = pucFrame[3] << 8;
  364. record_index |= pucFrame[4];
  365. record_num = pucFrame[7] << 8;
  366. record_num |= pucFrame[8];
  367. #if 0
  368. DBG printf("Byte count: %u, reference_type: %u, \r\n",
  369. byte_count, reference_type);
  370. DBG printf("Record index: %u, record num: %u\r\n",
  371. record_index, record_num);
  372. #endif
  373. *usLen = 1 + mb_log_get_entry((uint8_t*)&pucFrame[1], record_index);
  374. return MB_EX_NONE;
  375. }