This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] LP-EM-CC2340R5:如何快速有效地扫描外设?

Guru**** 2587365 points
Other Parts Discussed in Thread: LP-EM-CC2340R5, CC2340R5

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1395450/lp-em-cc2340r5-how-to-quickly-and-effectively-scan-for-peripherals

器件型号:LP-EM-CC2340R5
主题中讨论的其他器件: CC2340R5

工具与软件:

您好!

我有两个 LP-EM-CC2340R5器件、一个用作外设、另一个用作中央器件。 外设每4秒广播一次以节省电力。 应如何配置中央设备以更有效地扫描外设?

            外设设置图




            中央设置图

              中央 代码1-1  

/*=============================================
          AT command start scan.
=============================================*/
void start_scan(char *pdata)
{
    bStatus_t status;
    const BLEAppUtil_ScanStart_t centralScanStartParams =
    {
         /*! Zero for continuously scanning */
         .scanPeriod     = DEFAULT_SCAN_PERIOD, /* Units of 1.28sec */

         /*! Scan Duration shall be greater than to scan interval,*/
         /*! Zero continuously scanning. */
         .scanDuration   = DEFAULT_SCAN_DURATION, /* Units of 10ms */

         /*! If non-zero, the list of advertising reports will be */
         /*! generated and come with @ref GAP_EVT_SCAN_DISABLED.  */
         .maxNumReport   = APP_MAX_NUM_OF_ADV_REPORTS
    };

    status = BLEAppUtil_scanStart(&centralScanStartParams);

    if(status == FAILURE)
    {
        while(1){}
    }
}



      中央 代码1-2 (BLEAPPUTIL_ADV_REPORT)

void Central_ScanEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
{

    uint8 pint_rssi_buf[5] = {0};


    BLEAppUtil_ScanEventData_t *scanMsg = (BLEAppUtil_ScanEventData_t *)pMsgData;
//    bleStk_GapScan_Evt_AdvRpt_t *pScanRpt = NULL;


    switch (event)
    {
        case BLEAPPUTIL_SCAN_ENABLED:
        {
            centralScanIndex = 0;
            MenuModule_printf(APP_MENU_SCAN_EVENT, 0, "Scan status: Scan started...");

            break;
        }

        case BLEAPPUTIL_SCAN_DISABLED:
        {
            uint8 i;

            for(i = 0; i < APP_MAX_NUM_OF_ADV_REPORTS; i++)
            {
                memset(&centralScanRes[i], 0, sizeof(App_scanResults));
            }

            // Go over the advertise reports that was saved in the host level and save it
            for (i = 0; i < scanMsg->pBuf->pScanDis.numReport; i++)
            {
              GapScan_Evt_AdvRpt_t advReport;
              // Get the address from the report
              GapScan_getAdvReport(i, &advReport);

              // Add the report to the scan list
              Central_addScanRes(&advReport);


            }


            UART2_write(uart, (const char *)"OK\r\n", strlen((const char *)"OK\r\n"), NULL);

            MenuModule_printf(APP_MENU_SCAN_EVENT, 0, "Scan status: Scan disabled - "
                              "Reason: " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET
                              "Num results: " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                              scanMsg->pBuf->pScanDis.reason,
                              scanMsg->pBuf->pScanDis.numReport);
            break;
        }
        case BLEAPPUTIL_ADV_REPORT:

            pScanRpt = &scanMsg->pBuf->pAdvReport;

            //Display device name,support 20 byte(max)
            if (pScanRpt->pData != NULL)
            {
                uint8_t indx = 0;

                if(pScanRpt->dataLen > 0)
                {
                    SimpleCentral_findDeviceName(pScanRpt->pData, pScanRpt->dataLen, deviceName, MAX_SIZE);
                }
                //Determine the first byte
                if( (deviceName[0] != '\0') && (deviceName[0] <= '~') )  //if( (deviceName[0] != '\0') && (deviceName[0] >= ' ') && (deviceName[0] <= '~') )
                {
                    deviceName[MAX_SIZE-1] = '\0';
                    //RSSI
                    sprintf((char *)pint_rssi_buf, "%d",pScanRpt->rssi);

                    //print Mac address.
                    UART2_write(uart, (const char*)BLEAppUtil_convertBdAddr2Str(pScanRpt->addr),strlen((const char*)BLEAppUtil_convertBdAddr2Str(pScanRpt->addr)) , NULL);
                    UART2_write(uart, (const char *)"; ", strlen((const char *)"; "), NULL);
                    //print Device name
                    UART2_write(uart, (const char *)deviceName, strlen((const char *)deviceName), NULL);
                    UART2_write(uart, (const char *)"; ", strlen((const char *)"; "), NULL);
                    //print RSSI
                    UART2_write(uart, (const char *)pint_rssi_buf, strlen((const char *)pint_rssi_buf), NULL);

                    UART2_write(uart, (const char *)"\r\n", strlen((const char *)"\r\n"), NULL);
                }

             }

        break;

        default:
        {
            break;
        }

    }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anthony、您好!

    感谢您的咨询。

    考虑到扫描和广播之间未同步、缩短扫描间隔将降低扫描器找到广播器的几率。 我建议通过修改观测器配置内的"扫描周期"进行测试。 此参数用于跳过扫描事件"一段时间"(以秒为单位)。 因此、您可以首先增加周期并测量扫描器找到外围设备所需的平均时间。

    为了验证周期是否生效、您可以跟踪射频输出、如此处所述: 调试射频输出。

    BR、

    David。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:

    感谢您的建议。 测试完成后、我将与大家分享结果。

    此致、
    Anthony

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:

    我发现如果外设广播时间设置得太长、即使中心设备找到外设、也无法连接。 但是、如果外设广播时间设置得较短、则不会发生该问题。 您能提供一些相关指导吗? 我使用 basic_ble_LP_EM_CC2340R5_freertos_ticlang 进行修改。

    void Central_ScanEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
    
        uint8 pint_rssi_buf[5] = {0};
    
    
        BLEAppUtil_ScanEventData_t *scanMsg = (BLEAppUtil_ScanEventData_t *)pMsgData;
    //    bleStk_GapScan_Evt_AdvRpt_t *pScanRpt = NULL;
    
    
        switch (event)
        {
            case BLEAPPUTIL_SCAN_ENABLED:
            {
                centralScanIndex = 0;
                UART2_write(uart, (const char *)"Scan status: Scan started...\r\n", strlen((const char *)"Scan status: Scan started...\r\n"), NULL);
                MenuModule_printf(APP_MENU_SCAN_EVENT, 0, "Scan status: Scan started...");
    
                break;
            }
    
            case BLEAPPUTIL_SCAN_DISABLED:
            {
                uint8 i;
    
                for(i = 0; i < APP_MAX_NUM_OF_ADV_REPORTS; i++)
                {
                    memset(&centralScanRes[i], 0, sizeof(App_scanResults));
                }
    
                // Go over the advertise reports that was saved in the host level and save it
                for (i = 0; i < scanMsg->pBuf->pScanDis.numReport; i++)
                {
                  GapScan_Evt_AdvRpt_t advReport;
                  // Get the address from the report
                  GapScan_getAdvReport(i, &advReport);
    
                  // Add the report to the scan list
                  Central_addScanRes(&advReport);
    
    
                }
    
    
                UART2_write(uart, (const char *)"OK\r\n", strlen((const char *)"OK\r\n"), NULL);
    
                MenuModule_printf(APP_MENU_SCAN_EVENT, 0, "Scan status: Scan disabled - "
                                  "Reason: " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET
                                  "Num results: " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                                  scanMsg->pBuf->pScanDis.reason,
                                  scanMsg->pBuf->pScanDis.numReport);
                break;
            }
            case BLEAPPUTIL_ADV_REPORT:
    
    
    
                pScanRpt = &scanMsg->pBuf->pAdvReport;
    
                //Display device name,support 20 byte(max)
                if (pScanRpt->pData != NULL)
                {
                    uint8_t indx = 0;
    
                    if(pScanRpt->dataLen > 0)
                    {
                        SimpleCentral_findDeviceName(pScanRpt->pData, pScanRpt->dataLen, deviceName, MAX_SIZE);
                    }
                    //Determine the first byte
                    if( (deviceName[0] != '\0') && (deviceName[0] >= ' ') && (deviceName[0] <= '~') ) //if( (deviceName[0] != '\0') && (deviceName[0] <= '~') )
                    {
                        deviceName[MAX_SIZE-1] = '\0';
                        //RSSI
                        sprintf((char *)pint_rssi_buf, "%d",pScanRpt->rssi);
    
                        //print Mac address.
                        UART2_write(uart, (const char*)BLEAppUtil_convertBdAddr2Str(pScanRpt->addr),strlen((const char*)BLEAppUtil_convertBdAddr2Str(pScanRpt->addr)) , NULL);
                        UART2_write(uart, (const char *)"; ", strlen((const char *)"; "), NULL);
                        //print Device name
                        UART2_write(uart, (const char *)deviceName, strlen((const char *)deviceName), NULL);
                        UART2_write(uart, (const char *)"; ", strlen((const char *)"; "), NULL);
                        //print RSSI
                        UART2_write(uart, (const char *)pint_rssi_buf, strlen((const char *)pint_rssi_buf), NULL);
    
                        UART2_write(uart, (const char *)"\r\n", strlen((const char *)"\r\n"), NULL);
                    }
    
                 }
    
            break;
    
            default:
            {
                break;
            }
    
        }
    }

    此致、
    Anthony

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anthony、您好!

    感谢您的反馈。 您能否分享一下如何配置广播和扫描? 广播间隔和扫描间隔、窗口和持续时间是多少?

    什么意思是中央设备可以找到外设但无法连接? 您是否可以在要连接的设备列表中看到该设备、但在启动连接时会发生什么情况?

    BR、

    David。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:

    当我执行 AT 命令以开始扫描时、它会扫描外围器件。 我的期望是、即使扫描目标器件需要很长时间、Central 也应该能够连接至外设。 不幸的是、在 Central_Scan BLEAPPUTIL_SCAN_DISABLED 处理程序中、BLEAPPUTIL_ADV_REPORT 中找到的外设地址似乎没有正确地放置到 BLEAPPUTIL_SCAN_DISABLED 中。 这是我感到困惑的地方。 尝试连接后、会在连接 AT 命令中显示该消息  

    在 BLEAPPUTIL_ADV_REPORT 中找到目标外设的地址、但停止扫描后、无法在 BLEAPPUTIL_SCAN_DISABLED 中找到目标外设的地址。
     


    提取 connect at 命令的代码片段。


    if (search_res == 0)
    UART2_WRITE (UART、(const char*)"未找到\r\nFAIL\r\n"、strlen ("未找到\r\nFAIL\r\n")、NULL);






    中央 syscfg


     命令时中央启动扫描  

    /*=============================================
              AT command start scan.
    =============================================*/
    void start_scan(char *pdata)
    {
        bStatus_t status;
        const BLEAppUtil_ScanStart_t centralScanStartParams =
        {
             /*! Zero for continuously scanning */
             .scanPeriod     = (uint16_t)DEFAULT_SCAN_PERIOD, /* Units of 1.28sec */
    
             /*! Scan Duration shall be greater than to scan interval,*/
             /*! Zero continuously scanning. */
             .scanDuration   = DEFAULT_SCAN_DURATION, /* Units of 10ms */
    
             /*! If non-zero, the list of advertising reports will be */
             /*! generated and come with @ref GAP_EVT_SCAN_DISABLED.  */
             .maxNumReport   = APP_MAX_NUM_OF_ADV_REPORTS
        };
    
        status = BLEAppUtil_scanStart(&centralScanStartParams);
    
        if(status == FAILURE)
        {
            while(1){}
        }
    }

    连接 AT 命令   

    /*=============================================
         AT command connect to peripheral.
    =============================================*/
    void connect_dev(char *pdata)
    {
        //Pair to device address.
        uint8_t pair_addr[15] = {0};
    
        for(uint8_t i = 0; i < 14; i++)
        {
            pair_addr[i] = pdata[10+i];
        }
    
        //============================================
        bStatus_t status;
    
        uint8_t search_res = 0;
        // Get the scan results list
        App_scanResults *appScanRes;
        uint8 size = Scan_getScanResList(&appScanRes);
    
    
        // Set the connection parameters
        BLEAppUtil_ConnectParams_t connParams =
        {
         //.peerAddrType = appScanRes->addressType,//PEER_ADDRTYPE_PUBLIC_OR_PUBLIC_ID,
         .phys = INIT_PHY_1M,
         .timeout = 10000 //1000
        };
    
    
        search_res = 0;
    
        for(uint8_t i = 0; i < size; i++)
        {
            // Convert the addresses to strings
            if(strcmp((const char *)pair_addr,(const char *)BLEAppUtil_convertBdAddr2Str(appScanRes[i].address) ) == 0)  //"0x8472933C57E4"
            {
                search_res = 1;
    //            //connect to peripheral public address.
    //            Public_dev_addr[0] = 0xE4;
    //            Public_dev_addr[1] = 0x57;
    //            Public_dev_addr[2] = 0x3C;
    //            Public_dev_addr[3] = 0x93;
    //            Public_dev_addr[4] = 0x72;
    //            Public_dev_addr[5] = 0x84;
    //
    //          // Copy the selected address
                connParams.peerAddrType = appScanRes[i].addressType;
                memcpy(connParams.pPeerAddress, appScanRes[i].address, B_ADDR_LEN);
    
                // Connect parameter.
                status = BLEAppUtil_connect(&connParams);
    
    
                if (status != SUCCESS)
                {
                    UART2_write(uart, (const char*)"Connect\r\nfail\r\n",strlen("Connect\r\nfail\r\n") , NULL);
                }
                else
                {
                    UART2_write(uart, (const char*)"Address:",strlen("Address:") , NULL);
                    UART2_write(uart, (const char*)BLEAppUtil_convertBdAddr2Str(connParams.pPeerAddress),strlen((const char*)BLEAppUtil_convertBdAddr2Str(connParams.pPeerAddress)) , NULL);
                    UART2_write(uart, (const char*)"\r\nOK\r\n",strlen("\r\nOK\r\n") , NULL);
                }
    
                break;
            }
        }
    
        //no found
        if(search_res == 0)
            UART2_write(uart, (const char*)"no found\r\nfail\r\n",strlen("no found\r\nfail\r\n") , NULL);
    
    }

    外设 syscfg

    此致、
    Anthony

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anthony、您好!

    您如何确认器件实际已连接? 我想问一下、如果您订阅 BLEAPPUTIL_ADV_REPORT 事件、您是否在广告报告中找到了要查找的地址。 根据我的理解您确实发现了它、您在报告中找到广播地址后是否尝试过立即执行扫描禁用? 我之所以提出这个问题、是因为我不确定您是否实际执行了 AT 命令来禁用扫描。

    BR、

    David。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:

    我理解您的观点。 我只能使用 BLEAPPUTIL_ADV_REPORT 事件通知我是否存在任何可连接的外设地址。 是否可以成功连接取决于 BLEAppUtil_connect (&connParams)返回的状态。 我在之前的回复中提到了连接 AT 命令相关代码。 但在当前的应用中、我有两个以上的外设、每4秒广播一次。 当中央设备开始扫描10秒后停止时、我可能在此期间检测到一个或两个外设。 扫描结束后、希望 Central 可以随时连接到检测到的外设。 这可行吗?

    此致、
    Anthony

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anthony、您好!

    我可以看到、如果有两个以上的外设在4秒的间隔内进行广播、则涉及外设广播的通道的可能性非常低。 您可以:1)增加广播间隔或2)增加扫描窗口和间隔(300毫秒)以提高获得这些广告报告的可能性。

    BR、

    David。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:

    感谢您的答复。 我可能需要评估和调整此架构、因为每4秒广播一次会为我们生成非常好的功耗数据、但很难找到外设并与此类设置建立连接。 这让我陷入困境...

    此致、
    Anthony

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anthony、您好!

    是否可以选择增加扫描窗口和间隔? 值得一试、看看对中央器件功耗的影响。

    BR、

    David。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:


    您的建议非常有帮助。 每320ms 连续扫描一次、扫描窗口和间隔参数设置为300ms、可在大约15至40秒内实现检测。 有时它可能会超过这个时间范围、但至少是一个很好的开始。 我将相应地修改代码、如果有任何进一步的更新、我将在此处发布消息。

    此致、
    Anthony

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Anthony、您好!

    很高兴听到有关进度的消息。 请考虑、扫描窗口/间隔值将取决于您希望有效发现的外设数量(如果其 Adv 间隔不够频繁、在您的情况下出于节能原因)。

    BR、

    David。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 David:


    根据您的建议调整参数,并使用自定义的用户界面,实际效果很好。

    此致、
    Anthony