本文以SimpleBLECentral工程为例,介绍串口控制蓝牙。 过程: 扫描从机 - 根据从机号连接指定从机 - 获取RSSI值(信号强度) - 向char1写入特征值 - 断开连接
协议栈版本:BLE-CC254x-1.3.2 编译软件: IAR 8.20.2 硬件平台: Smart RF开发板(主芯片CC2541)、USB Dongle PC: 友善串口调试助手
声明:转载请注明出处。 原文地址:http://blog.csdn.net/liwei16611/article/category/7000460
1、在进行本文步骤前,请先阅读以下博文: 暂无
1、为什么要通过串口控制蓝牙? 答: 可以为后续实现串口蓝牙透传做准备,比较适合低成本低功耗的短距离小数据传输; 封装AT指令,通过串口来控制蓝牙的相关操作。
1、在串口回调函数内添加AT指令处理(SerialApp.c) // uart接收回调函数,当我们通过PC串口调试助手向开发板发送数据时,会调用该函数来接收 void sbpSerialAppCallback(uint8 port, uint8 event) { uint8 pktBuffer[SBP_UART_RX_BUF_SIZE]; (void)event; //返回可读的字节 if ( (numBytes = Hal_UART_RxBufLen(port)) > 0 ){ //读取全部有效的数据,这里可以一个一个读取,以解析特定的命令 (void)HalUARTRead (port, pktBuffer, numBytes); // AT指令处理函数 CommondHandle(pktBuffer, numBytes); } } 2、AT指令处理函数CommondHandle:验证串口(simpleBLECentral.c) 使用串口调试助手发送 AT AT指令处理函数返回OK给PC: // AT占用两个字节 if(length<2) return ; if(pBuffer[0]!='A' && pBuffer[1]!='T') return ; if(length <=4) { SerialPrintString("OK\r\n"); return ; } 注:指令 AT 串口测试,返回OK AT+ROLE? 获取当前角色 AT+SCAN 扫描从机 AT+CON[x] 连接指定的从机,x为搜索到的从机序号 AT+RSSI 获取rssi值 AT+DISCON 断开连接 AT+WRITE[0xXX] 向char1写入特征值 3、AT指令处理函数CommondHandle:BLE主机设备初始化完成(simpleBLECentral.c 的 simpleBLECentralEventCB 函数) 注册回调函数: // GAP Role Callbacks static const gapCentralRoleCB_t simpleBLERoleCB = { simpleBLECentralRssiCB, // RSSI callback simpleBLECentralEventCB // Event callback }; 初始化成功会直接调用回调函数的 GAP_DEVICE_INIT_DONE_EVENT 事件: case GAP_DEVICE_INIT_DONE_EVENT: { SerialPrintString("BLE Central: "); // 将 BLE 主机设备地址通过串口发送给PC SerialPrintString((uint8*)bdAddr2Str( pEvent->initDone.devAddr ));SerialPrintString("\r\n"); } break; 4、AT指令处理函数CommondHandle:BLE主机扫描从机(simpleBLECentral.c 的 CommondHandle 和 simpleBLECentralEventCB 函数) 1) 接收PC端AT指令:AT+SCAN if(length>=7 && str_cmp(pBuffer+3,"SCAN",4) == 0) { simpleBLEScanning = TRUE; simpleBLEScanRes = 0; SerialPrintString("Discovering...\r\n"); // 开始扫描从机设备 - 需要开启蓝牙从机设备 GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_ACTIVE_SCAN, DEFAULT_DISCOVERY_WHITE_LIST ); return ; } 2) 扫描到从机,调用回调函数处理 case GAP_DEVICE_DISCOVERY_EVENT: { simpleBLEScanning = FALSE; // if not filtering device discovery results based on service UUID if ( DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE ) { // Copy results simpleBLEScanRes = pEvent->discCmpl.numDevs; osal_memcpy( simpleBLEDevList, pEvent->discCmpl.pDevList, (sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) ); } // 将扫描的从机个数通过串口输出到PC SerialPrintValue("Devices Found", simpleBLEScanRes, 10); SerialPrintString("\r\n"); if ( simpleBLEScanRes > 0 ) { SerialPrintString("<- To Select\r\n"); } // initialize scan index to last device simpleBLEScanIdx = simpleBLEScanRes; } break; 5、AT指令处理函数CommondHandle:BLE连接扫描到的从机(simpleBLECentral.c 的 CommondHandle 和 simpleBLECentralEventCB 函数) 1) 接收PC端AT指令:AT+CON1 1表示从机序列号,即连接从机1 if(length>=7 && str_cmp(pBuffer+3,"CON",3) == 0) { // 连接参数CON后面跟的数值大于等于1,意思是连接第一个从机 第二个从机等 uint8 tmp=pBuffer[5]-48-1; if ( simpleBLEState == BLE_STATE_IDLE ){ // if there is a scan result if ( simpleBLEScanRes > 0 ) { uint8 addrType; uint8 *peerAddr; // connect to current device in scan result peerAddr = simpleBLEDevList[tmp].addr; addrType = simpleBLEDevList[tmp].addrType; simpleBLEState = BLE_STATE_CONNECTING; // 开始建立连接 GAPCentralRole_EstablishLink( DEFAULT_LINK_HIGH_DUTY_CYCLE, DEFAULT_LINK_WHITE_LIST, addrType, peerAddr ); SerialPrintString("Connecting:"); SerialPrintString((uint8*)bdAddr2Str( peerAddr));SerialPrintString("\r\n"); } } return ; } 2) 连接成功,调用回调函数处理 case GAP_LINK_ESTABLISHED_EVENT: { if ( pEvent->gap.hdr.status == SUCCESS ) { simpleBLEState = BLE_STATE_CONNECTED; simpleBLEConnHandle = pEvent->linkCmpl.connectionHandle; simpleBLEProcedureInProgress = TRUE; // If service discovery not performed initiate service discovery if ( simpleBLECharHdl == 0 ) { osal_start_timerEx( simpleBLETaskId, START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY ); } SerialPrintString("Connected: "); SerialPrintString((uint8*) bdAddr2Str( pEvent->linkCmpl.devAddr ));SerialPrintString("\r\n"); } else { simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; SerialPrintString("Connect Failed: "); SerialPrintValue("Reason:", pEvent->gap.hdr.status,10); } } 6、AT指令处理函数CommondHandle:BLE获取信号强度RSSI的值(simpleBLECentral.c 的 CommondHandle 和 simpleBLECentralEventCB 函数) 1) 接收PC端AT指令:AT+RSSI if(length>=7 && str_cmp(pBuffer+3,"RSSI",4) == 0) { // Start or cancel RSSI polling if ( simpleBLEState == BLE_STATE_CONNECTED ) { if ( !simpleBLERssi ) { simpleBLERssi = TRUE; // 开启获取RSSI值 GAPCentralRole_StartRssi( simpleBLEConnHandle, DEFAULT_RSSI_PERIOD ); } else { simpleBLERssi = FALSE; GAPCentralRole_CancelRssi( simpleBLEConnHandle ); LCD_WRITE_STRING( "RSSI Cancelled", HAL_LCD_LINE_1 ); SerialPrintString("RSSI Cancelled\r\n"); } } return ; } 2) RSSI获取成功,调用回调函数处理 static void simpleBLECentralRssiCB( uint16 connHandle, int8 rssi ) { // RSSI 值通过串口发送给 PC SerialPrintValue("RSSI -dB:", (uint8) (-rssi), 10);SerialPrintString("\r\n"); } 7、AT指令处理函数CommondHandle:BLE主机向char1写入特征值(simpleBLECentral.c 的 CommondHandle 和 simpleBLECentralEventCB 函数) 1) 接收PC端AT指令:AT+WRITE0x5A //AT+WRITE0xXX if(length>=10 && str_cmp(pBuffer+3,"WRITE0x",7) == 0) { //uint8 val=0; simpleBLECharVal=str2hex(pBuffer+10); if ( simpleBLEState == BLE_STATE_CONNECTED && simpleBLECharHdl != 0 && simpleBLEProcedureInProgress == FALSE ) { uint8 status; // 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 ); if ( status == SUCCESS ) { simpleBLEProcedureInProgress = TRUE; } } return ; } 8、AT指令处理函数CommondHandle:BLE主机断开连接(simpleBLECentral.c 的 CommondHandle 和 simpleBLECentralEventCB 函数) 1) 接收PC端AT指令:AT+DISCON if(length>=10 && str_cmp(pBuffer+3,"DISCON",6) == 0) { if ( simpleBLEState == BLE_STATE_CONNECTING || simpleBLEState == BLE_STATE_CONNECTED ) { // disconnect simpleBLEState = BLE_STATE_DISCONNECTING; // 断开连接 gStatus = GAPCentralRole_TerminateLink( simpleBLEConnHandle ); SerialPrintString("Disconnecting\r\n"); } } 2) 断开连接成功,调用回调函数处理 case GAP_LINK_TERMINATED_EVENT: { simpleBLEState = BLE_STATE_IDLE; simpleBLEConnHandle = GAP_CONNHANDLE_INIT; simpleBLERssi = FALSE; simpleBLEDiscState = BLE_DISC_STATE_IDLE; simpleBLECharHdl = 0; simpleBLEProcedureInProgress = FALSE; SerialPrintString("Disconnected: "); SerialPrintValue("Reason:", pEvent->linkTerminate.reason,10); } break;
