打印
[CC2640]

CC2640学习笔记(2)——运行流程

[复制链接]
434|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
八层楼|  楼主 | 2019-12-31 14:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
一、总流程
—> main()
—> 初始化硬件模块、系统任务及建立自定义app任务
—> 进入SimpleBLEPeripheral_createTask()【自定义app任务】
—> 进入回调函数SimpleBLEPeripheral_taskFxn()
—> 初始化app任务SimpleBLEPeripheral_init()
—> 处理(消息)事件及定时任务

1.1 打开SimpleBLEPeripheral例程
C:\ti\simplelink\ble_cc26xx_2_01_00_44423\Projects\ble\SimpleBLEPeripheral\CC26xx\IAR\SimpleBLEPeripheral.eww

1.2 main.c
1.2.1 初始化PIN 与 ICall 模块
// 初始化硬件GPIO口
    PIN_init(BoardGpioInitTable);
// 初始化ICall软件模块,用于app和stack之间的通信
    ICall_init();


1.2.2 建立 2 个系统必要任务程序
// 启动远程任务,对应的ICall的入口点,包含stack任务,优先级5
    ICall_createRemoteTasks();

// 初始化GAPRole任务,管理蓝牙设备角色等事务,优先级3
    GAPRole_createTask();


1.2.3 建立用户自定义app任务// 初始化app任务,以后用户要添加一个自定义任务,都要这样添加


SimpleBLEPeripheral_createTask();


1.2.4 完整代码
int main()
{
    // 初始化硬件GPIO口
    PIN_init(BoardGpioInitTable);

#ifndef POWER_SAVING
    /* Set constraints for Standby, powerdown and idle mode */
    Power_setConstraint(Power_SB_DISALLOW);
    Power_setConstraint(Power_IDLE_PD_DISALLOW);
#endif // POWER_SAVING

    // 初始化ICall软件模块,用于app和stack之间的通信
    ICall_init();

    // 启动远程任务,对应的ICall的入口点,包含stack任务,优先级5(越大越优先)
    ICall_createRemoteTasks();

    // 初始化GAPRole任务,管理蓝牙设备角色等事务,优先级3
    GAPRole_createTask();

    // 初始化app任务,以后用户要添加一个自定义任务,都要这样添加
    SimpleBLEPeripheral_createTask();
#ifdef FEATURE_OAD
    {
      uint8_t counter;
      uint32_t *vectorTable =  (uint32_t*) 0x20000000;
#if defined(__IAR_SYSTEMS_ICC__)
      uint32_t *flashVectors = &__vector_table;
#elif defined(__TI_COMPILER_VERSION__)
      uint32_t *flashVectors = &ti_sysbios_family_arm_m3_Hwi_resetVectors;
#endif //Compiler.

      // Write image specific interrupt vectors into RAM vector table.
      for(counter = 0; counter < 15; ++counter)
      {

  *vectorTable++ = *flashVectors++;
      }
    }
#endif //FEATURE_OAD

    // 开启操作系统,永不返回
    BIOS_start();

    // 防止编译器警告用,代码无法执行到这里
    return 0;
}


接下来, 我们不看系统调度, 直接来看 SimpleBLEPeripheral_createTask() 这个任务即可。

1.3 simpleBLEPeripheral.c
app任务,以后用户要添加一个自定义任务,都要像这样模仿

1.3.1 SimpleBLEPeripheral_createTask
void SimpleBLEPeripheral_createTask(void)
{
  // 创建一个任务结构体
  Task_Params taskParams;

  // 配置任务
  Task_Params_init(&taskParams);
  taskParams.stack = sbpTaskStack;
  taskParams.stackSize = SBP_TASK_STACK_SIZE;  // 堆栈大小,在开发中需要适当增大
  taskParams.priority = SBP_TASK_PRIORITY;     // 优先级,数值越小优先级越低

  // SimpleBLEPeripheral_taskFxn是任务回调函数,此函数不会返回
  Task_construct(&sbpTask, SimpleBLEPeripheral_taskFxn, &taskParams, NULL);
}



1.3.2 SimpleBLEPeripheral_taskFxn
static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
{
  // app任务初始化函数
  SimpleBLEPeripheral_init();

  // 死循环运行app任务
  for (;;)
  {
   ....
  // 这里是处理收到(消息) 事件与定时器事件的地方
   ....
  }
}



使用特权

评论回复

相关帖子

沙发
八层楼|  楼主 | 2019-12-31 14:48 | 只看该作者
二、处理(消息)事件流程
2.1 处理app事件
在上述1.3.2死循环体中

// 如果RTOS队列不为空,处理APP消息
if (!Queue_empty(appMsgQueue))
{
    sbmEvt_t *pMsg = (sbmEvt_t *)Util_dequeueMsg(appMsgQueue);
    if (pMsg)
    {
        // 处理APP消息
       SimpleBLEPeripheral_processAppMsg(pMsg);

        // 释放内存
        ICall_free(pMsg);
    }
}


2.1.1 SimpleBLEPeripheral_processAppMsg
在上述1.3.2死循环体中,处理APP消息的函数,用户自定义处理事件往这里加(如按键事件处理)

static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg)
{
  switch (pMsg->hdr.event)
  {
    // BLE连接状态机部分
    case SBP_STATE_CHANGE_EVT:
      SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)pMsg->hdr.state);
      break;

    // BLE传输的事件处理,比如收到数据等等
    case SBP_CHAR_CHANGE_EVT:
      SimpleBLEPeripheral_processCharValueChangeEvt(pMsg->hdr.state);
      break;

    default:
      // Do nothing.
      break;
  }
}


2.2 处理定时器事件
在上述1.3.2死循环体中

if (events & SBM_PERIODIC_EVT)        // 我们APP建立的定时器事件,相当于自定义的定时器
{
    events &= ~SBM_PERIODIC_EVT;

    Util_startClock(&periodicClock);

    // 执行定时任务
    SimpleBLEMulti_performPeriodicTask();
}



使用特权

评论回复
板凳
八层楼|  楼主 | 2019-12-31 14:49 | 只看该作者
三、BLE初始化流程
—> ICall_registerApp注册,必须首先调用
—> 设置GAP层,例如广播间隔等参数
—> 设置GAPRole,例如是否开启广播等、连接参数等
—> 设置配对与绑定,例如是否开启绑定,以及绑定模式
—> 添加服务,设置服务参数并注册服务回调函数
—> 启动设备
—> 其他硬件配置



3.1 ICall_registerApp注册
ICall_registerApp 函数就是注册当前app任务,只有注册之后, ICall 的接口才会辨认我们这个 app 的消息与事件操作。

// ******************************************************************
// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
// ******************************************************************
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &sem);


3.2 设置GAP层

如果你是广播者工程, 这一条语句是可以忽略的


// Setup the GAP

GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);



设置广播间隔


// Set advertising interval

{

    uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;  // 广播间隔,间隔越大功耗越低       


    GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);

    GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);

    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);

    GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);

}



使用特权

评论回复
地板
八层楼|  楼主 | 2019-12-31 14:50 | 只看该作者
3.3 设置GAP Role
// Setup the GAP Peripheral Role Profile
  {
    // For all hardware platforms, device starts advertising upon initialization
    uint8_t initialAdvertEnable = TRUE;          // 开机广播

    // By setting this to zero, the device will go into the waiting state after
    // being discoverable for 30.72 second, and will not being advertising again
    // until the enabler is set back to TRUE
    uint16_t advertOffTime = 0;

    uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
    uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;// 传输数据延时1~2秒或者反应不灵敏,更改这两个参数为最小值8,可实现快速反应,不过功耗也就上去了
    uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
    uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
    uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;

    // Set the GAP Role Parameters
    GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
                         &initialAdvertEnable);
    GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
                         &advertOffTime);

    GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
                         scanRspData);
    GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);

    GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t),
                         &enableUpdateRequest);
    GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
                         &desiredMinInterval);
    GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
                         &desiredMaxInterval);
    GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
                         &desiredSlaveLatency);
    GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
                         &desiredConnTimeout);
  }


上述宏定义

// Advertising interval when device is discoverable (units of 625us, 160=100ms)
#define DEFAULT_ADVERTISING_INTERVAL          160                // 广播间隔,间隔越大功耗越低

// Limited discoverable mode advertises for 30.72s, and then stops
// General discoverable mode advertises indefinitely
#define DEFAULT_DISCOVERABLE_MODE             GAP_ADTYPE_FLAGS_GENERAL

// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic
// parameter update request is enabled
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL     80                // 最小连接间隔

// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic
// parameter update request is enabled
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL     800                // 最大连接间隔

// Slave latency to use if automatic parameter update request is enabled
#define DEFAULT_DESIRED_SLAVE_LATENCY         0                        // 可忽略连接间隔的次数,默认是不忽略

// Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter
// update request is enabled
#define DEFAULT_DESIRED_CONN_TIMEOUT          1000                // 连接超时时间,连接iOS时此参数必须小于6S

// Whether to enable automatic parameter update request when a connection is
// formed
#define DEFAULT_ENABLE_UPDATE_REQUEST         FALSE                // 使能连接参数更新请求

// Connection Pause Peripheral time value (in seconds)
#define DEFAULT_CONN_PAUSE_PERIPHERAL         6                        // 有时当CC2640断开连接时,主机端过10S才会断开,此时将此数值改小


使用特权

评论回复
5
八层楼|  楼主 | 2019-12-31 14:50 | 只看该作者
3.4 设置配对与绑定
// Setup the GAP Bond Manager
{
    uint32_t passkey = 0; // passkey "000000" 无需密码直接配对的意思
    uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
    uint8_t mitm = TRUE;
    uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
    uint8_t bonding = TRUE;

    GAPBondMgr_SetParameter(GAPBOND_DEFAULT_PASSCODE, sizeof(uint32_t),
                            &passkey);
    GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
    GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
    GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
    GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}


3.5 添加服务,初始化GATT属性
// 以下是添加服务,初始化GATT属性,一般来说,要增加新的服务就需要添加一条类似的函数
// 下面增加了4个服务,用手机APP可以发现这些服务
// Initialize GATT attributes
GGS_AddService(GATT_ALL_SERVICES);           // GAP
GATTServApp_AddService(GATT_ALL_SERVICES);   // GATT attributes
DevInfo_AddService();                        // Device Information Service

#ifndef FEATURE_OAD
SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
#endif //!FEATURE_OAD


3.6 设置服务的初始值
设置这5个profile的初始值,其实不设置也没关系,可省略

// Setup the SimpleProfile Characteristic Values
{
    uint8_t charValue1 = 1;
    uint8_t charValue2 = 2;
    uint8_t charValue3 = 3;
    uint8_t charValue4 = 4;
    uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };

    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
                               &charValue1);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
                               &charValue2);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
                               &charValue3);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
                               &charValue4);
    SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
                               charValue5);
}

// 注册SimpleProfile回调函数
SimpleProfile_RegisterAppCBs(&SimpleBLEPeripheral_simpleProfileCBs);


使用特权

评论回复
6
八层楼|  楼主 | 2019-12-31 14:51 | 只看该作者
3.7 启动设备
// 开启设备
VOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);

// 注册配对与绑定的回调函数
VOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);

// Register with GAP for HCI/Host messages
GAP_RegisterForMsgs(selfEntity);

// Register for GATT local events and ATT Responses pending for transmission
GATT_RegisterForMsgs(selfEntity);



3.8 其他硬件配置
#if defined FEATURE_OAD
#if defined (HAL_IMAGE_A)
  LCD_WRITE_STRING("BLE Peripheral A", LCD_PAGE0);
#else
  LCD_WRITE_STRING("BLE Peripheral B", LCD_PAGE0);
#endif // HAL_IMAGE_A
#else
  LCD_WRITE_STRING("BLE Peripheral", LCD_PAGE0);
#endif // FEATURE_OAD

到这里, BLE初始化完毕,现在也已经执行广播了,用你的手机 APP便可以发现参考CC2640学习笔记1


使用特权

评论回复
7
wiba| | 2020-1-6 13:00 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
8
zljiu| | 2020-1-6 13:03 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
9
coshi| | 2020-1-6 13:05 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
10
drer| | 2020-1-6 13:06 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

83

主题

4106

帖子

2

粉丝