一、本节简介
本节以simple_peripheral工程为例,介绍如何添加从机通信状态的显示,如显示“Advertising”、“Connected”等状态。
二、实验平台
1)CC2640R2F平台
①协议栈版本:CC2640R2 SDK v1.40.00.45
②编译软件:CCS7.3.0.00019
③硬件平台:香瓜CC2640R2F开发板
④仿真器:香瓜XDS100V3下载器
2)手机平台
①手机型号:红米1S
②安卓版本:安卓4.3
③安卓app:BLE Reader
三、版权声明
1)作者:甜甜的大香瓜
2)声明:喝水不忘挖井人,转载请注明出处。
3)纠错/业务合作:[email protected]
4)香瓜BLE之CC2640R2F群:557278427
5)本文出处:原创连载资料《简单粗暴学蓝牙5》
6)完整开源资料下载地址(电脑端打开):
https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i
7)香瓜CC2640R2F开发板购买链接:
https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4023-16963296339.8.21bfc58419sWKt&id=558653143169
8)香瓜XDS100V3下载器购买链接:
https://item.taobao.com/item.htm?spm=a230r.1.14.1.1d150040zvJBco&id=558356989143&ns=1&abbucket=6#detail
四、实验前提
1、在进行本文步骤前,请先阅读以下章节:
1)《简单粗暴学蓝牙5》的“第一章至第四章”章节。
2、在进行本文步骤前,请先实现以下章节:
1)《简单粗暴学蓝牙5》的“第三章 软件的安装及使用”章节。
2)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之LCD》:http://blog.csdn.net/feilusia/article/details/78371371
五、基础知识
1、从机通信状态是指什么?
答:
在peripheral.h中有介绍
/// @brief GAP Peripheral Role States.
typedef enum
{
GAPROLE_INIT = 0, //!< Waiting to be started
GAPROLE_STARTED, //!< Started but not advertising
GAPROLE_ADVERTISING, //!< Currently Advertising
GAPROLE_ADVERTISING_NONCONN, //!< Currently using non-connectable Advertising
GAPROLE_WAITING, //!< Device is started but not advertising, is in waiting period before advertising again
GAPROLE_WAITING_AFTER_TIMEOUT, //!< Device just timed out from a connection but is not yet advertising, is in waiting period before advertising again
GAPROLE_CONNECTED, //!< In a connection
GAPROLE_CONNECTED_ADV, //!< In a connection + advertising
GAPROLE_ERROR //!< Error occurred - invalid state
} gaprole_States_t;
其中,我们最关心的是如下几种状态:
1)GAPROLE_STARTED:表明蓝牙初始化结束,此时可以显示本机的mac地址、显示"Initialized"。
2)GAPROLE_ADVERTISING:表明当前蓝牙已在广播,此时显示"Advertising"。
3)GAPROLE_CONNECTED:表明当前已被主机连接上了,此时显示“Connected”。
4)GAPROLE_WAITING:表明当前已与主机断开连接,比如主机主动断开、强行关闭手机的蓝牙app、强行关闭手机的蓝牙开关、强行手机关机,此时显示"Disconnected"。
2、为何要为这些状态增加显示?
答:
有了通信状态显示,可以更直观地知道设备运行的状态。是很实用的功能。
六、硬件原理
暂无
七、实验步骤
1、修改状态回调函数(替换simple_peripheral.c的SimpleBLEPeripheral_processStateChangeEvt函数)
static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState)
{
#ifdef PLUS_BROADCASTER
static bool firstConnFlag = false;
#endif // PLUS_BROADCASTER
//蓝牙状态
switch ( newState )
{
//蓝牙初始化好时
case GAPROLE_STARTED:
{
uint8_t ownAddress[B_ADDR_LEN];
uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
//获取本设备的8字节mac地址
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
//将8字节mac地址转为6字节系统ID
// use 6 bytes of device address for 8 bytes of system ID value
systemId[0] = ownAddress[0];
systemId[1] = ownAddress[1];
systemId[2] = ownAddress[2];
// set middle bytes to zero
systemId[4] = 0x00;
systemId[3] = 0x00;
// shift three bytes up
systemId[7] = ownAddress[5];
systemId[6] = ownAddress[4];
systemId[5] = ownAddress[3];
//保存系统ID
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
//显示(协议栈原显示驱动未用,使用香瓜的显示驱动)
// Display device address
Display_print0(dispHandle, SBP_ROW_BDADDR, 0, Util_convertBdAddr2Str(ownAddress));
Display_print0(dispHandle, SBP_ROW_ROLESTATE, 0, "Initialized");
//GUA
GUA_LCD_WriteString(Util_convertBdAddr2Str(ownAddress), GUA_LCD_LINE4);
GUA_LCD_WriteString("Initialized", GUA_LCD_LINE5);
//GUA
}
break;
//开始广播时
case GAPROLE_ADVERTISING:
Display_print0(dispHandle, SBP_ROW_ROLESTATE, 0, "Advertising");
//GUA
GUA_LCD_WriteString("Advertising", GUA_LCD_LINE5);
//GUA
break;
#ifdef PLUS_BROADCASTER
// After a connection is dropped, a device in PLUS_BROADCASTER will continue
// sending non-connectable advertisements and shall send this change of
// state to the application. These are then disabled here so that sending
// connectable advertisements can resume.
case GAPROLE_ADVERTISING_NONCONN:
{
uint8_t advertEnabled = FALSE;
// Disable non-connectable advertising.
GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),
&advertEnabled);
advertEnabled = TRUE;
// Enabled connectable advertising.
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&advertEnabled);
// Reset flag for next connection.
firstConnFlag = false;
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
}
break;
#endif //PLUS_BROADCASTER
//连接时
case GAPROLE_CONNECTED:
{
linkDBInfo_t linkInfo;
uint8_t numActive = 0;
//开启周期事件
Util_startClock(&periodicClock);
//获取已连接设备总数
numActive = linkDB_NumActive();
// Use numActive to determine the connection handle of the last
// connection
//提取到了设备信息,则说明之前已有连接设备,则显示已连接设备总数、显示此刻连接上的主机地址
if ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS )
{
Display_print1(dispHandle, SBP_ROW_ROLESTATE, 0, "Num Conns: %d", (uint16_t)numActive);
Display_print0(dispHandle, SBP_ROW_STATUS_1, 0, Util_convertBdAddr2Str(linkInfo.addr));
//GUA
GUA_LCD_WriteStringValue("Num Conns:", (uint16_t)numActive, 10, GUA_LCD_LINE5); //显示当前连接数
GUA_LCD_WriteString(Util_convertBdAddr2Str(linkInfo.addr), GUA_LCD_LINE6); //显示最后连接的主机地址
//GUA
}
//提取不到设备信息,则说明之前没有已连接设备,则显示此刻的设备已连接、显示此刻连接上的主机地址
else
{
uint8_t peerAddress[B_ADDR_LEN];
GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
Display_print0(dispHandle, SBP_ROW_ROLESTATE, 0, "Connected");
Display_print0(dispHandle, SBP_ROW_STATUS_1, 0, Util_convertBdAddr2Str(peerAddress));
//GUA
GUA_LCD_WriteString("Connected", GUA_LCD_LINE5); //显示为已连接
GUA_LCD_WriteString(Util_convertBdAddr2Str(peerAddress), GUA_LCD_LINE6); //显示当前连接的主机地址
//GUA
}
#if !defined(Display_DISABLE_ALL)
tbm_setItemStatus(&sbpMenuMain, TBM_ITEM_ALL, TBM_ITEM_NONE);
#endif // !Display_DISABLE_ALL
#ifdef PLUS_BROADCASTER
// Only turn advertising on for this state when we first connect
// otherwise, when we go from connected_advertising back to this state
// we will be turning advertising back on.
if (firstConnFlag == false)
{
uint8_t advertEnabled = FALSE; // Turn on Advertising
// Disable connectable advertising.
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&advertEnabled);
// Set to true for non-connectable advertising.
advertEnabled = TRUE;
// Enable non-connectable advertising.
GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),
&advertEnabled);
firstConnFlag = true;
}
#endif // PLUS_BROADCASTER
}
break;
//连接时广播
case GAPROLE_CONNECTED_ADV:
Display_print0(dispHandle, SBP_ROW_ROLESTATE, 0, "Connected Advertising");
//GUA
GUA_LCD_WriteString("Connected Advertising", GUA_LCD_LINE5);
//GUA
break;
//设备启动了但是没有广播出来,等待下一次广播
case GAPROLE_WAITING:
Util_stopClock(&periodicClock);
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
Display_print0(dispHandle, SBP_ROW_ROLESTATE, 0, "Disconnected");
#if !defined(Display_DISABLE_ALL)
// Disable PHY change
tbm_setItemStatus(&sbpMenuMain, TBM_ITEM_NONE, TBM_ITEM_ALL);
#endif // !Display_DISABLE_ALL
// Clear remaining lines
Display_clearLines(dispHandle, SBP_ROW_RESULT, SBP_ROW_STATUS_2);
//GUA
GUA_LCD_WriteString("Disconnected", GUA_LCD_LINE5);
GUA_LCD_ClearLine(GUA_LCD_LINE6);
//GUA
break;
//等待超时
case GAPROLE_WAITING_AFTER_TIMEOUT:
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
Display_print0(dispHandle, SBP_ROW_RESULT, 0, "Timed Out");
#if !defined(Display_DISABLE_ALL)
tbm_setItemStatus(&sbpMenuMain, TBM_ITEM_NONE, TBM_ITEM_ALL);
#endif // !Display_DISABLE_ALL
// Clear remaining lines
Display_clearLines(dispHandle, SBP_ROW_STATUS_1, SBP_ROW_STATUS_2);
//GUA
GUA_LCD_WriteString("Timed Out", GUA_LCD_LINE5);
GUA_LCD_ClearLine(GUA_LCD_LINE6);
//GUA
#ifdef PLUS_BROADCASTER
// Reset flag for next connection.
firstConnFlag = false;
#endif // PLUS_BROADCASTER
break;
//异常状态时
case GAPROLE_ERROR:
Display_print0(dispHandle, SBP_ROW_RESULT, 0, "Error");
//GUA
GUA_LCD_WriteString("Error", GUA_LCD_LINE5);
//GUA
break;
default:
Display_clearLines(dispHandle, SBP_ROW_RESULT, SBP_ROW_STATUS_2);
//GUA
GUA_LCD_ClearLine(GUA_LCD_LINE6);
//GUA
break;
}
}
增加了oled显示、增加了部分注释。
八、注意事项
暂无
九、实验结果
仿真并全速运行,可以看到:
1、上电后自动广播的显示
2、连接后的显示
注:由于断开连接等状态显示的时间过短,会快速地被重新广播刷新掉,所以其他状态只有仿真设置断点时能看到。
因此,实验成功。