#include "head.h" #include "bluetooth.h" // #define BL_DEBUG // 调试打印 #define FREAM_SPLIT_LEN (240) // 分帧长度 #define FREAM_INTERVAL_TIME_MS (65) // 帧间隔ms,手册建议帧间隔60ms以上 #define BL_DISC_REBOOT_TIME_MS (100) // 连接断开复位蓝牙延时ms #define BL_IDLE_REBOOT_TIME_MS (120000) // 蓝牙空闲状态自动复位延时ms #define BL_ENABLE_RESEND_MODE (1) // 重发机制 #define BL_RESEND_TIMES (3) // 重发次数 #define BL_RECV_TIMEOUT_MS (500) // 接收超时时间 #define BL_TIMEOUT_RESEND_MS (500) // 超时重发时间 #define BLUETOOTH_DEFAULT_NAME "OLE-DTUv5" // 蓝牙默认名称,获取ID失败时设置此蓝牙名称 /* 各指令详细描述请参考蓝牙手册,路径:Z:\研发中心\研发二部\共享\88_DTU5.0\02蓝牙模块 */ /* AT指令匹配列表 */ const struct at_cmd_index_match at_cmd_index_match[AT_CMD_MAX] = { //指令字符串 追加字符串 指令结束字符串 数据段结束字符串 指令结果结束字符串 指令匹配的枚举类型 {"SCAN" , "=" , "{\r\n" , "}\r\n" , NULL , AT_CMD_SACN }, {"CONN" , "=" , "=" , NULL , NULL , AT_CMD_CONN }, {"CHINFO" , "" , "{\r\n" , "}\r\n" , "OK\r\n" , AT_CMD_CHINFO }, {"LESEND" , "=" , "\r\n" , NULL , "OK\r\n" , AT_CMD_LESEND }, {"LEDISC" , "=" , "=" , "\r\n" , NULL , AT_CMD_LEDISC }, {"NAME" , "=" , "=" , "\r\n" , "OK\r\n" , AT_CMD_NAME }, {"MAC" , "" , "=" , "\r\n" , "OK\r\n" , AT_CMD_MAC }, {"REBOOT" , "" , "\r\n" , NULL , "OK\r\n" , AT_CMD_REBOOT }, {"DATA" , "" , "=" , "\r\n" , NULL , AT_CMD_DATA }, {"GATTSTAT" , "" , "=" , "\r\n" , NULL , AT_CMD_STAT }, }; /** * @brief 获取一个buf * @details 从缓存队列中返回一个buf * @param _pt 结构体指针 * @return buf索引 * @author EWen * @date 2025-10-11 * @remarks 增加发送队列缓存是考虑到多帧分帧放进缓存后自动发送,但目前报文组帧处理了可以一帧发完,暂时用不上 */ static u8 _get_one_buf(bl_tbuf_t *pt) { u8 head; head = pt->tb_head; pt->tb_head++; if(pt->tb_head >= BL_TBUF_NUM) { pt->tb_head = 0; } // 系统设计时,保证缓冲不会满,以下情况不应出现 if(pt->tb_head==pt->tb_tail_ack || pt->tb_head==pt->tb_tail_send) { 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); } return head; } /** * @brief 确认一条发送的报文 * @details none * @param _pt 结构体指针 * @param _cmd_type 接收到的报文类型 * @return none * @author EWen * @date 2025-10-11 * @remarks Tnone */ static void _ack_one_buf(bl_tbuf_t *pt, s8 _cmd_type) { if(_cmd_type == AT_CMD_DATA) { //蓝牙模块主动发送的数据不需进行发送确认 return; } if(_cmd_type == AT_CMD_STAT) { u8 send_cmd_index; send_cmd_index = (pt->tb_tail_ack+1) >= BL_TBUF_NUM ? 0 : (pt->tb_tail_ack+1); // 不是因终端主动发起的命令而收到AT_CMD_STAT类型数据不需确认 if(pt->tb_cmd[send_cmd_index] != AT_CMD_CONN\ || pt->tb_cmd[send_cmd_index] != AT_CMD_LEDISC) return; } pt->tb_tail_ack++; if(pt->tb_tail_ack >= BL_TBUF_NUM) pt->tb_tail_ack = 0; #ifdef BL_DEBUG 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); #endif } /** * @brief 组帧 * @details none * @param _pt 结构体指针 * @param _pdat 数据指针 * @param _cmd 组帧类型 * @param _len 数据长度 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks 目前格式字符填充部分最长长度为数据发送格式填充18字节 */ static int _frame_packing(BLUETOOTH_DEF *_pt,const u8 *_pdat, AT_CMD _cmd, u8 _len) { u8 i = 0; u8 head = 0; u8 *pd = NULL; u8 ext_len = 0; u8 str_len = 0; // 目前格式字符填充部分最长长度为数据发送格式填充18字节 // 组帧buf首字节为发送长度因此再 -1 if(_len >= BL_TBUF_LEN - 18 - 1) { rt_printf("蓝牙->%s 组帧数据长度越限,in len=%d,max=%d\r\n", __func__, _len, BL_TBUF_LEN - 19); return -1; } // 匹配at命令 for(i = 0; i < AT_CMD_MAX; i++) { if(at_cmd_index_match[i].cmd == _cmd) break; } if(i == AT_CMD_MAX) { rt_printf("bluetooth: %s error! can't find cmd %d\r\n", __func__, _cmd); return -2; } head = _get_one_buf(&_pt->tx_buf[0]); _pt->tx_buf[0].tb_cmd[head] = _cmd; pd = &_pt->tx_buf[0].tb_data[head][1]; // 固定头 strcpy(pd,"AT+"); pd += 3; ext_len += 3; // 根据_cmd 填充命令 str_len = strlen(at_cmd_index_match[i].cmd_str); strncpy(pd,at_cmd_index_match[i].cmd_str,str_len); pd += str_len; ext_len += str_len; // 根据可选字符填充 if(at_cmd_index_match[i].send_op_str) { str_len = strlen(at_cmd_index_match[i].send_op_str); strncpy(pd,at_cmd_index_match[i].send_op_str,str_len); pd += str_len; ext_len += str_len; } // 填充长度数据 if(_cmd == AT_CMD_LESEND) { u8 tmp_len[6] = {0}; *pd++ = '0'; *pd++ = ','; ext_len += 2; sprintf(tmp_len,"%d", _len); str_len = strlen(tmp_len); strncpy(pd,tmp_len,str_len); pd+= str_len; ext_len +=str_len; *pd++ = ','; ext_len += 1; } // 填充发送数据 if(_pdat) { memcpy(pd,_pdat,_len); pd += _len; } // 固定尾 strcpy(pd,"\r\n"); ext_len += 2; // 首字节为需发送报文长度 _pt->tx_buf[0].tb_data[head][0] = _len+ext_len; #ifdef BL_DEBUG rt_printf_time("%s data:%d,ext:%d\r\n", __func__, _len, ext_len); for(i = 0; i < _len+ext_len; i++) { if(i!=0 && i%16==0) rt_printf("\r\n"); rt_printf("%02x ",_pt->tx_buf[0].tb_data[head][i+1]); } rt_printf("\r\n"); #endif return 0; } /** * @brief 设置蓝牙名称 * @details none * @param _pt 结构体指针 * @param _pdat 名称字符串指针 * @param _len 名称长度 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks none */ static int _name_set(BLUETOOTH_DEF *pt, const u8 *_pdat, u8 _len) { return _frame_packing(pt,_pdat,AT_CMD_NAME,_len); } /** * @brief 蓝牙模块软重启 * @details none * @param _pt 结构体指针 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks none */ static int _reboot(BLUETOOTH_DEF *pt) { return _frame_packing(pt,NULL,AT_CMD_REBOOT,0); } /** * @brief 断开蓝牙连接 * @details none * @param _pt 结构体指针 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks 已连接状态才起作用,否则蓝牙模块不回复 */ static int _ledisc(BLUETOOTH_DEF *pt) { const u8 para = '0'; // 固定为 "0" if(!pt->lnk_sta){ // 非连接状态下发送断开连接命令,蓝牙模块不会回复报文 rt_printf("非连接状态下不能进行断开连接操作!\r\n"); return -1; } return _frame_packing(pt,¶,AT_CMD_LEDISC,1); } /** * @brief 接收数据复位 * @details none * @param _pt 结构体指针 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks none */ static void _recv_rst(BLUETOOTH_DEF *pt,u8 num) { if(num == 10) { rt_printf_time("接收帧错误,超时未能接收到帧结束符号!!!\r\n"); } if(pt->cTypeCounter) { rt_printf_time("bluetooth_recv_rst:state=%d,counter=%d,num=%d\r\n",pt->cTypeCounter,pt->cRecvCnt,num); } pt->cTypeCounter=0; pt->cRecvLenth=0; pt->cRecvCnt=0; pt->us0_recv = 0; } /** * @brief 蓝牙接收数据解析 * @details 判断是否接收到完整一帧 * @param _pt 结构体指针 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks none */ static int _recv_parse(BLUETOOTH_DEF *pt, u8 c) { u8 i = 0; u8 match_count = 0; switch(pt->cTypeCounter) { case 0: if (c == '+') //固定起始符号 { pt->cmd_type = -1; pt->cTypeCounter++; pt->us0_recv = bsp_ustimer_get_origin(); memset(pt->cmd_recvbuf,'\0',sizeof(pt->cmd_recvbuf)); } else { _recv_rst(pt,1); } break; case 1: pt->cmd_recvbuf[pt->cRecvCnt++] = c; if(pt->cRecvCnt >= CMD_RECVBUF_LEN) { _recv_rst(pt,2); rt_printf_time("接收指令错误,指令长度溢出!!!\r\n"); break; } // 最短命令匹配字符MAC if(pt->cRecvCnt < 3) { break; } // 命令未匹配 if(pt->cmd_type == -1) { for(i = 0; i < AT_CMD_MAX; i++) { // 匹配命令 if(strstr(at_cmd_index_match[i].cmd_str,pt->cmd_recvbuf) != NULL) { match_count++; pt->cmd_type = at_cmd_index_match[i].cmd; break; } } // 3个字符都未能匹配一条,不支持命令,重新接收 if(match_count == 0) { rt_printf("蓝牙接收->不支持的指令:%s\r\n",pt->cmd_recvbuf); pt->cmd_type = -1; _recv_rst(pt,3); break; } else if(match_count > 1) { // 多条匹配继续接收匹配 pt->cmd_type = -1; } } else { if(strstr(pt->cmd_recvbuf,at_cmd_index_match[pt->cmd_type].cmd_end_str) != NULL) { #ifdef BL_DEBUG pt->cmd_recvbuf[pt->cRecvCnt - 1] = '\0'; rt_printf("recv cmd:%s\r\n",pt->cmd_recvbuf); #endif // 命令结束,转入下一流程 pt->cRecvCnt = 0; pt->cTypeCounter++; memset(pt->recvbuf,0,sizeof(pt->recvbuf)); _ack_one_buf(&pt->tx_buf[0], pt->cmd_type); } } break; case 2: if(at_cmd_index_match[pt->cmd_type].data_end_str) { // 此帧包含数据 pt->recvbuf[pt->cRecvCnt++] = c; if(pt->cRecvCnt >= BLUETOOTH_BUF_LEN) { _recv_rst(pt,4); rt_printf("蓝牙接收->数据长度溢出!!!\r\n"); break; } if(c == '\n') { 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) { #ifdef BL_DEBUG int i = 0; rt_printf("recv data:\r\n"); for(i = 0; i <= pt->cRecvCnt-1; i++) { if(i%16 == 0 && i != 0) rt_printf("\r\n"); rt_printf("%02x ", pt->recvbuf[i]); } rt_printf("\r\n"); #endif if(at_cmd_index_match[pt->cmd_type].sta_end_str) { pt->cRecvCnt = 0; pt->cTypeCounter++; } else { pt->bData = true; pt->cTypeCounter = 0; _recv_rst(pt,5); } } } } else if(at_cmd_index_match[pt->cmd_type].sta_end_str) { // 结果判断 pt->cTypeCounter++; pt->cmd_recvbuf[pt->cRecvCnt++] = c; } else { _recv_rst(pt,6); rt_printf("%s %d unknowd operation!\r\n", __func__, __LINE__); } break; case 3: // 结果 pt->cmd_recvbuf[pt->cRecvCnt++] = c; if(c == '\n') { #ifdef BL_DEBUG rt_printf("recv statue:%s", pt->cmd_recvbuf); #endif if(strstr(pt->cmd_recvbuf,"OK\r\n") != NULL) { pt->cmd_sta = true; if(at_cmd_index_match[pt->cmd_type].data_end_str) { pt->bData = true; } } else { rt_printf("蓝牙->执行%s->%s失败!!\r\n", at_cmd_index_match[pt->cmd_type].cmd_str, pt->cmd_recvbuf); } pt->cTypeCounter = 0; _recv_rst(pt,7); } break; default: _recv_rst(pt,8); break; } return 0; } /** * @brief 接收应用 * @details 从fifo提取数据去解析 * @param _pt 结构体指针 * @return none * @author EWen * @date 2025-10-11 * @remarks none */ static void _recv_app(BLUETOOTH_DEF *pt) { u8 c; // 接收数据 while(pt->bData == false) { if(rt_fifo_get(&pt->recv_fifo,&c,1) == 0) { if(pt->b_recv_reset) { _recv_rst(pt,10); pt->b_recv_reset = 0; } break; } _recv_parse(pt,c); } } /** * @brief 蓝牙接收数据解析 * @details 数据接收判断时已将"+DATA="去除 * @param _pt 结构体指针 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks 数据内容格式:+DATA=para1,para2,para3; para1:固定值0,para2:接收的数据长度,para3:接收的数据内容 */ static int _data_parse(BLUETOOTH_DEF *pt) { u16 i = 0; u8 *pd = NULL; char *endptr; u16 data_len = 0; u8 len_str[5] = {0}; // 固定开头为 "0," if(pt->recvbuf[0] != '0' || pt->recvbuf[1] != ',') { rt_printf("%s data format error!\r\n", __func__); return -1; } // 解析长度字符串 pd = &pt->recvbuf[2]; for(i = 0; i < 5; i++) { len_str[i] = *pd++; // 长度字符串以","结束,跳过"," if(*pd == ',') { pd++; break; } } if(i == 5) { rt_printf("%s lenth error!\r\n", __func__); return -2; } else { data_len = strtol(len_str,&endptr,10); if(*endptr != '\0') { rt_printf("%s lenth strtol failed!\r\n", __func__); return -3; } #ifdef BL_DEBUG rt_printf("%s data_len:%d\r\n", __func__, data_len); #endif } for(i = 0; i < data_len; i++) { u8 j; int ret; ret = sec_recv(&pt->rx_buf,*pd++,pt->arrSendBuf,false); if(ret==SEC_FRAME_OK_APP) // 带规约的报文 { rt_printf("未实现的蓝牙通讯帧处理->SEC_FRAME_OK_APP\r\n"); } else if(ret==SEC_FRAME_OK_EXT) //纯安全扩展报文 发送 { u16 remaining_length = 0; // 前两个字节为加密返回报文的长度 remaining_length = ((pt->arrSendBuf[0]<<8)+(pt->arrSendBuf[1])); #ifdef BL_DEBUG rt_printf("esam data len->%d\r\n", remaining_length); #endif // 分帧 // TODO 直接将报文分帧有较大几率证书管理工具会报错,此处已在加密报文处理中将每帧证书长度修改为220处理 // 可以在一帧报文中将加密安全扩展报文发送,如确实需分帧的话要按照加密报文分帧处理再分帧,此处没有处理。。。 if(remaining_length > FREAM_SPLIT_LEN) { for(j = 0;;j++) { if(remaining_length <= FREAM_SPLIT_LEN) { _frame_packing(pt,pt->arrSendBuf+2+j*FREAM_SPLIT_LEN,AT_CMD_LESEND,(u8)remaining_length); break; } _frame_packing(pt,pt->arrSendBuf+2+j*FREAM_SPLIT_LEN,AT_CMD_LESEND,FREAM_SPLIT_LEN); remaining_length -= FREAM_SPLIT_LEN; } } else { _frame_packing(pt,pt->arrSendBuf+2,AT_CMD_LESEND,(u8)remaining_length); } } } return 0; } /** * @brief 蓝牙连接状态解析 * @details none * @param _pt 结构体指针 * @return 0:成功 其它:失败 * @author EWen * @date 2025-10-11 * @remarks 数据格式0,0 1 2 */ static int _status_parse(BLUETOOTH_DEF *pt) { // 固定开头为 "0," if(pt->recvbuf[0] != '0' || pt->recvbuf[1] != ',') { rt_printf("%s data format error!\r\n", __func__); return -1; } if(pt->recvbuf[2] == '1') { // 连接断开 pt->lnk_sta = false; rt_printf("蓝牙连接断开!\r\n"); pt->us0_disc_reboot = bsp_ustimer_get_origin(); } else if(pt->recvbuf[2] == '2') { // 正在连接 rt_printf("蓝牙连接中...\r\n"); } else if(pt->recvbuf[2] == '3') { // 已连接 pt->lnk_sta = true; rt_printf("蓝牙已连接!\r\n"); } else { // 未知的连接状态 rt_printf_time("蓝牙连接状态解析错误,未知的状态%d%d%d!\r\n",pt->recvbuf[0],pt->recvbuf[1],pt->recvbuf[2]); return -2; } return 0; } /** * @brief 蓝牙名称设置解析 * @details 解析名称设置结果 * @param _pt 结构体指针 * @return none * @author EWen * @date 2025-10-11 * @remarks none */ static void _name_set_parse(BLUETOOTH_DEF *pt) { rt_printf("设置蓝牙名称:%s%s\r\n", pt->recvbuf, pt->cmd_sta ? "成功!" : "失败!"); } /** * @brief 蓝牙数据初始化 * @details none * @param _pt 结构体指针 * @param chnl 通道 * @return 0: 成功 其它: 失败 * @author EWen * @date 2025-10-11 * @remarks none */ int bluetooth_init(BLUETOOTH_DEF *pt, u8 chnl) { u8 name_buf[30] = {0}; RMT_FIXED_TABLE tfixedset; memset(pt,0,sizeof(BLUETOOTH_DEF)); memset(&tfixedset,0,sizeof(tfixedset)); tfixedset.num = RMT_FIXED_SET_NUM; tfixedset.set[0].type = FIXED_SET_ID; iec_get_fixedset_csv(&tfixedset); // 初始化接收buf结构 pt->chnl = chnl; pt->rx_buf.chn = pt->chnl; pt->rx_buf.buf = pt->esambuf; rt_fifo_init(&pt->recv_fifo,pt->recv_fifo_buf,BLUETOOTH_BUF_LEN); if(tfixedset.set[0].len == 24) { /* ID 标准定义24位 */ rt_printf("设置蓝牙名称:%s\r\n", tfixedset.set[0].str); memcpy(name_buf,tfixedset.set[0].str,tfixedset.set[0].len); } else { strcpy(name_buf,BLUETOOTH_DEFAULT_NAME); rt_printf("蓝牙: 未能从fixset.csv中获取到正确ID,使用默认名称:%s.\r\n", BLUETOOTH_DEFAULT_NAME); } _name_set(pt,name_buf,strlen(name_buf)); _reboot(pt); return 0; } /** * @brief 蓝牙数据接收 * @details 将数据存入fifo中 * @param _pt 结构体指针 * @param _byte 数据 * @return none * @author EWen * @date 2025-10-11 * @remarks none */ void bluetooth_recv(BLUETOOTH_DEF *pt, u8 _byte) { rt_fifo_put(&pt->recv_fifo,&_byte,1); } /** * @brief 发送检查 * @details none * @param _pt 结构体指针 * @return none * @author EWen * @date 2025-10-11 * @remarks 帧间隔延时精度受扫描间隔影响,实际测试到1000ms间隔发送也没什么问题 */ static void _send_polling(BLUETOOTH_DEF *_pt) { u8 *buf; u16 i = 0; u16 len = 0; u8 *pd,tb_send; bl_tbuf_t *pbuf; pbuf = &_pt->tx_buf[0]; #if BL_ENABLE_RESEND_MODE // 上一帧未收到回复 if(pbuf->tb_tail_send != pbuf->tb_tail_ack) { // 未超时不发下一帧 if(bsp_ustimer_get_duration(_pt->us0_cfmtimeout) < USTIMER_MS*BL_TIMEOUT_RESEND_MS) { // tb_tail_send != tb_tail_ack,说明已进行过报文发送即更新过_pt->us0_cfmtimeout // 所以此处直接判断延时是否超时也没有问题 return; } else { // 重发次数到达不再重发 if(_pt->resend_cnt >= BL_RESEND_TIMES) { _pt->resend_cnt = 0; memset(_pt->tx_buf,0,sizeof(_pt->tx_buf)); return; } // 超时重发 pbuf->tb_tail_send--; // 发送尾索引回上一帧的位置进行重发 _pt->resend_cnt++; 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]); for(i = 0; i < pbuf->tb_data[pbuf->tb_tail_send][0]; i++) { if(i!=0 && i%16==0) rt_printf("\r\n"); rt_printf("%02x ",pbuf->tb_data[pbuf->tb_tail_send][i+1]); } rt_printf("\r\n"); } } #endif // 如果串口忙或者帧间隔时间未到,不能发送数据 if(g_tRsComm[_pt->chnl].bextsend || bsp_ustimer_get_duration(_pt->us0_sendpiece) < USTIMER_MS*FREAM_INTERVAL_TIME_MS) { return; } if(pbuf->tb_head == pbuf->tb_tail_send) { return; } // 更新发送尾指针,保留老指针备用。 tb_send = pbuf->tb_tail_send; pbuf->tb_tail_send++; if(pbuf->tb_tail_send >= BL_TBUF_NUM) { pbuf->tb_tail_send = 0; } #ifdef BL_DEBUG 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); #endif //将数据复制到真正发送的buf len = pbuf->tb_data[tb_send][0]; pd = g_tRsComm[_pt->chnl].extsendbuf; memcpy(pd,&pbuf->tb_data[tb_send][1],len); g_tRsComm[_pt->chnl].extsendcnt=0; g_tRsComm[_pt->chnl].extsendlen=len; g_tRsComm[_pt->chnl].bextsend=true; #ifdef BL_DEBUG { rt_printf_time("bluetooth send data:%d\r\n",len); for(i = 0; i chnl].extsendbuf[i]); } rt_printf("\r\n"); } #endif _pt->us0_cfmtimeout=_pt->us0_sendpiece=bsp_ustimer_get_origin(); } /** * @brief 蓝牙应用巡检 * @details none * @param _pt 结构体指针 * @return 0:成功 其它:失败 * @author EWen * @date 2025-10-11 * @remarks none */ int bluetooth_app(BLUETOOTH_DEF *pt) { _recv_app(pt); if(pt->bData) { switch (pt->cmd_type) { case AT_CMD_DATA: _data_parse(pt); break; case AT_CMD_STAT: _status_parse(pt); break; case AT_CMD_NAME: _name_set_parse(pt); break; default: rt_printf("%s 未支持的指令类型->%d\r\n", __func__, pt->cmd_type); break; } pt->bData = false; } _send_polling(pt); return 0; } /** * @brief 蓝牙定时器 * @details 处理一些定时任务 * @param _pt 结构体指针 * @return none * @author EWen * @date 2025-10-11 * @remarks 延时精度受扫描间隔影响,但实际在此处理的操作实时性要求不高,因此没有关系 */ void bluetooth_timer(BLUETOOTH_DEF *pt) { if(pt->us0_disc_reboot) { if(bsp_ustimer_get_duration(pt->us0_disc_reboot) >= BL_DISC_REBOOT_TIME_MS*USTIMER_MS) { _reboot(pt); pt->us0_disc_reboot = 0; } } if(pt->lnk_sta) { pt->us0_idle_reboot = 0; } else { if(pt->us0_idle_reboot == 0) { pt->us0_idle_reboot = bsp_ustimer_get_origin(); } else { if(bsp_ustimer_get_duration(pt->us0_idle_reboot) >= BL_IDLE_REBOOT_TIME_MS*USTIMER_MS) { _reboot(pt); pt->us0_idle_reboot = 0; } } } if(pt->us0_recv) { if(bsp_ustimer_get_duration(pt->us0_recv) >= BL_RECV_TIMEOUT_MS*USTIMER_MS) { pt->us0_recv = 0; pt->b_recv_reset = true; } } }