第二十三节 蓝牙协议栈之主机通讯
随着蓝牙4.0模块的大量使用,为了很多从未接触过蓝牙的工程师也能快速便捷地开发蓝牙项目或者使用蓝牙,主从一体、远控IO等等特性也成为蓝牙模块必备的条件。其实,联合第二十一节和本节(第二十二节),我们就能将一个本无固件的裸片蓝牙,使其开发为具备主从一体功能的蓝牙模块。这两节的内容,也是本连载篇的重点部分之一。
上一节我们对从机的工作流程有了一个整体的把握。我们现在接着来看主机的工作流程。
主机的工作主要是扫描设备,对发现的设备发起连接,然后就是对特征值的读写操作了。
手动连接
从机的对外广播是在初始化的时候完成的,那主机的扫描是在哪里开始的呢?阅读源码可以发现主机的操作都在按键处理中完成的。主机通过五向按键中的五个按键实现不同的功能。
因为从机一直处于广播状态,所以秩序将上一节中的从机程序烧录进开发板即可,然后将主机程序烧录到另外一快开发板,通过五向按键来实现和从机的连接和读写功能。
(1) 上电提示
从机上电提示:
主机上电提示:
(2)根据主机的按键功能,我们按“UP”键,开始搜索周边设备。搜索完成后,可以看到,扫描到了一个设备。
扫描到一个设备:
(3)接着我们查看扫描到的设备地址,按左键。可以看到扫描到的设备地址为0x7C669D9F638A。这个地址正是我们的从机地址。
显示从机地址:
(4)按中间键连接从机,可以看到主机提示连接成功,从机也提示连接成功。
主机提示连接成功:
从机提示连接成功:
(5)接着我们开始读取从机的RSSI值,按下键。
(6)再次按下键,取消RSSI值的读取。
(7)对从机的CHAR1进行读写,再次按上键读取到CHAR1的值为1。
(8)接着按上键,对CHAR1写入0,同时看到从机提示CHAR1的值被修改为0。
主机写入成功:
从机提示CHAR1被改变:
上电自动连接
上一节中我们通过五向按键实现了主机连接从机的功能,这一节中们来实现主机上电后自动搜索连接从机。
要实现连接,从机必须处于广播状态,剩下的工作全部由主机完成,扫描、发起连接。
主机的状态也有回调函数,主机启动后,第一个状态是初始化,所以我们在初始化完成时开始扫描,
这样开机后主机就会开始扫描周边设备,接下来我们在扫描完成后对扫描到的设备发起连接。
将工程编译下载后通过串口助手观察主机和从机的输出可以发现主机上电后自动的完成了一系列的操作。
主机提示:
从机提示:
本文章转载自
http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/69222.aspx
请勿用于商业
随着蓝牙4.0模块的大量使用,为了很多从未接触过蓝牙的工程师也能快速便捷地开发蓝牙项目或者使用蓝牙,主从一体、远控IO等等特性也成为蓝牙模块必备的条件。其实,联合第二十一节和本节(第二十二节),我们就能将一个本无固件的裸片蓝牙,使其开发为具备主从一体功能的蓝牙模块。这两节的内容,也是本连载篇的重点部分之一。
上一节我们对从机的工作流程有了一个整体的把握。我们现在接着来看主机的工作流程。
主机的工作主要是扫描设备,对发现的设备发起连接,然后就是对特征值的读写操作了。
手动连接
从机的对外广播是在初始化的时候完成的,那主机的扫描是在哪里开始的呢?阅读源码可以发现主机的操作都在按键处理中完成的。主机通过五向按键中的五个按键实现不同的功能。
static void simpleBLECentral_HandleKeys( uint8 shift, uint8 keys )
{
(void)shift; // Intentionally unreferenced parameter
if ( keys & HAL_KEY_UP ) // 向上
{
// Start or stop discovery
if ( simpleBLEState != BLE_STATE_CONNECTED ) // 如果没有连接,开始扫描
{
if ( !simpleBLEScanning )
{
simpleBLEScanning = TRUE;
simpleBLEScanRes = 0;
LCD_WRITE_STRING( "Discovering...", HAL_LCD_LINE_1 );
LCD_WRITE_STRING( "", HAL_LCD_LINE_2 );
GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE,
DEFAULT_DISCOVERY_ACTIVE_SCAN,
DEFAULT_DISCOVERY_WHITE_LIST );
}
else
{
GAPCentralRole_CancelDiscovery();
}
}
else if ( simpleBLEState == BLE_STATE_CONNECTED && // 如果连接并且发现Handle进行读写操作
simpleBLECharHdl != 0 &&
simpleBLEProcedureInProgress == FALSE )
{
uint8 status;
// Do a read or write as long as no other read or write is in progress
if ( simpleBLEDoWrite )
{
// Do a write
attWriteReq_t req;
req.handle = simpleBLECharHdl;
req.len = 1;
req.value[0] = simpleBLECharVal;
req.sig = 0;
req.cmd = 0;
status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
else
{
// Do a read
attReadReq_t req;
req.handle = simpleBLECharHdl;
status = GATT_ReadCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
}
if ( status == SUCCESS )
{
simpleBLEProcedureInProgress = TRUE;
simpleBLEDoWrite = !simpleBLEDoWrite;
}
}
}
if ( keys & HAL_KEY_LEFT ) // 左
{
// Display discovery results
if ( !simpleBLEScanning && simpleBLEScanRes > 0 ) // 显示扫描到的设备
{
// Increment index of current result (with wraparound)
simpleBLEScanIdx++;
if ( simpleBLEScanIdx >= simpleBLEScanRes )
{
simpleBLEScanIdx = 0;
}
LCD_WRITE_STRING_VALUE( "Device", simpleBLEScanIdx + 1,
10, HAL_LCD_LINE_1 );
LCD_WRITE_STRING( bdAddr2Str( simpleBLEDevList[simpleBLEScanIdx].addr ),
HAL_LCD_LINE_2 );
}
}
if ( keys & HAL_KEY_RIGHT ) // 右
{
// Connection update
if ( simpleBLEState == BLE_STATE_CONNECTED ) // 如果连接,则更新连接
{
GAPCentralRole_UpdateLink( simpleBLEConnHandle,
DEFAULT_UPDATE_MIN_CONN_INTERVAL,
DEFAULT_UPDATE_MAX_CONN_INTERVAL,
DEFAULT_UPDATE_SLAVE_LATENCY,
DEFAULT_UPDATE_CONN_TIMEOUT );
}
}
if ( keys & HAL_KEY_CENTER ) // 中间键
{
uint8 addrType;
uint8 *peerAddr;
// Connect or disconnect
if ( simpleBLEState == BLE_STATE_IDLE ) // 空闲则连接
{
// if there is a scan result
if ( simpleBLEScanRes > 0 )
{
// connect to current device in scan result
peerAddr = simpleBLEDevList[simpleBLEScanIdx].addr;
addrType = simpleBLEDevList[simpleBLEScanIdx].addrType;
simpleBLEState = BLE_STATE_CONNECTING;
GAPCentralRole_EstablishLink( DEFAULT_LINK_HIGH_DUTY_CYCLE,
DEFAULT_LINK_WHITE_LIST,
addrType, peerAddr );
LCD_WRITE_STRING( "Connecting", HAL_LCD_LINE_1 );
LCD_WRITE_STRING( bdAddr2Str( peerAddr ), HAL_LCD_LINE_2 );
}
}
else if ( simpleBLEState == BLE_STATE_CONNECTING || // 连接则断开连接
simpleBLEState == BLE_STATE_CONNECTED )
{
// disconnect
simpleBLEState = BLE_STATE_DISCONNECTING;
gStatus = GAPCentralRole_TerminateLink( simpleBLEConnHandle );
LCD_WRITE_STRING( "Disconnecting", HAL_LCD_LINE_1 );
}
}
if ( keys & HAL_KEY_DOWN ) // 下
{
// Start or cancel RSSI polling
if ( simpleBLEState == BLE_STATE_CONNECTED ) // 连接则读取RSSi的值
{
if ( !simpleBLERssi )
{
simpleBLERssi = TRUE;
GAPCentralRole_StartRssi( simpleBLEConnHandle, DEFAULT_RSSI_PERIOD );
}
else
{
simpleBLERssi = FALSE;
GAPCentralRole_CancelRssi( simpleBLEConnHandle );
LCD_WRITE_STRING( "RSSI Cancelled", HAL_LCD_LINE_1 );
}
}
}
}
因为从机一直处于广播状态,所以秩序将上一节中的从机程序烧录进开发板即可,然后将主机程序烧录到另外一快开发板,通过五向按键来实现和从机的连接和读写功能。
(1) 上电提示
从机上电提示:
主机上电提示:
(2)根据主机的按键功能,我们按“UP”键,开始搜索周边设备。搜索完成后,可以看到,扫描到了一个设备。
扫描到一个设备:
(3)接着我们查看扫描到的设备地址,按左键。可以看到扫描到的设备地址为0x7C669D9F638A。这个地址正是我们的从机地址。
显示从机地址:
(4)按中间键连接从机,可以看到主机提示连接成功,从机也提示连接成功。
主机提示连接成功:
从机提示连接成功:
(5)接着我们开始读取从机的RSSI值,按下键。
(6)再次按下键,取消RSSI值的读取。
(7)对从机的CHAR1进行读写,再次按上键读取到CHAR1的值为1。
(8)接着按上键,对CHAR1写入0,同时看到从机提示CHAR1的值被修改为0。
主机写入成功:
从机提示CHAR1被改变:
上电自动连接
上一节中我们通过五向按键实现了主机连接从机的功能,这一节中们来实现主机上电后自动搜索连接从机。
要实现连接,从机必须处于广播状态,剩下的工作全部由主机完成,扫描、发起连接。
主机的状态也有回调函数,主机启动后,第一个状态是初始化,所以我们在初始化完成时开始扫描,
这样开机后主机就会开始扫描周边设备,接下来我们在扫描完成后对扫描到的设备发起连接。
将工程编译下载后通过串口助手观察主机和从机的输出可以发现主机上电后自动的完成了一系列的操作。
主机提示:
从机提示:
本文章转载自
http://www.deyisupport.com/question_answer/wireless_connectivity/bluetooth/f/103/t/69222.aspx
请勿用于商业