download.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. #include "download.h"
  2. #include "upload.h"
  3. #include "user_uart.h"
  4. #include "user_crc16.h"
  5. #include "base64.h"
  6. #include "string.h"
  7. #include "user_server.h"
  8. static uint32_t download_delay_count = 0;
  9. static bool coll_ready_stat = false;
  10. static uint16_t coll_sw_count = 0;
  11. static uint16_t check_download_count = 0;
  12. static download_work_stat_e download_work_stat = DOWNLOAD_DEV_TYPE;
  13. static uint32_t download_offline_timeout = 0;
  14. static bool download_offline_stat = true;
  15. static void set_download_offline(bool stat);
  16. modbus_work_s download_work = {
  17. .rtu_addr = COLL_UART_ADDR,
  18. .tx_size = 0,
  19. .rx_size = 0,
  20. .tx_buffer = {0},
  21. .rx_buffer = {0},
  22. .rtu_rec = {0},
  23. .modbusRx_stat = false,
  24. .modbusTx_stat = false,
  25. };
  26. /*******************************************************************************
  27. * @函数名称 downloadRx_receive
  28. * @函数说明 处理接收数据
  29. * @输入参数 data:数据指针
  30. size:数据长度
  31. * @输出参数 无
  32. * @返回参数 无
  33. *******************************************************************************/
  34. static void downloadRx_receive(uint8_t *data, uint16_t size)
  35. {
  36. memcpy(download_work.rx_buffer, data, size);
  37. download_work.rx_size = size;
  38. #if USE_BASE64 == 1
  39. uint8_t data[MODBUS_DATA_SIZE] = {0};
  40. if(download_work.rx_buffer[download_work.rx_size - 2] == '\r'
  41. && download_work.rx_buffer[download_work.rx_size - 1] == '\n')
  42. {
  43. download_work.rx_buffer[download_work.rx_size - 2] = '\0';
  44. int len = base64_decode((char *)download_work.rx_buffer, data);
  45. memcpy((void *)&(download_work.rtu_rd), data, len);
  46. memcpy((void *)&(download_work.rtu_rd.crc), &(data[len - 2]), 2);
  47. memcpy((void *)&(download_work.rtu_rec), data, len);
  48. memcpy((void *)&(download_work.rtu_rec.crc), &(data[len - 2]), 2);
  49. download_work.rtu_rec.dataSize = len - 6;
  50. download_work.modbusRx_stat = true;
  51. }
  52. #else
  53. memcpy((void *)&(download_work.rtu_rd), download_work.rx_buffer, download_work.rx_size);
  54. memcpy((void *)&(download_work.rtu_rd.crc), &(download_work.rx_buffer[download_work.rx_size - 2]), 2);
  55. memcpy((void *)&(download_work.rtu_rec), download_work.rx_buffer, download_work.rx_size);
  56. memcpy((void *)&(download_work.rtu_rec.crc), &(download_work.rx_buffer[download_work.rx_size - 2]), 2);
  57. download_work.rtu_rec.dataSize = download_work.rx_size - 6;
  58. download_work.modbusRx_stat = true;
  59. #endif
  60. }
  61. /*******************************************************************************
  62. * @函数名称 downloadTx_send
  63. * @函数说明 发送数据
  64. * @输入参数 无
  65. * @输出参数 无
  66. * @返回参数 无
  67. *******************************************************************************/
  68. static void downloadTx_send(uint8_t *data, int size)
  69. {
  70. #if USE_BASE64 == 1
  71. base64_encode(data, (char *)download_work.tx_buffer, size);
  72. int len = strlen((char *)download_work.tx_buffer);
  73. download_work.tx_buffer[len] = '\r';
  74. download_work.tx_buffer[len + 1] = '\n';
  75. download_work.tx_buffer[len + 2] = '\0';
  76. download_work.tx_size = len + 2;
  77. #else
  78. memcpy(download_work.tx_buffer, data, size);
  79. download_work.tx_size = size;
  80. #endif
  81. download_work.modbusTx_stat = true;
  82. vUser_usart1_send(download_work.tx_buffer, download_work.tx_size);
  83. }
  84. /*******************************************************************************
  85. * @函数名称 rtu_protocol_sd_dev_type
  86. * @函数说明 设置询问从机设备类型数据
  87. * @输入参数 data:数据指针
  88. * @输出参数 无
  89. * @返回参数 无
  90. *******************************************************************************/
  91. static uint16_t rtu_protocol_sd_dev_type(uint8_t *data)
  92. {
  93. data[0] = download_work.rtu_addr;
  94. data[1] = CMD_RD_REG;
  95. data[2] = (uint8_t)(REG_DEV_TYPE_ADDR >> 8);
  96. data[3] = (uint8_t)REG_DEV_TYPE_ADDR;
  97. data[4] = 0x00;
  98. data[5] = 0x01;
  99. check_download_count++;
  100. return 6;
  101. }
  102. /*******************************************************************************
  103. * @函数名称 rtu_protocol_sd_coll_stat
  104. * @函数说明 设置询问从机就绪状态数据
  105. * @输入参数 data:数据指针
  106. * @输出参数 无
  107. * @返回参数 无
  108. *******************************************************************************/
  109. static uint16_t rtu_protocol_sd_coll_stat(uint8_t *data)
  110. {
  111. data[0] = download_work.rtu_addr;
  112. data[1] = CMD_RD_REG;
  113. data[2] = (uint8_t)(REG_COLL_STAT_ADDR >> 8);
  114. data[3] = (uint8_t)REG_COLL_STAT_ADDR;
  115. data[4] = 0x00;
  116. data[5] = 0x01;
  117. return 6;
  118. }
  119. /*******************************************************************************
  120. * @函数名称 rtu_protocol_sd_coll_count
  121. * @函数说明 设置询问从机包含的主板总数数据
  122. * @输入参数 data:数据指针
  123. * @输出参数 无
  124. * @返回参数 无
  125. *******************************************************************************/
  126. static uint16_t rtu_protocol_sd_coll_count(uint8_t *data)
  127. {
  128. data[0] = download_work.rtu_addr;
  129. data[1] = CMD_RD_REG;
  130. data[2] = (uint8_t)(REG_COLL_COUNT_ADDR >> 8);
  131. data[3] = (uint8_t)REG_COLL_COUNT_ADDR;
  132. data[4] = 0x00;
  133. data[5] = 0x01;
  134. return 6;
  135. }
  136. /*******************************************************************************
  137. * @函数名称 rtu_protocol_sd_sw_stat
  138. * @函数说明 设置询问从机包含的开关量数据
  139. * @输入参数 data:数据指针
  140. * @输出参数 无
  141. * @返回参数 无
  142. *******************************************************************************/
  143. static uint16_t rtu_protocol_sd_sw_stat(uint8_t *data)
  144. {
  145. data[0] = download_work.rtu_addr;
  146. data[1] = CMD_RD_REG;
  147. data[2] = (uint8_t)(REG_COLL_SW_HIGH_STAT_ADDR >> 8);
  148. data[3] = (uint8_t)REG_COLL_SW_HIGH_STAT_ADDR;
  149. data[4] = 0x00;
  150. data[5] = 0x02;
  151. return 6;
  152. }
  153. /*******************************************************************************
  154. * @函数名称 rtu_protocol_send
  155. * @函数说明 发送数据
  156. * @输入参数 data:数据指针
  157. size:数据长度
  158. * @输出参数 无
  159. * @返回参数 无
  160. *******************************************************************************/
  161. static void rtu_protocol_send(uint8_t *data, int size)
  162. {
  163. uint16_t crc = 0xFFFF;
  164. crc = GetCRC16(data, size, crc);
  165. memcpy(&data[size], &crc, 2);
  166. downloadTx_send(data, size + 2);
  167. }
  168. /*******************************************************************************
  169. * @函数名称 rtu_protocol_sd_task
  170. * @函数说明 发送数据任务
  171. * @输入参数 无
  172. * @输出参数 无
  173. * @返回参数 无
  174. *******************************************************************************/
  175. static void rtu_protocol_sd_task(void)
  176. {
  177. uint8_t data[MODBUS_DATA_SIZE] = {0};
  178. uint16_t datasize = 0;
  179. switch(download_work_stat)
  180. {
  181. case DOWNLOAD_DEV_TYPE:datasize = rtu_protocol_sd_dev_type(data);break;
  182. case DOWNLOAD_COLL_REDAY_STAT:datasize = rtu_protocol_sd_coll_stat(data);break;
  183. case DOWNLOAD_COLL_COUNT:datasize = rtu_protocol_sd_coll_count(data);break;
  184. case DOWNLOAD_SW_STAT:datasize = rtu_protocol_sd_sw_stat(data);break;
  185. default:{
  186. download_work_stat = DOWNLOAD_DEV_TYPE;
  187. datasize = rtu_protocol_sd_dev_type(data);
  188. }break;
  189. }
  190. rtu_protocol_send(data, datasize);
  191. }
  192. /*******************************************************************************
  193. * @函数名称 rtu_protocol_rd_dev_type_parsing
  194. * @函数说明 解析读取设备类型
  195. * @输入参数 rd:数据
  196. * @输出参数 无
  197. * @返回参数 无
  198. *******************************************************************************/
  199. static bool rtu_protocol_rd_dev_type_parsing(rtu_rd_s *rd)
  200. {
  201. uint16_t temp = 0;
  202. temp = rd->data[0];
  203. temp <<= 8;
  204. temp += rd->data[1];
  205. if(temp == (uint16_t)COLL_UART_ADDR)
  206. {
  207. download_work_stat = DOWNLOAD_COLL_REDAY_STAT;
  208. check_download_count = 0;
  209. return true;
  210. }
  211. return false;
  212. }
  213. /*******************************************************************************
  214. * @函数名称 rtu_protocol_rd_coll_stat_parsing
  215. * @函数说明 解析读取设备就绪状态
  216. * @输入参数 rd:数据
  217. * @输出参数 无
  218. * @返回参数 无
  219. *******************************************************************************/
  220. static bool rtu_protocol_rd_coll_stat_parsing(rtu_rd_s *rd)
  221. {
  222. uint16_t temp = 0;
  223. temp = rd->data[0];
  224. temp <<= 8;
  225. temp += rd->data[1];
  226. if(temp == COLL_READY_STAT)
  227. {
  228. download_work_stat = DOWNLOAD_COLL_COUNT;
  229. coll_ready_stat = true;
  230. return true;
  231. }
  232. return false;
  233. }
  234. /*******************************************************************************
  235. * @函数名称 rtu_protocol_rd_coll_count_parsing
  236. * @函数说明 解析读取下挂主板数量
  237. * @输入参数 rd:数据
  238. * @输出参数 无
  239. * @返回参数 无
  240. *******************************************************************************/
  241. static bool rtu_protocol_rd_coll_count_parsing(rtu_rd_s *rd)
  242. {
  243. uint16_t temp = 0;
  244. temp = rd->data[0];
  245. temp <<= 8;
  246. temp += rd->data[1];
  247. if(temp < COLL_MAX_COUNT)
  248. {
  249. coll_sw_count = temp;
  250. download_work_stat = DOWNLOAD_SW_STAT;
  251. vUser_server_set_coll_stat(coll_sw_count);
  252. return true;
  253. }
  254. return false;
  255. }
  256. /*******************************************************************************
  257. * @函数名称 rtu_protocol_rd_sw_stat_parsing
  258. * @函数说明 解析读取下挂主板开关量状态
  259. * @输入参数 rd:数据
  260. * @输出参数 无
  261. * @返回参数 无
  262. *******************************************************************************/
  263. static bool rtu_protocol_rd_sw_stat_parsing(rtu_rd_s *rd)
  264. {
  265. uint32_t temp = 0;
  266. if(rd->dataSize != 4)
  267. {
  268. return false;
  269. }
  270. temp = rd->data[0];
  271. temp <<= 8;
  272. temp += rd->data[1];
  273. temp <<= 8;
  274. temp += rd->data[2];
  275. temp <<= 8;
  276. temp += rd->data[3];
  277. vUser_server_set_download_sw_stat(temp);
  278. return true;
  279. }
  280. /*******************************************************************************
  281. * @函数名称 rtu_protocol_rd_reg_parsing
  282. * @函数说明 解析读指令返回的数据
  283. * @输入参数 rd:数据
  284. * @输出参数 无
  285. * @返回参数 无
  286. *******************************************************************************/
  287. static bool rtu_protocol_rd_reg_parsing(rtu_rd_s *rd)
  288. {
  289. bool stat = false;
  290. switch(download_work_stat)
  291. {
  292. case DOWNLOAD_DEV_TYPE:stat = rtu_protocol_rd_dev_type_parsing(rd);break;
  293. case DOWNLOAD_COLL_REDAY_STAT:stat = rtu_protocol_rd_coll_stat_parsing(rd);break;
  294. case DOWNLOAD_COLL_COUNT:stat = rtu_protocol_rd_coll_count_parsing(rd);break;
  295. case DOWNLOAD_SW_STAT:stat = rtu_protocol_rd_sw_stat_parsing(rd);break;
  296. default:break;
  297. }
  298. return stat;
  299. }
  300. /*******************************************************************************
  301. * @函数名称 rtu_rd_protocol_parsing
  302. * @函数说明 读指令返回解析
  303. * @输入参数 rd:数据
  304. * @输出参数 无
  305. * @返回参数 无
  306. *******************************************************************************/
  307. static bool rtu_rd_protocol_parsing(rtu_rd_s *rd)
  308. {
  309. uint16_t crc = 0xFFFF;
  310. crc = GetCRC16((uint8_t *)rd, rd->dataSize + 3, crc);
  311. if(crc != rd->crc)
  312. {
  313. return false;
  314. }
  315. if(rd->func == CMD_RD_REG)
  316. {
  317. if(true == rtu_protocol_rd_reg_parsing(rd))
  318. {
  319. return true;
  320. }
  321. }
  322. return false;
  323. }
  324. /*******************************************************************************
  325. * @函数名称 rtu_protocol_wr_reg_parsing
  326. * @函数说明 写指令数据解析
  327. * @输入参数 rec:数据
  328. * @输出参数 无
  329. * @返回参数 无
  330. *******************************************************************************/
  331. static bool rtu_protocol_wr_reg_parsing(rtu_rec_s *rec)
  332. {
  333. uint16_t reg_addr = 0;
  334. reg_addr = rec->regAddr[0];
  335. reg_addr <<= 8;
  336. reg_addr += rec->regAddr[1];
  337. switch(reg_addr)
  338. {
  339. default:break;
  340. }
  341. return false;
  342. }
  343. /*******************************************************************************
  344. * @函数名称 rtu_rec_protocol_parsing
  345. * @函数说明 写指令返回解析
  346. * @输入参数 rec:数据
  347. * @输出参数 无
  348. * @返回参数 无
  349. *******************************************************************************/
  350. static bool rtu_rec_protocol_parsing(rtu_rec_s *rec)
  351. {
  352. uint16_t crc = 0xFFFF;
  353. crc = GetCRC16((uint8_t *)rec, rec->dataSize + 4, crc);
  354. if(crc != rec->crc)
  355. {
  356. return false;
  357. }
  358. if(rec->func == CMD_WR_REG)
  359. {
  360. if(true == rtu_protocol_wr_reg_parsing(rec))
  361. {
  362. return true;
  363. }
  364. }
  365. return false;
  366. }
  367. /*******************************************************************************
  368. * @函数名称 rtu_protocol_parsing
  369. * @函数说明 返回数据解析
  370. * @输入参数 无
  371. * @输出参数 无
  372. * @返回参数 无
  373. *******************************************************************************/
  374. static bool rtu_protocol_parsing(void)
  375. {
  376. if(download_work.rtu_rec.addr != download_work.rtu_addr)
  377. {
  378. return false;
  379. }
  380. if(download_work.rtu_rec.func == CMD_RD_REG)
  381. {
  382. if(true == rtu_rd_protocol_parsing(&(download_work.rtu_rd)))
  383. {
  384. set_download_offline(false);
  385. }
  386. }
  387. else if(download_work.rtu_rec.func == CMD_WR_REG)
  388. {
  389. if(true == rtu_rec_protocol_parsing(&(download_work.rtu_rec)))
  390. {
  391. set_download_offline(false);
  392. }
  393. }
  394. else{
  395. download_work_stat = DOWNLOAD_DEV_TYPE;
  396. }
  397. }
  398. /************************************************
  399. * 函数名:set_dowload_offline
  400. * 描述 :设置从机通讯状态灯
  401. * 输入 :stat:通讯状态
  402. * 输出 :无
  403. * 注意 :无
  404. ************************************************/
  405. static void set_download_offline(bool stat)
  406. {
  407. if(stat == true)
  408. {
  409. download_offline_timeout = 5000;
  410. if(download_offline_stat == false)
  411. {
  412. download_offline_stat = true;
  413. }
  414. }
  415. else{
  416. if(download_offline_stat == true)
  417. {
  418. download_offline_stat = false;
  419. }
  420. }
  421. }
  422. /************************************************
  423. * 函数名:vDowload_tick
  424. * 描述 :任务计时器
  425. * 输入 :无
  426. * 输出 :无
  427. * 注意 :无
  428. ************************************************/
  429. void vDownload_tick(void)
  430. {
  431. if(download_delay_count > 0)
  432. {
  433. download_delay_count--;
  434. }
  435. if(download_offline_timeout > 0)
  436. {
  437. download_offline_timeout--;
  438. }
  439. else{
  440. set_download_offline(true);
  441. }
  442. }
  443. /************************************************
  444. * 函数名:vDownload_pro
  445. * 描述 :执行任务
  446. * 输入 :无
  447. * 输出 :无
  448. * 注意 :无
  449. ************************************************/
  450. void vDownload_pro(void)
  451. {
  452. if(download_delay_count == 0)
  453. {
  454. download_delay_count = 500;
  455. if(check_download_count >= MAX_REPLAY_COUNT)
  456. {
  457. vUser_server_set_coll_stat(0);
  458. }
  459. rtu_protocol_sd_task();
  460. }
  461. if(download_work.modbusRx_stat == true)
  462. {
  463. download_work.modbusRx_stat = false;
  464. rtu_protocol_parsing();
  465. }
  466. }
  467. /*******************************************************************************
  468. * @函数名称 vUpload_init
  469. * @函数说明 初始化
  470. * @输入参数 无
  471. * @输出参数 无
  472. * @返回参数 无
  473. *******************************************************************************/
  474. void vDownload_init(void)
  475. {
  476. user_uart_param_s param = {
  477. .baudrate = 115200,
  478. .wordlength = USART_WordLength_8b,
  479. .stopbit = USART_StopBits_1,
  480. .parity = USART_Parity_No,
  481. };
  482. vUser_usart1_init(&param);
  483. vUser_usart1_set_data_upload_func(downloadRx_receive);
  484. }