前言
TI BLE SDK提供了Simple Peripheral工程,初学者可以通过这个工程来学习基本的蓝牙知识,通过实操掌握蓝牙基本的理论与通信方式。
在介绍这个工程前,先为大家介绍蓝牙Peripheral与Central的区别。如下图GAP主要负责Ble设备的连接,GAP状态机描述了设备空闲、设备发现与连接三个阶段的状态转换,状态解释如下
- Standby 复位后设备处于初始空闲态
- Advertiser 广播者广播指定格式数据使其他设备知道自己可连接,广播消息可包含设备地址和一些附加数据比如设备名称
- Scanner 接收广播消息时,扫描设备发送一个扫描请求给广播者,广播者回应一个扫描响应。这个过程称作设备发现。
- Initiator 发起者需要选择一个对端设备去连接,当广播者接收到匹配的连接地址时,发起者可以发送连接请求建立连接。
- Peripheral/Central 连接建立后,广播者为Peripheral作为Slave设备,发起者为Central作为Master设备。
根据上面介绍,我们知道Peripheral为发送广播消息的设备,也就是说Simple Peripheral工程会把Ble设备作为广播者,在测试时我们可以用手机作为Central设备来进行扫描连接。
Simple Peripheral工程解析
一. 总流程
—> main()
—> 初始化硬件模块、系统任务及建立自定义app任务
—> 进入Simple_Peripheral_createTask()【自定义app任务】
—> 进入回调函数SimplePeripheral_taskFxn()
—> 初始化app任务SimplePeripheral_init()
—> 处理(消息)事件及定时任务
1.1 打开Simple_Peripheral例程
在SDK安装路径中,参考我的路径:…\simplelink_cc13xx_cc26xx_sdk_7_10_01_24\examples\rtos\CC26X2R1_LAUNCHXL\ble5stack\simple_peripheral
1.2 main.c
1.2.1 初始化PIN 与 ICall 模块
// 初始化硬件
Board_initGeneral();
// 初始化ICall软件模块,用于app和stack之间的通信
ICall_init();
1.2.2 建立任务并启动BIOS
// 启动远程任务,对应的ICall的入口点,包含stack任务,优先级5
ICall_createRemoteTasks();
// 初始化app任务,以后用户要添加一个自定义任务,都要这样添加
SimpleBLEPeripheral_createTask();
// 启动Bios
BIOS_start();
1.2.4 完整代码
int main()
{
/* Register Application callback to trap asserts raised in the Stack */
RegisterAssertCback(AssertHandler);
Board_initGeneral();
// Enable iCache prefetching
VIMSConfigure(VIMS_BASE, TRUE, TRUE);
// Enable cache
VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);
/* Update User Configuration of the stack */
user0Cfg.appServiceInfo->timerTickPeriod = Clock_tickPeriod;
user0Cfg.appServiceInfo->timerMaxMillisecond = ICall_getMaxMSecs();
/* Initialize ICall module */
ICall_init();
/* Start tasks of external images - Priority 5 */
ICall_createRemoteTasks();
SimplePeripheral_createTask();
/* enable interrupts and start SYS/BIOS */
BIOS_start();
return 0;
}
接下来, 我们不看系统调度, 直接来看SimplePeripheral_createTask()
这个任务即可。
1.3 simple_Peripheral.c
app任务,以后用户要添加一个自定义任务,都要像这样模仿
1.3.1 SimplePeripheral_createTask
void SimplePeripheral_createTask(void)
{
// 创建一个任务结构体
Task_Params taskParams;
// 配置任务
Task_Params_init(&taskParams);
taskParams.stack = spTaskStack;
taskParams.stackSize = SP_TASK_STACK_SIZE; // 堆栈大小,在开发中需要适当增大
taskParams.priority = SP_TASK_PRIORITY; // 优先级,数值越小优先级越低
// SimplePeripheral_taskFxn是任务回调函数,此函数不会返回
Task_construct(&spTask, SimplePeripheral_taskFxn, &taskParams, NULL);
}
1.3.2 SimplePeripheral_taskFxn
static void SimplePeripheral_taskFxn(UArg a0, UArg a1)
{
// app任务初始化函数
SimplePeripheral_init();
// 死循环运行app任务
for (;;)
{
....
// 这里是处理收到(消息) 事件与定时器事件的地方
//处理协议栈GAT,GATT,HCI等消息通知
SimplePeripheral_processStackMsg(pMsg);
//处理Profile的回调,包括广播,配对,周期事件,自定义特征等消息callback
SimplePeripheral_processAppMsg(pMsg);
....
}
}
二. 处理(消息)事件流程
2.1 处理stack事件
在上述1.3.2死循环体中
// 处理stack发送的消息
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
uint8 safeToDealloc = TRUE;
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
{
ICall_Stack_Event *pEvt =