【BLE】CC2541之配对密码的读取与修改

本篇博文最后修改时间:2016年12月29日,11:59。


一、简介

本文以SimpleBLEPeripheral工程为例,介绍如何用指令进行读取、修改配对密码。


二、实验平台

协议栈版本:BLE-CC254x-1.4.0

编译软件: IAR 8.20.2

硬件平台: Smart RF开发板(主芯片CC2541)

手机型号: 小米4S

安卓版本:安卓5.1

安卓app:TruthBlue


三、版权声明

博主:甜甜的大香瓜

声明:喝水不忘挖井人,转载请注明出处。

原文地址:http://blog.csdn.NET/feilusia

联系方式:897503845@qq.com

香瓜BLE之CC2541群:127442605

香瓜BLE之CC2640群:557278427

香瓜BLE之Android群:541462902

香瓜单片机之STM8/STM32群:164311667
甜甜的大香瓜的小店(淘宝店):https://shop217632629.taobao.com/?spm=2013.1.1000126.d21.hd2o8i

四、实验前提

1、在进行本文步骤前,请先 阅读以下博文:
1)《CC2541之SNV》:http://blog.csdn.net/feilusia/article/details/50190859

2、在进行本文步骤前,请先实现以下博文:

1)《CC2541之配对与绑定》:http://blog.csdn.net/feilusia/article/details/50212945
2)《CC2541之设置出厂时的配对密码》:http://blog.csdn.net/feilusia/article/details/53607891
3)《CC2541之通信协议》:http://blog.csdn.net/feilusia/article/details/53520236

五、通信协议



六、测试指令
香瓜的测试指令

1、功能码0x00(开关灯)
1)关灯
fe010000ffffffffffffffffffffffffffffffff

2)开灯
fe01000100ffffffffffffffffffffffffffffff

2、功能码0x01(读取密码)
fe0001ffffffffffffffffffffffffffffffffff

3、功能码0x02(修改密码)
1)修改密码为654321
fe0402f1fb0900f9ffffffffffffffffffffffff 

2)修改密码为132648
fe04022806020034ffffffffffffffffffffffff 

可自行对照上面的通信协议加强理解该指令。


七、实验步骤

1、修改通信协议的接收处理部分(替换GUA_RF_Communication.c

//******************************************************************************                            
//name:             GUA_RF_Communication.c               
//introduce:        香瓜的通信协议        
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜BLE之CC2541(127442605)                       
//changetime:       2016.12.13       
//****************************************************************************** 
#include "GUA_RF_Communication.h"
#include <string.h>

/*********************宏定义************************/ 
//通信协议的功能码
#define FUNC_GUA_LED_ON_OFF                             0x00    //led开关的功能码
#define FUNC_GUA_READ_PASSWORD                          0x01    //读取密码的功能码
#define FUNC_GUA_CHANGE_PASSWORD                        0x02    //修改密码的功能码

//应用层事件(从应用层复制过来)
#define SBP_START_DEVICE_EVT                            0x0001
#define SBP_PERIODIC_EVT                                0x0002
#define SBP_GUA_RF_COMMUNICAION_PROCESS_EVT             0x0004  //通信处理事件
#define SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT         0x0008  //通信数据出错事件

#define SBP_GUA_TERMINATE_CONNECTION_EVT                0x0010  //从机主动断开事件      
#define SBP_GUA_LED_ON_OFF_EVT                          0x0040  //led开关事件
#define SBP_GUA_READ_PASSWORD_EVT                       0x0080  //读取密码事件
#define SBP_GUA_CHANGE_PASSWORD_EVT                     0x0100  //修改密码事件 

//通信协议的数据包长度
#define GUA_DATA_PACKAGE_LEN                            20      //20字节一包

//******************************************************************************                
//name:             GUA_RF_Communication_Judgment               
//introduce:        RF的通信数据判断            
//parameter:        npGUA_Receive: 接收缓冲区首地址       
//return:           true: 数据包正确
//                  false: 数据包错误             
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜BLE之CC2541(127442605)                      
//changetime:       2016.12.13                      
//****************************************************************************** 
GUA_U8 GUA_RF_Communication_Judgment(GUA_U8 *npGUA_Receive)
{
  GUA_U8 nGUA_Sof = *npGUA_Receive;
  GUA_U8 nGUA_Len =  *(npGUA_Receive + 1);
  GUA_U8 nGUA_Func =  *(npGUA_Receive + 2);	
  GUA_U8 *npGUA_Data = npGUA_Receive + 3;
  GUA_U8 nGUA_Crc =  *(npGUA_Receive + 3 + nGUA_Len);
  GUA_U8 nGUA_Crc_Count = 0;	
	
  //判断起始位正确性
  if(nGUA_Sof != 0xFE)
  {
    return GUA_RF_COMMUNICATION_JUDGMENT_FALSE;  
  }		

  //接收数据长度
  if(nGUA_Len > 16)
  {
    return GUA_RF_COMMUNICATION_JUDGMENT_FALSE;  
  } 

  //计算校验和
  nGUA_Crc_Count += nGUA_Sof;    
  nGUA_Crc_Count += nGUA_Len;	
  nGUA_Crc_Count += nGUA_Func;
	
  while(nGUA_Len--)
  {
    nGUA_Crc_Count += *(npGUA_Data + nGUA_Len);
  }
	
  //比较校验和
  if(nGUA_Crc != nGUA_Crc_Count)  
  {
    return GUA_RF_COMMUNICATION_JUDGMENT_FALSE;  
  } 	

  //数据包正确
  return GUA_RF_COMMUNICATION_JUDGMENT_TRUE;
}

extern void GUA_SimpleGATTprofile_Char6_Notify(GUA_U16 nGUA_ConnHandle, GUA_U8 *npGUA_Value, GUA_U8 nGUA_Len);
//******************************************************************************                
//name:             GUA_RF_Communication_DataPackage_Send               
//introduce:        RF的通信数据打包并发送(包头+有效数据长度+功能码+有效数据+补齐字节)            
//parameter:        nGUA_Func: 功能码     
//                  npGUA_ValidData: 有效数据首地址
//                  nGUA_ValidData_Len: 要发送的数据
//return:           none            
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜BLE之CC2541(127442605)                      
//changetime:       2016.12.13                     
//****************************************************************************** 
void GUA_RF_Communication_DataPackage_Send(GUA_U16 nGUA_ConnHandle, GUA_U8 nGUA_Func, GUA_U8 *npGUA_ValidData, GUA_U8 nGUA_ValidData_Len)
{
  GUA_U8 nbGUA_DataPackage_Data[GUA_DATA_PACKAGE_LEN]; 
  GUA_U8 nGUA_Num;
  
  //初始化发送缓冲区
  memset(nbGUA_DataPackage_Data, 0xFF, 20);  
  
  //填充数据
  nbGUA_DataPackage_Data[0] = 0xFE;                                                     //包头
  nbGUA_DataPackage_Data[1] = nGUA_ValidData_Len;                                       //有效数据长度  
  nbGUA_DataPackage_Data[2] = nGUA_Func;                                                //功能码
  memcpy(nbGUA_DataPackage_Data + 3, npGUA_ValidData, nGUA_ValidData_Len);              //有效数据

  
  nbGUA_DataPackage_Data[3 + nGUA_ValidData_Len] = 0;                                   //校验和清零  
  for(nGUA_Num = 0; nGUA_Num < (3 + nGUA_ValidData_Len); nGUA_Num++)
  {
    nbGUA_DataPackage_Data[3 + nGUA_ValidData_Len] += nbGUA_DataPackage_Data[nGUA_Num]; //校验和累加   
  } 
  
  //发送数据    
  GUA_SimpleGATTprofile_Char6_Notify(nGUA_ConnHandle, nbGUA_DataPackage_Data, GUA_DATA_PACKAGE_LEN); 
}

//******************************************************************************                
//name:             GUA_RF_Communication_Process               
//introduce:        RF的通信数据处理            
//parameter:        npGUA_Receive: 接收缓冲区首地址     
//                  nGUA_Event: 要启动的事件
//return:           none            
//author:           甜甜的大香瓜                     
//email:            897503845@qq.com         
//QQ group          香瓜BLE之CC2541(127442605)                      
//changetime:       2016.12.13                      
//****************************************************************************** 
void GUA_RF_Communication_Process(GUA_U8 *npGUA_Receive, GUA_U16 *npGUA_Event)
{
  GUA_U8 nGUA_Func =  *(npGUA_Receive + 2);

  //判断功能码
  switch(nGUA_Func)
  {	
    //led开关的功能码
    case FUNC_GUA_LED_ON_OFF:
    {
      *npGUA_Event = SBP_GUA_LED_ON_OFF_EVT;
      break;      
    }

    //读取密码的功能码
    case FUNC_GUA_READ_PASSWORD:
    {
      *npGUA_Event = SBP_GUA_READ_PASSWORD_EVT;
      break;      
    }

    //修改密码的功能码
    case FUNC_GUA_CHANGE_PASSWORD:
    {
      *npGUA_Event = SBP_GUA_CHANGE_PASSWORD_EVT;
      break;      
    }

    //功能码无效
    default:
    {
      *npGUA_Event = SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT;
      break;      
    }           
  }
}

2、添加“从机主动断开事件、读取密码事件、修改密码事件

①定义“从机主动断开事件、读取密码事件、修改密码事件”(SimpleBLEPeripheral.c中)

  //从机主动断开事件
  if (events & SBP_GUA_TERMINATE_CONNECTION_EVT)
  {
    //断开连接
    GAPRole_TerminateConnection();

    return (events ^ SBP_GUA_TERMINATE_CONNECTION_EVT);
  }
  
  //功能码01 读取密码事件
  if (events & SBP_GUA_READ_PASSWORD_EVT)
  {
    uint16 nGUA_ConnHandle;       
    uint8 nGUA_Func;    
    uint8 nbGUA_ValidData[16]; 
    uint8 nGUA_ValidData_Len;

    //获得连接句柄
    GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);

    //功能码填充  
    nGUA_Func = 0x01;       

    //有效数据填充
    osal_memcpy(&nbGUA_ValidData[0], (uint8 *)(&gGUA_Password), sizeof(gGUA_Password));   

    //有效数据的长度
    nGUA_ValidData_Len = sizeof(gGUA_Password);

    //发送数据   
    GUA_RF_Communication_DataPackage_Send(nGUA_ConnHandle, nGUA_Func, nbGUA_ValidData, nGUA_ValidData_Len);     

    return (events ^ SBP_GUA_READ_PASSWORD_EVT);
  }

  //功能码02 修改密码事件
  if ( events & SBP_GUA_CHANGE_PASSWORD_EVT )
  {
    uint16 nGUA_ConnHandle;       
    uint8 nGUA_Func;    
    uint8 nbGUA_ValidData[16]; 
    uint8 nGUA_ValidData_Len;
    uint8 nbGUA_Char6[SIMPLEPROFILE_CHAR6_LEN] = {0};  
    
    /*****************处理指令************************/
    //读出RF接收到的数据到缓冲区
    SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6, nbGUA_Char6);

    //将APP传来的密码保存起来
    osal_memcpy((uint8 *)(&gGUA_Password), &nbGUA_Char6[3], sizeof(gGUA_Password));
    GUA_SNV_Password(GUA_SNV_PASSWORD_WRITE, (uint8 *)(&gGUA_Password), sizeof(gGUA_Password)); 

    //清除绑定信息
    GAPBondMgr_SetParameter(GAPBOND_ERASE_ALLBONDS,0, NULL);     
    
    //设置1S后断开连接
    osal_start_timerEx(simpleBLEPeripheral_TaskID, SBP_GUA_TERMINATE_CONNECTION_EVT, 1000);  
    
    /*****************应答************************/
    //获得连接句柄
    GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);

    //功能码填充  
    nGUA_Func = 0x02;       

    //有效数据填充
    osal_memcpy(&nbGUA_ValidData[0], (uint8 *)(&gGUA_Password), sizeof(gGUA_Password));   

    //有效数据的长度
    nGUA_ValidData_Len = sizeof(gGUA_Password);

    //发送数据   
    GUA_RF_Communication_DataPackage_Send(nGUA_ConnHandle, nGUA_Func, nbGUA_ValidData, nGUA_ValidData_Len);     

    return (events ^ SBP_GUA_CHANGE_PASSWORD_EVT);
  }

其中,在修改密码1S之后,从机会主动断开连接。


②定义“从机主动断开事件、读取密码事件、修改密码事件”的宏(替换SimpleBLEPeripheral.h中原来的事件宏

// Simple BLE Peripheral Task Events
#define SBP_START_DEVICE_EVT                            0x0001
#define SBP_PERIODIC_EVT                                0x0002
#define SBP_GUA_RF_COMMUNICAION_PROCESS_EVT             0x0004  //通信处理事件
#define SBP_GUA_RF_COMMUNICAION_COMMAND_ERR_EVT         0x0008  //通信数据出错事件

#define SBP_GUA_TERMINATE_CONNECTION_EVT                0x0010  //从机主动断开事件      
#define SBP_GUA_LED_ON_OFF_EVT                          0x0040  //led开关事件
#define SBP_GUA_READ_PASSWORD_EVT                       0x0080  //读取密码事件
#define SBP_GUA_CHANGE_PASSWORD_EVT                     0x0100  //修改密码事件   

八、注意事项

手机可能缓存了之前的代码(在更新过CC2541的代码之后,都需要清除手机端的缓存!!!),因此要清除缓存,清除缓存的方法如下:

方法一:关闭app、关闭蓝牙总开关、打开蓝牙总开关、打开app。
方法二:手机重启。


九、实验结果

仿真并全速运行,用truthblue扫描并连接。
1、默认密码
连接时会弹窗要求输入密码需要输入密码,也就是出厂密码123456。

2、读取密码和修改密码

1)读取密码指令与应答指令如上图红框,解析如下:
①app端发送
fe0001ffffffffffffffffffffffffffffffffff
②CC2541返回
fe0401 40E20100 26ffffffffffffffffffffffff
可解析出当前密码为: 0x0001E240= 123456

2)修改密码指令与应答指令如上图蓝框,解析如下:
1)app端发送(修改密码为654321)
fe0402f1fb0900f9ffffffffffffffffffffffff 
2)CC2541返回
fe0402f1fb0900f9ffffffffffffffffffffffff 
可解析出当前密码为:0x0009fbf1=654321

3)修改密码成功返回应答之后的1S,从机端会主动断开与app的连接。如上图紫框。


3、再次连接

再次连接时又会弹窗要求输入密码需要输入密码,这时候输入的则是我们刚刚修改好的654321。


4、再次查询密码


读取密码指令与应答指令如上图,解析如下:
①app端发送
fe0001ffffffffffffffffffffffffffffffffff
②CC2541返回
fe0401 f1fb0900f8 ffffffffffffffffffffffff
可解析出当前密码为:0x0009fbf1=654321

因此,成功地通过指令将密码从123456修改为654321,实验成功。


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值