为了实现外设+广播者的功能,除了直接使用peripheral.c和peripheral.h两个文件之外,TI还提供了peripheralBroadcaster.c和peripheralBroadcaster.h两个文件,下面就使用这两个文件来实现外设+广播者功能。我在《BLE工程——外设+广播者实现(使用peripheral.c)》一文的工程中进行修改。
1、将PROFILES工程组下peripheral.c和peripheral.h两个文件从工程中剔除,同时将peripheralBroadcaster.c和peripheralBroadcaster.h两个文件加入该工程组中。
2、此时编译工程会出现错误,打开peripheral.c文件,将包含的头文件:
#include "hci.h"
改为:
#include "hci_tl.h"
3、此时,编译虽然通过了,但下载到开发板中设备却不广播。原因在于GAPRole_Init()函数中角色设置错误了,需要将:
gapRole_profileRole=(GAP_PROFILE_PERIPHERAL|GAP_PROFILE_BROADCASTER);
改为:
gapRole_profileRole = (GAP_PROFILE_PERIPHERAL);
之所以要这么改是因为gapRole_SetupGAP()->GAP_DeviceInit()函数内选择条件中并没有GAP_PROFILE_PERIPHERAL|GAP_PROFILE_BROADCASTER这样的选项。
4、此时设备会开始广播,手机连上之后,但不一会儿连接就断开了。这个问题的原因是连接参数更新出错。需要做如下修改:
a.定义两个变量,一个用来保存连接的间隔参数,另一个用来保存连接延时个数。
static uint16 gapRole_ConnInterval = 0;
static uint16 gapRole_ConnSlaveLatency = 0;
b.在设备连接时,即gapRole_ProcessGAPMsg()函数的GAP_LINK_ESTABLISHED_EVENT选项中保存连接参数,添加如下两句:
if ( pPkt->hdr.status == SUCCESS )
{
......
/* Store connection information */
gapRole_ConnInterval = pPkt->connInterval;
gapRole_ConnSlaveLatency = pPkt->connLatency;
......
}
c.当连接参数更新超时时,重新更新连接参数。将GAPRole_ProcessEvent()函数中的if ( events & UPDATE_PARAMS_TIMEOUT_EVT )条件内的:
/* 这就是连接后会断开的原因 */
VOID GAP_TerminateLinkReq( gapRole_TaskID, gapRole_ConnectionHandle,
HCI_DISCONNECT_REMOTE_USER_TERM );
修改为:
gapRole_SendUpdateParam( gapRole_ConnInterval, gapRole_ConnSlaveLatency );
5、此时,虽然连接后连接不会断,但是按下JoyStick的上键是并没有开始广播。主要的原因是peripheralBroadcaster.c对用于保存广播状态的变量gapRole_AdvEnabled设置不明确,需要在如下几处做修改:
a.当设备连接时,系统会自动关闭广播,但代码并没有改变gapRole_AdvEnabled的状态,所以需要在gapRole_ProcessGAPMsg()函数的GAP_LINK_ESTABLISHED_EVENT选项中,添加语句:
if ( pPkt->hdr.status == SUCCESS )
{
.....
gapRole_AdvEnabled = FALSE;
}
b.每次设置打开/关闭广播时都要设置gapRole_AdvEnabled变量,即在GAPRole_SetParameter()中的GAPROLE_ADVERT_ENABLED选项中,添加语句:
if ( (gapRole_state == GAPROLE_CONNECTED) && (advEnabled == TRUE) )
{
gapRole_AdvEnabled = TRUE;
......
}
else if ( ..... )
{
gapRole_AdvEnabled = FALSE;
......
}
c.gapRole_ProcessGAPMsg()函数下的GAP_LINK_TERMINATED_EVENT选项中添加:
if ( gapRole_state == GAPROLE_CONNECTED_ADV )
{
......
}
else
{
.......
gapRole_AdvEnabled = TRUE;
}
6、此时,设备连接上后,按下JoyStick的上键则开始广播,再按下JoyStick的上键广播就会广播,但如再按下JoyStick的上键打算再次打开广播就会出现错误。造成这种原因是:连接后打开再关闭广播,此时设备的状态被设置成GAPROLE_WAITING状态,所以再次打开广播时GAPRole_ProcessEvent()的if ( events & START_ADVERTISING_EVT )条件下的:
if ( gapRole_state == GAPROLE_CONNECTED )
{
/* 不可连接广播 */
params.eventType = GAP_ADTYPE_ADV_NONCONN_IND;
}
else
{
params.eventType = gapRole_AdvEventType;
params.initiatorAddrType = gapRole_AdvDirectType;
VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr,
B_ADDR_LEN );
}
由于状态不是GAPROLE_CONNECTED,所以广播会被设置成连接的广播,所以会出错。要修正这个问题,需要将gapRole_ProcessGAPMsg()函数中的GAP_END_DISCOVERABLE_DONE_EVENT选项下的:
gapRole_state = GAPROLE_WAITING;
修改成:
if (gapRole_state == GAPROLE_CONNECTED_ADV)
{
gapRole_state = GAPROLE_CONNECTED;
}
else if (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT)
{
gapRole_AdvEnabled = TRUE;
VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
}
else
{
gapRole_state = GAPROLE_WAITING;
}
7、此时,广播的控制正常,但是当设备处于连接+广播状态,此时断开连接后设备将不再广播,所以打开simpleBLEPeripheral.c文件,将原先peripheralStateNotificationCB()函数中的GAPROLE_WAITING选项下的:
static uint8 auto_stop_adv= 0;
if ( auto_stop_adv )
{
uint8 adv_enabled_status = 1;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8),
&adv_enabled_status);
auto_stop_adv = 0;
}
if ( gapProfileState == GAPROLE_CONNECTED_ADV )
{
auto_stop_adv = 1;
}
修改为:
if ( gapProfileState == GAPROLE_CONNECTED_ADV )
{
uint8 adv_enabled_status = 1;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8),
&adv_enabled_status);
}
到此,就基本上修改完成了,将程序下载进SmartRF开发板中,在SmartRF首次运行时,就默认已经将广播打开了。
<1>按下JoyStick的上键,则将会将广播关闭,LCD上显示disconnect。
<2>在按下JoyStick的上键,则再次打开广播,LCD上显示advertising。
<3>手机连接SmartRF后,LCD上显示connected。
<4>按下JoyStick的上键,开启广播,LCD上显示connected advertising。此时,手机就可再次收到广播信号,但无法连接。
<5>按下JoyStick的上键,关闭广播,LCD上显示再次显示connected。
<6>手机断开,广播再次开启,且是可连接的广播,此时LCD显示advertising。
<7>如果手机连接了SmartRF,且不可连接广播开启着,此时手机断开连接,会继续广播,但变成可连接广播,LCD显示advertising。