bluetooth.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. #include "head.h"
  2. #include "bluetooth.h"
  3. // #define BL_DEBUG // 调试打印
  4. #define FREAM_SPLIT_LEN (240) // 分帧长度
  5. #define FREAM_INTERVAL_TIME_MS (65) // 帧间隔ms,手册建议帧间隔60ms以上
  6. #define BL_DISC_REBOOT_TIME_MS (100) // 连接断开复位蓝牙延时ms
  7. #define BL_IDLE_REBOOT_TIME_MS (120000) // 蓝牙空闲状态自动复位延时ms
  8. #define BL_ENABLE_RESEND_MODE (1) // 重发机制
  9. #define BL_RESEND_TIMES (3) // 重发次数
  10. #define BL_RECV_TIMEOUT_MS (500) // 接收超时时间
  11. #define BL_TIMEOUT_RESEND_MS (500) // 超时重发时间
  12. #define BLUETOOTH_DEFAULT_NAME "OLE-DTUv5" // 蓝牙默认名称,获取ID失败时设置此蓝牙名称
  13. /* 各指令详细描述请参考蓝牙手册,路径:Z:\研发中心\研发二部\共享\88_DTU5.0\02蓝牙模块 */
  14. /* AT指令匹配列表 */
  15. const struct at_cmd_index_match at_cmd_index_match[AT_CMD_MAX] =
  16. {
  17. //指令字符串 追加字符串 指令结束字符串 数据段结束字符串 指令结果结束字符串 指令匹配的枚举类型
  18. {"SCAN" , "=" , "{\r\n" , "}\r\n" , NULL , AT_CMD_SACN },
  19. {"CONN" , "=" , "=" , NULL , NULL , AT_CMD_CONN },
  20. {"CHINFO" , "" , "{\r\n" , "}\r\n" , "OK\r\n" , AT_CMD_CHINFO },
  21. {"LESEND" , "=" , "\r\n" , NULL , "OK\r\n" , AT_CMD_LESEND },
  22. {"LEDISC" , "=" , "=" , "\r\n" , NULL , AT_CMD_LEDISC },
  23. {"NAME" , "=" , "=" , "\r\n" , "OK\r\n" , AT_CMD_NAME },
  24. {"MAC" , "" , "=" , "\r\n" , "OK\r\n" , AT_CMD_MAC },
  25. {"REBOOT" , "" , "\r\n" , NULL , "OK\r\n" , AT_CMD_REBOOT },
  26. {"DATA" , "" , "=" , "\r\n" , NULL , AT_CMD_DATA },
  27. {"GATTSTAT" , "" , "=" , "\r\n" , NULL , AT_CMD_STAT },
  28. };
  29. /**
  30. * @brief 获取一个buf
  31. * @details 从缓存队列中返回一个buf
  32. * @param _pt 结构体指针
  33. * @return buf索引
  34. * @author EWen
  35. * @date 2025-10-11
  36. * @remarks 增加发送队列缓存是考虑到多帧分帧放进缓存后自动发送,但目前报文组帧处理了可以一帧发完,暂时用不上
  37. */
  38. static u8 _get_one_buf(bl_tbuf_t *pt)
  39. {
  40. u8 head;
  41. head = pt->tb_head;
  42. pt->tb_head++;
  43. if(pt->tb_head >= BL_TBUF_NUM)
  44. {
  45. pt->tb_head = 0;
  46. }
  47. // 系统设计时,保证缓冲不会满,以下情况不应出现
  48. if(pt->tb_head==pt->tb_tail_ack || pt->tb_head==pt->tb_tail_send)
  49. {
  50. rt_printf_time("bluetooth: _get_one_buf error:head=%d,send=%d,ack=%d.\r\n",pt->tb_head,pt->tb_tail_send,pt->tb_tail_ack);
  51. }
  52. return head;
  53. }
  54. /**
  55. * @brief 确认一条发送的报文
  56. * @details none
  57. * @param _pt 结构体指针
  58. * @param _cmd_type 接收到的报文类型
  59. * @return none
  60. * @author EWen
  61. * @date 2025-10-11
  62. * @remarks Tnone
  63. */
  64. static void _ack_one_buf(bl_tbuf_t *pt, s8 _cmd_type)
  65. {
  66. if(_cmd_type == AT_CMD_DATA)
  67. {
  68. //蓝牙模块主动发送的数据不需进行发送确认
  69. return;
  70. }
  71. if(_cmd_type == AT_CMD_STAT)
  72. {
  73. u8 send_cmd_index;
  74. send_cmd_index = (pt->tb_tail_ack+1) >= BL_TBUF_NUM ? 0 : (pt->tb_tail_ack+1);
  75. // 不是因终端主动发起的命令而收到AT_CMD_STAT类型数据不需确认
  76. if(pt->tb_cmd[send_cmd_index] != AT_CMD_CONN\
  77. || pt->tb_cmd[send_cmd_index] != AT_CMD_LEDISC)
  78. return;
  79. }
  80. pt->tb_tail_ack++;
  81. if(pt->tb_tail_ack >= BL_TBUF_NUM)
  82. pt->tb_tail_ack = 0;
  83. #ifdef BL_DEBUG
  84. rt_printf("ack tb_head=%d,tb_tail_send=%d,tb_tail_ack=%d\r\n", pt->tb_head, pt->tb_tail_send, pt->tb_tail_ack);
  85. #endif
  86. }
  87. /**
  88. * @brief 组帧
  89. * @details none
  90. * @param _pt 结构体指针
  91. * @param _pdat 数据指针
  92. * @param _cmd 组帧类型
  93. * @param _len 数据长度
  94. * @return 0: 成功 其它: 失败
  95. * @author EWen
  96. * @date 2025-10-11
  97. * @remarks 目前格式字符填充部分最长长度为数据发送格式填充18字节
  98. */
  99. static int _frame_packing(BLUETOOTH_DEF *_pt,const u8 *_pdat, AT_CMD _cmd, u8 _len)
  100. {
  101. u8 i = 0;
  102. u8 head = 0;
  103. u8 *pd = NULL;
  104. u8 ext_len = 0;
  105. u8 str_len = 0;
  106. // 目前格式字符填充部分最长长度为数据发送格式填充18字节
  107. // 组帧buf首字节为发送长度因此再 -1
  108. if(_len >= BL_TBUF_LEN - 18 - 1)
  109. {
  110. rt_printf("蓝牙->%s 组帧数据长度越限,in len=%d,max=%d\r\n", __func__, _len, BL_TBUF_LEN - 19);
  111. return -1;
  112. }
  113. // 匹配at命令
  114. for(i = 0; i < AT_CMD_MAX; i++)
  115. {
  116. if(at_cmd_index_match[i].cmd == _cmd)
  117. break;
  118. }
  119. if(i == AT_CMD_MAX)
  120. {
  121. rt_printf("bluetooth: %s error! can't find cmd %d\r\n", __func__, _cmd);
  122. return -2;
  123. }
  124. head = _get_one_buf(&_pt->tx_buf[0]);
  125. _pt->tx_buf[0].tb_cmd[head] = _cmd;
  126. pd = &_pt->tx_buf[0].tb_data[head][1];
  127. // 固定头
  128. strcpy(pd,"AT+");
  129. pd += 3;
  130. ext_len += 3;
  131. // 根据_cmd 填充命令
  132. str_len = strlen(at_cmd_index_match[i].cmd_str);
  133. strncpy(pd,at_cmd_index_match[i].cmd_str,str_len);
  134. pd += str_len;
  135. ext_len += str_len;
  136. // 根据可选字符填充
  137. if(at_cmd_index_match[i].send_op_str)
  138. {
  139. str_len = strlen(at_cmd_index_match[i].send_op_str);
  140. strncpy(pd,at_cmd_index_match[i].send_op_str,str_len);
  141. pd += str_len;
  142. ext_len += str_len;
  143. }
  144. // 填充长度数据
  145. if(_cmd == AT_CMD_LESEND)
  146. {
  147. u8 tmp_len[6] = {0};
  148. *pd++ = '0';
  149. *pd++ = ',';
  150. ext_len += 2;
  151. sprintf(tmp_len,"%d", _len);
  152. str_len = strlen(tmp_len);
  153. strncpy(pd,tmp_len,str_len);
  154. pd+= str_len;
  155. ext_len +=str_len;
  156. *pd++ = ',';
  157. ext_len += 1;
  158. }
  159. // 填充发送数据
  160. if(_pdat)
  161. {
  162. memcpy(pd,_pdat,_len);
  163. pd += _len;
  164. }
  165. // 固定尾
  166. strcpy(pd,"\r\n");
  167. ext_len += 2;
  168. // 首字节为需发送报文长度
  169. _pt->tx_buf[0].tb_data[head][0] = _len+ext_len;
  170. #ifdef BL_DEBUG
  171. rt_printf_time("%s data:%d,ext:%d\r\n", __func__, _len, ext_len);
  172. for(i = 0; i < _len+ext_len; i++)
  173. {
  174. if(i!=0 && i%16==0) rt_printf("\r\n");
  175. rt_printf("%02x ",_pt->tx_buf[0].tb_data[head][i+1]);
  176. }
  177. rt_printf("\r\n");
  178. #endif
  179. return 0;
  180. }
  181. /**
  182. * @brief 设置蓝牙名称
  183. * @details none
  184. * @param _pt 结构体指针
  185. * @param _pdat 名称字符串指针
  186. * @param _len 名称长度
  187. * @return 0: 成功 其它: 失败
  188. * @author EWen
  189. * @date 2025-10-11
  190. * @remarks none
  191. */
  192. static int _name_set(BLUETOOTH_DEF *pt, const u8 *_pdat, u8 _len)
  193. {
  194. return _frame_packing(pt,_pdat,AT_CMD_NAME,_len);
  195. }
  196. /**
  197. * @brief 蓝牙模块软重启
  198. * @details none
  199. * @param _pt 结构体指针
  200. * @return 0: 成功 其它: 失败
  201. * @author EWen
  202. * @date 2025-10-11
  203. * @remarks none
  204. */
  205. static int _reboot(BLUETOOTH_DEF *pt)
  206. {
  207. return _frame_packing(pt,NULL,AT_CMD_REBOOT,0);
  208. }
  209. /**
  210. * @brief 断开蓝牙连接
  211. * @details none
  212. * @param _pt 结构体指针
  213. * @return 0: 成功 其它: 失败
  214. * @author EWen
  215. * @date 2025-10-11
  216. * @remarks 已连接状态才起作用,否则蓝牙模块不回复
  217. */
  218. static int _ledisc(BLUETOOTH_DEF *pt)
  219. {
  220. const u8 para = '0'; // 固定为 "0"
  221. if(!pt->lnk_sta){
  222. // 非连接状态下发送断开连接命令,蓝牙模块不会回复报文
  223. rt_printf("非连接状态下不能进行断开连接操作!\r\n");
  224. return -1;
  225. }
  226. return _frame_packing(pt,&para,AT_CMD_LEDISC,1);
  227. }
  228. /**
  229. * @brief 接收数据复位
  230. * @details none
  231. * @param _pt 结构体指针
  232. * @return 0: 成功 其它: 失败
  233. * @author EWen
  234. * @date 2025-10-11
  235. * @remarks none
  236. */
  237. static void _recv_rst(BLUETOOTH_DEF *pt,u8 num)
  238. {
  239. if(num == 10)
  240. {
  241. rt_printf_time("接收帧错误,超时未能接收到帧结束符号!!!\r\n");
  242. }
  243. if(pt->cTypeCounter)
  244. {
  245. rt_printf_time("bluetooth_recv_rst:state=%d,counter=%d,num=%d\r\n",pt->cTypeCounter,pt->cRecvCnt,num);
  246. }
  247. pt->cTypeCounter=0;
  248. pt->cRecvLenth=0;
  249. pt->cRecvCnt=0;
  250. pt->us0_recv = 0;
  251. }
  252. /**
  253. * @brief 蓝牙接收数据解析
  254. * @details 判断是否接收到完整一帧
  255. * @param _pt 结构体指针
  256. * @return 0: 成功 其它: 失败
  257. * @author EWen
  258. * @date 2025-10-11
  259. * @remarks none
  260. */
  261. static int _recv_parse(BLUETOOTH_DEF *pt, u8 c)
  262. {
  263. u8 i = 0;
  264. u8 match_count = 0;
  265. switch(pt->cTypeCounter)
  266. {
  267. case 0:
  268. if (c == '+') //固定起始符号
  269. {
  270. pt->cmd_type = -1;
  271. pt->cTypeCounter++;
  272. pt->us0_recv = bsp_ustimer_get_origin();
  273. memset(pt->cmd_recvbuf,'\0',sizeof(pt->cmd_recvbuf));
  274. }
  275. else
  276. {
  277. _recv_rst(pt,1);
  278. }
  279. break;
  280. case 1:
  281. pt->cmd_recvbuf[pt->cRecvCnt++] = c;
  282. if(pt->cRecvCnt >= CMD_RECVBUF_LEN)
  283. {
  284. _recv_rst(pt,2);
  285. rt_printf_time("接收指令错误,指令长度溢出!!!\r\n");
  286. break;
  287. }
  288. // 最短命令匹配字符MAC
  289. if(pt->cRecvCnt < 3)
  290. {
  291. break;
  292. }
  293. // 命令未匹配
  294. if(pt->cmd_type == -1)
  295. {
  296. for(i = 0; i < AT_CMD_MAX; i++)
  297. {
  298. // 匹配命令
  299. if(strstr(at_cmd_index_match[i].cmd_str,pt->cmd_recvbuf) != NULL)
  300. {
  301. match_count++;
  302. pt->cmd_type = at_cmd_index_match[i].cmd;
  303. break;
  304. }
  305. }
  306. // 3个字符都未能匹配一条,不支持命令,重新接收
  307. if(match_count == 0)
  308. {
  309. rt_printf("蓝牙接收->不支持的指令:%s\r\n",pt->cmd_recvbuf);
  310. pt->cmd_type = -1;
  311. _recv_rst(pt,3);
  312. break;
  313. }
  314. else if(match_count > 1)
  315. {
  316. // 多条匹配继续接收匹配
  317. pt->cmd_type = -1;
  318. }
  319. }
  320. else
  321. {
  322. if(strstr(pt->cmd_recvbuf,at_cmd_index_match[pt->cmd_type].cmd_end_str) != NULL)
  323. {
  324. #ifdef BL_DEBUG
  325. pt->cmd_recvbuf[pt->cRecvCnt - 1] = '\0';
  326. rt_printf("recv cmd:%s\r\n",pt->cmd_recvbuf);
  327. #endif
  328. // 命令结束,转入下一流程
  329. pt->cRecvCnt = 0;
  330. pt->cTypeCounter++;
  331. memset(pt->recvbuf,0,sizeof(pt->recvbuf));
  332. _ack_one_buf(&pt->tx_buf[0], pt->cmd_type);
  333. }
  334. }
  335. break;
  336. case 2:
  337. if(at_cmd_index_match[pt->cmd_type].data_end_str)
  338. {
  339. // 此帧包含数据
  340. pt->recvbuf[pt->cRecvCnt++] = c;
  341. if(pt->cRecvCnt >= BLUETOOTH_BUF_LEN)
  342. {
  343. _recv_rst(pt,4);
  344. rt_printf("蓝牙接收->数据长度溢出!!!\r\n");
  345. break;
  346. }
  347. if(c == '\n')
  348. {
  349. if(strstr(&pt->recvbuf[pt->cRecvCnt - strlen(at_cmd_index_match[pt->cmd_type].data_end_str)],at_cmd_index_match[pt->cmd_type].data_end_str) != NULL)
  350. {
  351. #ifdef BL_DEBUG
  352. int i = 0;
  353. rt_printf("recv data:\r\n");
  354. for(i = 0; i <= pt->cRecvCnt-1; i++)
  355. {
  356. if(i%16 == 0 && i != 0) rt_printf("\r\n");
  357. rt_printf("%02x ", pt->recvbuf[i]);
  358. }
  359. rt_printf("\r\n");
  360. #endif
  361. if(at_cmd_index_match[pt->cmd_type].sta_end_str)
  362. {
  363. pt->cRecvCnt = 0;
  364. pt->cTypeCounter++;
  365. }
  366. else
  367. {
  368. pt->bData = true;
  369. pt->cTypeCounter = 0;
  370. _recv_rst(pt,5);
  371. }
  372. }
  373. }
  374. }
  375. else if(at_cmd_index_match[pt->cmd_type].sta_end_str)
  376. {
  377. // 结果判断
  378. pt->cTypeCounter++;
  379. pt->cmd_recvbuf[pt->cRecvCnt++] = c;
  380. }
  381. else
  382. {
  383. _recv_rst(pt,6);
  384. rt_printf("%s %d unknowd operation!\r\n", __func__, __LINE__);
  385. }
  386. break;
  387. case 3:
  388. // 结果
  389. pt->cmd_recvbuf[pt->cRecvCnt++] = c;
  390. if(c == '\n')
  391. {
  392. #ifdef BL_DEBUG
  393. rt_printf("recv statue:%s", pt->cmd_recvbuf);
  394. #endif
  395. if(strstr(pt->cmd_recvbuf,"OK\r\n") != NULL)
  396. {
  397. pt->cmd_sta = true;
  398. if(at_cmd_index_match[pt->cmd_type].data_end_str)
  399. {
  400. pt->bData = true;
  401. }
  402. }
  403. else
  404. {
  405. rt_printf("蓝牙->执行%s->%s失败!!\r\n", at_cmd_index_match[pt->cmd_type].cmd_str, pt->cmd_recvbuf);
  406. }
  407. pt->cTypeCounter = 0;
  408. _recv_rst(pt,7);
  409. }
  410. break;
  411. default:
  412. _recv_rst(pt,8);
  413. break;
  414. }
  415. return 0;
  416. }
  417. /**
  418. * @brief 接收应用
  419. * @details 从fifo提取数据去解析
  420. * @param _pt 结构体指针
  421. * @return none
  422. * @author EWen
  423. * @date 2025-10-11
  424. * @remarks none
  425. */
  426. static void _recv_app(BLUETOOTH_DEF *pt)
  427. {
  428. u8 c;
  429. // 接收数据
  430. while(pt->bData == false)
  431. {
  432. if(rt_fifo_get(&pt->recv_fifo,&c,1) == 0)
  433. {
  434. if(pt->b_recv_reset)
  435. {
  436. _recv_rst(pt,10);
  437. pt->b_recv_reset = 0;
  438. }
  439. break;
  440. }
  441. _recv_parse(pt,c);
  442. }
  443. }
  444. /**
  445. * @brief 蓝牙接收数据解析
  446. * @details 数据接收判断时已将"+DATA="去除
  447. * @param _pt 结构体指针
  448. * @return 0: 成功 其它: 失败
  449. * @author EWen
  450. * @date 2025-10-11
  451. * @remarks 数据内容格式:+DATA=para1,para2,para3; para1:固定值0,para2:接收的数据长度,para3:接收的数据内容
  452. */
  453. static int _data_parse(BLUETOOTH_DEF *pt)
  454. {
  455. u16 i = 0;
  456. u8 *pd = NULL;
  457. char *endptr;
  458. u16 data_len = 0;
  459. u8 len_str[5] = {0};
  460. // 固定开头为 "0,"
  461. if(pt->recvbuf[0] != '0' || pt->recvbuf[1] != ',')
  462. {
  463. rt_printf("%s data format error!\r\n", __func__);
  464. return -1;
  465. }
  466. // 解析长度字符串
  467. pd = &pt->recvbuf[2];
  468. for(i = 0; i < 5; i++)
  469. {
  470. len_str[i] = *pd++;
  471. // 长度字符串以","结束,跳过","
  472. if(*pd == ',')
  473. {
  474. pd++;
  475. break;
  476. }
  477. }
  478. if(i == 5)
  479. {
  480. rt_printf("%s lenth error!\r\n", __func__);
  481. return -2;
  482. }
  483. else
  484. {
  485. data_len = strtol(len_str,&endptr,10);
  486. if(*endptr != '\0')
  487. {
  488. rt_printf("%s lenth strtol failed!\r\n", __func__);
  489. return -3;
  490. }
  491. #ifdef BL_DEBUG
  492. rt_printf("%s data_len:%d\r\n", __func__, data_len);
  493. #endif
  494. }
  495. for(i = 0; i < data_len; i++)
  496. {
  497. u8 j;
  498. int ret;
  499. ret = sec_recv(&pt->rx_buf,*pd++,pt->arrSendBuf,false);
  500. if(ret==SEC_FRAME_OK_APP) // 带规约的报文
  501. {
  502. rt_printf("未实现的蓝牙通讯帧处理->SEC_FRAME_OK_APP\r\n");
  503. }
  504. else if(ret==SEC_FRAME_OK_EXT) //纯安全扩展报文 发送
  505. {
  506. u16 remaining_length = 0;
  507. // 前两个字节为加密返回报文的长度
  508. remaining_length = ((pt->arrSendBuf[0]<<8)+(pt->arrSendBuf[1]));
  509. #ifdef BL_DEBUG
  510. rt_printf("esam data len->%d\r\n", remaining_length);
  511. #endif
  512. // 分帧
  513. // TODO 直接将报文分帧有较大几率证书管理工具会报错,此处已在加密报文处理中将每帧证书长度修改为220处理
  514. // 可以在一帧报文中将加密安全扩展报文发送,如确实需分帧的话要按照加密报文分帧处理再分帧,此处没有处理。。。
  515. if(remaining_length > FREAM_SPLIT_LEN)
  516. {
  517. for(j = 0;;j++)
  518. {
  519. if(remaining_length <= FREAM_SPLIT_LEN)
  520. {
  521. _frame_packing(pt,pt->arrSendBuf+2+j*FREAM_SPLIT_LEN,AT_CMD_LESEND,(u8)remaining_length);
  522. break;
  523. }
  524. _frame_packing(pt,pt->arrSendBuf+2+j*FREAM_SPLIT_LEN,AT_CMD_LESEND,FREAM_SPLIT_LEN);
  525. remaining_length -= FREAM_SPLIT_LEN;
  526. }
  527. }
  528. else
  529. {
  530. _frame_packing(pt,pt->arrSendBuf+2,AT_CMD_LESEND,(u8)remaining_length);
  531. }
  532. }
  533. }
  534. return 0;
  535. }
  536. /**
  537. * @brief 蓝牙连接状态解析
  538. * @details none
  539. * @param _pt 结构体指针
  540. * @return 0:成功 其它:失败
  541. * @author EWen
  542. * @date 2025-10-11
  543. * @remarks 数据格式0,0 1 2
  544. */
  545. static int _status_parse(BLUETOOTH_DEF *pt)
  546. {
  547. // 固定开头为 "0,"
  548. if(pt->recvbuf[0] != '0' || pt->recvbuf[1] != ',')
  549. {
  550. rt_printf("%s data format error!\r\n", __func__);
  551. return -1;
  552. }
  553. if(pt->recvbuf[2] == '1')
  554. {
  555. // 连接断开
  556. pt->lnk_sta = false;
  557. rt_printf("蓝牙连接断开!\r\n");
  558. pt->us0_disc_reboot = bsp_ustimer_get_origin();
  559. }
  560. else if(pt->recvbuf[2] == '2')
  561. {
  562. // 正在连接
  563. rt_printf("蓝牙连接中...\r\n");
  564. }
  565. else if(pt->recvbuf[2] == '3')
  566. {
  567. // 已连接
  568. pt->lnk_sta = true;
  569. rt_printf("蓝牙已连接!\r\n");
  570. }
  571. else
  572. {
  573. // 未知的连接状态
  574. rt_printf_time("蓝牙连接状态解析错误,未知的状态%d%d%d!\r\n",pt->recvbuf[0],pt->recvbuf[1],pt->recvbuf[2]);
  575. return -2;
  576. }
  577. return 0;
  578. }
  579. /**
  580. * @brief 蓝牙名称设置解析
  581. * @details 解析名称设置结果
  582. * @param _pt 结构体指针
  583. * @return none
  584. * @author EWen
  585. * @date 2025-10-11
  586. * @remarks none
  587. */
  588. static void _name_set_parse(BLUETOOTH_DEF *pt)
  589. {
  590. rt_printf("设置蓝牙名称:%s%s\r\n", pt->recvbuf, pt->cmd_sta ? "成功!" : "失败!");
  591. }
  592. /**
  593. * @brief 蓝牙数据初始化
  594. * @details none
  595. * @param _pt 结构体指针
  596. * @param chnl 通道
  597. * @return 0: 成功 其它: 失败
  598. * @author EWen
  599. * @date 2025-10-11
  600. * @remarks none
  601. */
  602. int bluetooth_init(BLUETOOTH_DEF *pt, u8 chnl)
  603. {
  604. u8 name_buf[30] = {0};
  605. RMT_FIXED_TABLE tfixedset;
  606. memset(pt,0,sizeof(BLUETOOTH_DEF));
  607. memset(&tfixedset,0,sizeof(tfixedset));
  608. tfixedset.num = RMT_FIXED_SET_NUM;
  609. tfixedset.set[0].type = FIXED_SET_ID;
  610. iec_get_fixedset_csv(&tfixedset);
  611. // 初始化接收buf结构
  612. pt->chnl = chnl;
  613. pt->rx_buf.chn = pt->chnl;
  614. pt->rx_buf.buf = pt->esambuf;
  615. rt_fifo_init(&pt->recv_fifo,pt->recv_fifo_buf,BLUETOOTH_BUF_LEN);
  616. if(tfixedset.set[0].len == 24)
  617. {
  618. /* ID 标准定义24位 */
  619. rt_printf("设置蓝牙名称:%s\r\n", tfixedset.set[0].str);
  620. memcpy(name_buf,tfixedset.set[0].str,tfixedset.set[0].len);
  621. }
  622. else
  623. {
  624. strcpy(name_buf,BLUETOOTH_DEFAULT_NAME);
  625. rt_printf("蓝牙: 未能从fixset.csv中获取到正确ID,使用默认名称:%s.\r\n", BLUETOOTH_DEFAULT_NAME);
  626. }
  627. _name_set(pt,name_buf,strlen(name_buf));
  628. _reboot(pt);
  629. return 0;
  630. }
  631. /**
  632. * @brief 蓝牙数据接收
  633. * @details 将数据存入fifo中
  634. * @param _pt 结构体指针
  635. * @param _byte 数据
  636. * @return none
  637. * @author EWen
  638. * @date 2025-10-11
  639. * @remarks none
  640. */
  641. void bluetooth_recv(BLUETOOTH_DEF *pt, u8 _byte)
  642. {
  643. rt_fifo_put(&pt->recv_fifo,&_byte,1);
  644. }
  645. /**
  646. * @brief 发送检查
  647. * @details none
  648. * @param _pt 结构体指针
  649. * @return none
  650. * @author EWen
  651. * @date 2025-10-11
  652. * @remarks 帧间隔延时精度受扫描间隔影响,实际测试到1000ms间隔发送也没什么问题
  653. */
  654. static void _send_polling(BLUETOOTH_DEF *_pt)
  655. {
  656. u8 *buf;
  657. u16 i = 0;
  658. u16 len = 0;
  659. u8 *pd,tb_send;
  660. bl_tbuf_t *pbuf;
  661. pbuf = &_pt->tx_buf[0];
  662. #if BL_ENABLE_RESEND_MODE
  663. // 上一帧未收到回复
  664. if(pbuf->tb_tail_send != pbuf->tb_tail_ack)
  665. {
  666. // 未超时不发下一帧
  667. if(bsp_ustimer_get_duration(_pt->us0_cfmtimeout) < USTIMER_MS*BL_TIMEOUT_RESEND_MS)
  668. {
  669. // tb_tail_send != tb_tail_ack,说明已进行过报文发送即更新过_pt->us0_cfmtimeout
  670. // 所以此处直接判断延时是否超时也没有问题
  671. return;
  672. }
  673. else
  674. {
  675. // 重发次数到达不再重发
  676. if(_pt->resend_cnt >= BL_RESEND_TIMES)
  677. {
  678. _pt->resend_cnt = 0;
  679. memset(_pt->tx_buf,0,sizeof(_pt->tx_buf));
  680. return;
  681. }
  682. // 超时重发
  683. pbuf->tb_tail_send--; // 发送尾索引回上一帧的位置进行重发
  684. _pt->resend_cnt++;
  685. rt_printf_time("超时重发上一帧,重发次数=%d,tb_head=%d,tb_tail_send=%d,len=%d\r\n", _pt->resend_cnt, pbuf->tb_head, pbuf->tb_tail_send, pbuf->tb_data[pbuf->tb_tail_send][0]);
  686. for(i = 0; i < pbuf->tb_data[pbuf->tb_tail_send][0]; i++)
  687. {
  688. if(i!=0 && i%16==0) rt_printf("\r\n");
  689. rt_printf("%02x ",pbuf->tb_data[pbuf->tb_tail_send][i+1]);
  690. }
  691. rt_printf("\r\n");
  692. }
  693. }
  694. #endif
  695. // 如果串口忙或者帧间隔时间未到,不能发送数据
  696. if(g_tRsComm[_pt->chnl].bextsend || bsp_ustimer_get_duration(_pt->us0_sendpiece) < USTIMER_MS*FREAM_INTERVAL_TIME_MS)
  697. {
  698. return;
  699. }
  700. if(pbuf->tb_head == pbuf->tb_tail_send)
  701. {
  702. return;
  703. }
  704. // 更新发送尾指针,保留老指针备用。
  705. tb_send = pbuf->tb_tail_send;
  706. pbuf->tb_tail_send++;
  707. if(pbuf->tb_tail_send >= BL_TBUF_NUM)
  708. {
  709. pbuf->tb_tail_send = 0;
  710. }
  711. #ifdef BL_DEBUG
  712. rt_printf("send tb_head=%dtb_tail_send=%dtb_tail_ack=%d\r\n", pbuf->tb_head, pbuf->tb_tail_send, pbuf->tb_tail_ack);
  713. #endif
  714. //将数据复制到真正发送的buf
  715. len = pbuf->tb_data[tb_send][0];
  716. pd = g_tRsComm[_pt->chnl].extsendbuf;
  717. memcpy(pd,&pbuf->tb_data[tb_send][1],len);
  718. g_tRsComm[_pt->chnl].extsendcnt=0;
  719. g_tRsComm[_pt->chnl].extsendlen=len;
  720. g_tRsComm[_pt->chnl].bextsend=true;
  721. #ifdef BL_DEBUG
  722. {
  723. rt_printf_time("bluetooth send data:%d\r\n",len);
  724. for(i = 0; i <len; i++)
  725. {
  726. if(i!=0 && i%16==0) rt_printf("\r\n");
  727. rt_printf("%02x ",g_tRsComm[_pt->chnl].extsendbuf[i]);
  728. }
  729. rt_printf("\r\n");
  730. }
  731. #endif
  732. _pt->us0_cfmtimeout=_pt->us0_sendpiece=bsp_ustimer_get_origin();
  733. }
  734. /**
  735. * @brief 蓝牙应用巡检
  736. * @details none
  737. * @param _pt 结构体指针
  738. * @return 0:成功 其它:失败
  739. * @author EWen
  740. * @date 2025-10-11
  741. * @remarks none
  742. */
  743. int bluetooth_app(BLUETOOTH_DEF *pt)
  744. {
  745. _recv_app(pt);
  746. if(pt->bData)
  747. {
  748. switch (pt->cmd_type)
  749. {
  750. case AT_CMD_DATA:
  751. _data_parse(pt);
  752. break;
  753. case AT_CMD_STAT:
  754. _status_parse(pt);
  755. break;
  756. case AT_CMD_NAME:
  757. _name_set_parse(pt);
  758. break;
  759. default:
  760. rt_printf("%s 未支持的指令类型->%d\r\n", __func__, pt->cmd_type);
  761. break;
  762. }
  763. pt->bData = false;
  764. }
  765. _send_polling(pt);
  766. return 0;
  767. }
  768. /**
  769. * @brief 蓝牙定时器
  770. * @details 处理一些定时任务
  771. * @param _pt 结构体指针
  772. * @return none
  773. * @author EWen
  774. * @date 2025-10-11
  775. * @remarks 延时精度受扫描间隔影响,但实际在此处理的操作实时性要求不高,因此没有关系
  776. */
  777. void bluetooth_timer(BLUETOOTH_DEF *pt)
  778. {
  779. if(pt->us0_disc_reboot)
  780. {
  781. if(bsp_ustimer_get_duration(pt->us0_disc_reboot) >= BL_DISC_REBOOT_TIME_MS*USTIMER_MS)
  782. {
  783. _reboot(pt);
  784. pt->us0_disc_reboot = 0;
  785. }
  786. }
  787. if(pt->lnk_sta)
  788. {
  789. pt->us0_idle_reboot = 0;
  790. }
  791. else
  792. {
  793. if(pt->us0_idle_reboot == 0)
  794. {
  795. pt->us0_idle_reboot = bsp_ustimer_get_origin();
  796. }
  797. else
  798. {
  799. if(bsp_ustimer_get_duration(pt->us0_idle_reboot) >= BL_IDLE_REBOOT_TIME_MS*USTIMER_MS)
  800. {
  801. _reboot(pt);
  802. pt->us0_idle_reboot = 0;
  803. }
  804. }
  805. }
  806. if(pt->us0_recv)
  807. {
  808. if(bsp_ustimer_get_duration(pt->us0_recv) >= BL_RECV_TIMEOUT_MS*USTIMER_MS)
  809. {
  810. pt->us0_recv = 0;
  811. pt->b_recv_reset = true;
  812. }
  813. }
  814. }