美文网首页物联网loT从业者物联网相关技术研究
CC2640R2F学习笔记(10)——GAP主机端连接

CC2640R2F学习笔记(10)——GAP主机端连接

作者: Leung_ManWah | 来源:发表于2019-03-27 10:06 被阅读12次

    一、背景

    链路层(LL)控制设备的射频状态,有五个设备状态:待机、广播、扫描、初始化和连接。

    广播 为广播数据包,而 扫描 则是监听广播。

    GAP通信中角色,中心设备(Central - 主机)用来扫描和连接 外围设备(Peripheral - 从机)

    二、配置连接参数

    2.1 连接参数相关宏

    #define DEFAULT_CONN_INT                      200
    #define DEFAULT_CONN_TIMEOUT                  1000
    #define DEFAULT_CONN_LATENCY                  0
    
    // 连接时是否启动高速扫描,避免从机广播间隔长,导致主机连接很慢
    #define DEFAULT_LINK_HIGH_DUTY_CYCLE          FALSE
    

    2.2 配置GAP参数值

    以SDK2.4 multi_role工程为例,在 multi_role_init() 初始化多角色应用程序函数中,

    /*===================================== 主机 =====================================*/
    /*------------------- 扫描参数 -------------------*/
    // 扫描处理周期,周期越短,处理次数越多
    GAP_SetParamValue(TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION);
    
    // 连接间隔
    GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, DEFAULT_CONN_INT);
    GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_CONN_INT);
    GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONN_TIMEOUT);
    GAP_SetParamValue(TGAP_CONN_EST_LATENCY, DEFAULT_CONN_LATENCY);
    

    2.3 配置GAP角色规范(Role Profile)

    以SDK2.4 multi_role工程为例,在 multi_role_init() 初始化多角色应用程序函数中,

     /*===================================== 主机 =====================================*/
    /*------------------- 连接参数 -------------------*/
    // 设置可连接设备数
    VOID GAPRole_StartDevice(&multi_role_gapRoleCBs, &maxNumBleConns);
    
    // 为连接句柄表分配内存
    if(connHandleMap = ICall_malloc(sizeof(connHandleMapEntry_t) *maxNumBleConns))
    {
        // 初始化连接句柄表的索引
        for(uint8_t i = 0; i < maxNumBleConns; i++)             
        {
            connHandleMap[i].connHandle = INVALID_CONNHANDLE;
        }
    }
    
    // 为特征句柄表分配内存
    if(discInfo = ICall_malloc(sizeof(discInfo_t) *maxNumBleConns))
    {
        // 初始化特征句柄表的索引
        for(uint8_t i = 0; i < maxNumBleConns; i++)                      
        {
            discInfo[i].charHdl = 0;
            discInfo[i].discState = BLE_DISC_STATE_IDLE;
            discInfo[i].svcEndHdl = 0;
            discInfo[i].svcStartHdl = 0;
        }
    }
    

    三、连接相关函数

    3.1 正在连接标志

    以SDK2.4 multi_role工程为例,multi_role.c中局部变量

    static uint8_t connecting = FALSE;
    

    3.2 执行连接函数

    /**
     @brief 执行连接函数
     @param index 索引
     @return TRUE - 成功;FALSE - 失败
    */
    bool mr_doConnect(uint8_t index)
    {
        if(connecting == TRUE)                                              // 如果正在连接,则取消
        {
            GAPRole_TerminateConnection(GAP_CONNHANDLE_INIT);               // 终止连接
    
            connecting = FALSE;                                             // 清除连接标志
            return FALSE;
        }
        else                                                                // 尝试连接
        {
            GAPRole_EstablishLink(DEFAULT_LINK_HIGH_DUTY_CYCLE,             // 连接当前设备
                                  DEFAULT_LINK_WHITE_LIST,
                                  devList[index].addrType,
                                  devList[index].addr);
    
            connecting = TRUE;                                              // 连接标志置一
            return TRUE;
        }
    }
    

    3.3 执行断连函数

    /**
     @brief 执行断开连接函数
     @param index 索引
     @return TRUE - 成功;FALSE - 失败
    */
    bool mr_doDisconnect(uint8_t index)
    {
        GAPRole_TerminateConnection(connHandleMap[index].connHandle);       // 与当前设备终止连接
    
        return TRUE;
    }
    

    四、连接相关事件

    在执行完连接函数或者断连函数后,会产生相应的事件。

    以SDK2.4 multi_role工程为例,在 multi_role_processRoleEvent() 处理多角色事件函数中,

    4.1 建立连接完成事件

    switch(pEvent->gap.opcode)
    {
        /*===================================== 建立链接事件 =====================================*/
        case GAP_LINK_ESTABLISHED_EVENT:
        {
    
            if(pEvent->gap.hdr.status == SUCCESS)                           // 如果建立链接成功
            {
                connecting = FALSE;                                         // 清除正在连接标志
    
                // Add index-to-connHandle mapping entry and update menus
                uint8_t index = multi_role_addMappingEntry(pEvent->linkCmpl.connectionHandle,
                                                           pEvent->linkCmpl.devAddr);
    
                if(linkDB_NumActive() >= maxNumBleConns)                    // 如果没有活跃链接,则关闭广播
                {
                    uint8_t advertEnabled = FALSE;
                    GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                                         &advertEnabled, NULL);
                }
    
                // 开始发现服务
                multi_role_startDiscovery(pEvent->linkCmpl.connectionHandle);
    
                // Start periodic clock if this is the first connection
                if(linkDB_NumActive() == 1)
                {
                    Util_startClock(&periodicClock);
                }
            }
            else                                                            // 如果建立链接失败
            {
                /* Display_print0(dispHandle, MR_ROW_STATUS1, 0, "Connect Failed"); */
                /* Display_print1(dispHandle, MR_ROW_STATUS2, 0, "Reason: %d", pEvent->gap.hdr.status); */
            }
        }
        break;
    }
    

    4.2 终止连接事件

    switch(pEvent->gap.opcode)
    {
     /*===================================== 中断链接事件 =====================================*/
        case GAP_LINK_TERMINATED_EVENT:
        {
    
            // 获取当前活跃连接设备数
            uint8_t currentNumActive = linkDB_NumActive();
    
            // 从连接句柄表中查找索引
            connIndex = multi_role_mapConnHandleToIndex(pEvent->linkTerminate.connectionHandle);
    
            // Check to prevent buffer overrun
            if(connIndex < maxNumBleConns)
            {
                // 重置连接设备信息
                connHandleMap[connIndex].connHandle = INVALID_CONNHANDLE;
    
                discInfo[connIndex].discState = BLE_DISC_STATE_IDLE;
                discInfo[connIndex].charHdl = 0;
    
                // If there aren't any active connections
                if(currentNumActive == 0)
                {
                    // 停止周期定时器
                    Util_stopClock(&periodicClock);
                }
    
                // If it is possible to advertise again
                /*
                if(currentNumActive == (maxNumBleConns-1))
                {
                    Display_print0(dispHandle, MR_ROW_ADV, 0, "Ready to Advertise");
                    Display_print0(dispHandle, MR_ROW_STATUS2, 0, "Ready to Scan");
                }
                */
            }
        }
        break;
    }
    

    • 由 Leung 写于 2019 年 3 月 27 日

    • 参考:simplelink_cc2640r2_sdk_2_40_00_32 [提取码:3pg6]

    相关文章

      网友评论

        本文标题:CC2640R2F学习笔记(10)——GAP主机端连接

        本文链接:https://www.haomeiwen.com/subject/grravqtx.html