modbus.c 11 KB

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