一、简介

本文以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;

【IoT】TI BLE CC2541 串口控制蓝牙详解相关推荐

  1. 【BLE】OTA基础知识详解

    [BLE]OTA基础知识详解 一. 概念 1. 缩写 BIM Boot Image Manager , the software bootloader CRC cyclic redundancy ch ...

  2. oracle控制文件都一样么,Oracle控制文件详解

    一.Oracle控制文件 为二进制文件,初始化大小由CREATEDATABASE指定,可以使用RMAN备份 记录了当前数据库的结构信息,同时也包含数据文件及日志文件的信息以及相关的状态,归档信息等等 ...

  3. python的turtle怎么设置rgb颜色_Python : turtle色彩控制实例详解

    ? 1 turtle.pencolor(* args ) 返回或设置pencolor. 允许四种输入格式: ? 1 pencolor() 将当前的pencolor返回为颜色规范字符串或元组(参见示例) ...

  4. 远程访问及控制(详解)——SSH远程管理及TCP Wrappers 访问控制

    远程访问及控制(详解)--SSH远程管理及TCP Wrappers 访问控制 一.SSH远程管理 1.定义 2.优点 3.客户端与服务端 4.SSH服务的开启.端口号和配置文件 二.配置 OpenSS ...

  5. ThinkPHP的RBAC(基于角色权限控制)详解

    ThinkPHP的RBAC(基于角色权限控制)详解 一.什么是RBAC 基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到 ...

  6. M1卡区块控制位详解

    M1卡区块控制位详解 Mifare 1S50/Mifare 1S70 每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取 控制.存取控制为4个字节,共32位,扇区中的每个块(包括 ...

  7. 单片机控制两个步进电机画圆_基于单片机的步进电机转速控制设计详解(附程序)...

    步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件.在非超载的情况下,电机的转速.停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角.这 ...

  8. 《前端》权限链接--vue前端权限控制方案详解附demo_feiyu_may的博客-CSDN博客_vue 前端权限

    前端权限控制 - 潘正 - 博客园  https://www.cnblogs.com/guchengnan/p/11800947.html vue前端权限控制方案详解附demo_feiyu_may的博 ...

  9. 增程式发动机仿真控制逻辑详解(一)

    本文转载在我的微信公众号:古德曼汽车工业. 希望关注本专栏的朋友,也能一并关注微信公众号. 原文地址:增程式发动机仿真控制逻辑详解(一) 1.前言 本订阅号的一个特色就是,你们都猜不到[思想]下一次更 ...

最新文章

  1. 发现一个有意思的博主(科研工作者)
  2. git-svn:通过git来管理svn代码
  3. P1198 [JSOI2008]最大数
  4. linux用unzip解压.zip文件失败解决方案
  5. token和session的区别
  6. mysql 设置事物自动提交_mysql事务自动提交的问题
  7. Linux C文件编译
  8. #考研#计算机文化知识1(局域网及网络互联)
  9. MAC修改保存bash_profile文件
  10. 锁表 for update
  11. python中字符编码:coding utf-8, unicde, defaultencoding, UnicodeDecodeError, UnicodeEncodeError
  12. 2012-2013QS计算机专业世界大学排名
  13. WZ-S甲醛传感器使用说明代码应用案例笔记
  14. 巴菲特指标:估值过高
  15. 永磁同步电机的直接转矩控制(三)一一一滑模控制器改进DTC
  16. 树莓派pico从零开始的入门(一)
  17. 小提琴统计图_箱形图和小提琴图
  18. 我的世界服务器修改spawn,编辑“命令/spawnpoint” - Minecraft Wiki,最详细的官方我的世界百科...
  19. Spring+SpringMVC+Hibernate整合(封装CRUD操作)
  20. 06.02、js之设置日期方法-年月日时分秒毫秒比较

热门文章

  1. estore和小项目总结
  2. Mac配置开发环境(后端)和软件安利
  3. 虚拟化技术KVM和XEN概述
  4. UE官方教程笔记01-实时渲染基础上
  5. 学习模拟电路设计制作
  6. 修改小米系统升级服务器,MIUI开发版系统更新策略大改 这些用户将无缘
  7. 软件自动化测试开发邹辉,软件自动化测试开发
  8. 关于机器学习的定义的理解
  9. 【核心内容及推导思路】人类记忆系统之谜,也许就是这么回事儿
  10. SQLmap注入教程