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