自学内容网 自学内容网

【BLE】CC2541之AT指令实时修改设备名称

本文最后修改时间:2020年02月07日 19:32

一、本节简介

本文以SimpleBLEPeripheral工程为例,介绍如何使用AT指令来修改设备名称,且不需要重启设备,断开连接时即可看到广播中修改后的设备名称。

二、实验平台

1)CC2541平台

①协议栈版本:BLE-CC254x-1.4.0

②编译软件:IAR 8.20.2

③硬件平台:香瓜CC2541开发板

④仿真器:香瓜CC Debugger下载器

2)手机平台

①手机型号:小米8

②安卓版本:安卓8

③安卓app:TruthBlue

三、版权声明

1)作者:甜甜的大香瓜

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

3)纠错/业务合作:897503845@qq.com

4)香瓜BLE之CC2541群:127442605

5)本文出处:原创连载资料《简单粗暴学蓝牙4.0(CC2541篇)》

6)完整开源资料下载地址(电脑端打开):

opengua.taobao.com

7)香瓜CC2541开发板套件购买:

opengua.taobao.com

四、实验前提

1、在进行本文步骤前,请先阅读以下章节:

1)《简单粗暴学蓝牙4.0(CC2541篇)》的“第一章至第三章”章节

2)《简单粗暴学蓝牙4.0(CC2541篇)》的《CC2541之动态更新设备名》

3)《简单粗暴学蓝牙4.0(CC2541篇)》的《CC2541之SNV》

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

1)《简单粗暴学蓝牙4.0(CC2541篇)》的“第三章 软件的安装及使用”章节。

2)《简单粗暴学蓝牙4.0(CC2541篇)》的《CC2541之串口透传(20字节内任意长度)》

五、基础知识

暂无

六、硬件原理

暂无

七、实验步骤

1、添加SNV头文件(SimpleBLEPeripheral.c中)

#include “osal_snv.h”

2添加设备名称所用的宏定义(SimpleBLEPeripheral.c中)

//GUA

//SNV的设备名称使用

#define GUA_SNV_DEVICE_NAME_ID          0x80

#define GUA_SNV_DEVICE_NAME_READ        0x00

#define GUA_SNV_DEVICE_NAME_WRITE       0x01

//GUA

3添加SNV读写设备名称数据的函数

1定义SNV读写设备名称数据的函数(SimpleBLEPeripheral.c中)

//******************************************************************************

//name:         GUA_SNV_DeviceName

//introduce:    从 SNV 读取或写入设备名称

//parameter:    nGUA_WriteReadFlag:GUA_SNV_DEVICE_NAME_READ or GUA_SNV_DEVICE_NAME_WRITE

//              pGUA_DeviceName:设备名称结构体

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜 BLE 之 CC2541(127442605)

//shop:         opengua.taobao.com

//changetime:   2020.01.18

//******************************************************************************

static void GUA_SNV_DeviceName(uint8 nGUA_WriteReadFlag, ST_GUA_DEVICE_NAME *pGUA_DeviceName)

{

  uint8 nGUA_Ret;

  ST_GUA_DEVICE_NAME aGUA_Default_DeviceName = {7, “opengua”};

  //从SNV读设备名称

  if(nGUA_WriteReadFlag == GUA_SNV_DEVICE_NAME_READ)

  {

nGUA_Ret = osal_snv_read(GUA_SNV_DEVICE_NAME_ID, sizeof(stGUA_Device_Name), pGUA_DeviceName);

   

//如果第一次读取失败,则说明没有写过,是出厂的设备。因此在这里设置为出厂设备名称。

If(nGUA_Ret == NV_OPER_FAILED)

{

      //将出厂设备名称写入snv中

      osal_snv_write(GUA_SNV_DEVICE_NAME_ID, sizeof(stGUA_Device_Name), &aGUA_Default_DeviceName);

      //读出设备名称

      osal_snv_read(GUA_SNV_DEVICE_NAME_ID, sizeof(stGUA_Device_Name), pGUA_DeviceName);

}

  }

  //写新的设备名称到SNV

  else if(nGUA_WriteReadFlag == GUA_SNV_DEVICE_NAME_WRITE)

  {

//写进新的设备名称

osal_snv_write(GUA_SNV_DEVICE_NAME_ID, (pGUA_DeviceName->Len)+1, pGUA_DeviceName);

//读出新的设备名称

nGUA_Ret = osal_snv_read(GUA_SNV_DEVICE_NAME_ID, (pGUA_DeviceName->Len)+1, pGUA_DeviceName);

  }

}

每次上电时会调用此函数,将设备名称的结构体数据从SNV中读出。第一次出厂名称为“opengua”。

2声明SNV读写设备名称数据的函数(SimpleBLEPeripheral.c中)

//GUA

static void GUA_SNV_DeviceName(uint8 nGUA_WriteReadFlag, ST_GUA_DEVICE_NAME *pGUA_DeviceName);

//GUA

4、添加设备名称结构体SimpleBLEPeripheral.c中的最上方

//GUA

typedef struct{

  uint8 Len;

  uint8 Name[GAP_DEVICE_NAME_LEN];    

}ST_GUA_DEVICE_NAME;

ST_GUA_DEVICE_NAME stGUA_Device_Name;     

//GUA

之所以需要放在最上方,是因为声明函数中使用到此结构体,因此需要比声明函数位置更上方。

5、替换代码SimpleBLEPeripheral.c中的SimpleBLEPeripheral_Init

//GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );

替换成

//GUA

uint8 aGUA_ScanRspData_Temp[B_MAX_ADV_LEN] = {0}; 

uint8 nGUA_I = 0; 

   

//GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData );

   

//从SNV中读出设备名称结构体

GUA_SNV_DeviceName(GUA_SNV_DEVICE_NAME_READ, &stGUA_Device_Name);

   

//保存名称数据字段

aGUA_ScanRspData_Temp[nGUA_I++] = 1 + stGUA_Device_Name.Len;        //名称字段的长度=1(数据类型长度)+数据长度

aGUA_ScanRspData_Temp[nGUA_I++] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;   //名称字段的数据类型

osal_memcpy(&aGUA_ScanRspData_Temp[nGUA_I], stGUA_Device_Name.Name, stGUA_Device_Name.Len);//复制名称数据

//保存原来历程中的后续数据字段

nGUA_I += stGUA_Device_Name.Len;

osal_memcpy(&aGUA_ScanRspData_Temp[nGUA_I], (scanRspData+21), 9);

nGUA_I += 9;

   

//将扫描应答数据传给协议栈

GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, nGUA_I, aGUA_ScanRspData_Temp);   

//GUA

此处是在上电初始化时,将SNV的设备名称数据读出,并替换掉原来协议栈中的设备名称。但又保持原来扫描应答包的其他数据段。

6替换香瓜profile的回调函数(SimpleBLEPeripheral.c中)

//******************************************************************************

//name:         GUAProfileChangeCB

//introduce:    主机写入时的回调函数

//parameter:    paramID:特征值id

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜 BLE 之 CC2541(127442605)

//shop:         opengua.taobao.com

//changetime:   2020.01.19

//******************************************************************************

static void GUAProfileChangeCB( uint8 paramID )

{

  switch( paramID )

  {

case GUAPROFILE_CHAR1:

      {

        uint16 nGUA_NotifyHandle;

        uint8 aGUA_Buf[20] = {0};

        uint8 aGUA_AT[3] = “AT+”;  

        uint8 aGUA_AT_OK[5] = “AT+OK”;

        uint8 aGUA_ScanRspData_Temp[B_MAX_ADV_LEN] = {0}; 

        uint8 nGUA_I = 0;

       

        //获取句柄

        GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_NotifyHandle);

       

        //获取主机发来的数据

        GUAProfile_GetParameter(GUAPROFILE_CHAR1, aGUA_Buf);

       

        //判断是否是AT指令,如果是AT指令,则是修改名称的指令,否则从串口透传出去

        if(osal_memcmp(aGUA_Buf, aGUA_AT, 3) == TRUE)

        {

          //保存名称数据长度和名称数据到SNV

          stGUA_Device_Name.Len = gnGUA_len -3;

          osal_memcpy(stGUA_Device_Name.Name, (aGUA_Buf+3), stGUA_Device_Name.Len);

          GUA_SNV_DeviceName(GUA_SNV_DEVICE_NAME_WRITE, &stGUA_Device_Name);       

          //保存名称数据字段到扫描应答包的缓冲区

          aGUA_ScanRspData_Temp[nGUA_I++] = 1 + stGUA_Device_Name.Len;        //名称字段的长度=1(数据类型长度)+数据长度

          aGUA_ScanRspData_Temp[nGUA_I++] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;   //名称字段的数据类型

          osal_memcpy(&aGUA_ScanRspData_Temp[nGUA_I], stGUA_Device_Name.Name, stGUA_Device_Name.Len);//复制名称数据

          

          //保存原来历程中的后续数据字段到扫描应答包的缓冲区

          nGUA_I += stGUA_Device_Name.Len;

          osal_memcpy(&aGUA_ScanRspData_Temp[nGUA_I], (scanRspData+21), 9);

          nGUA_I += 9;

             

          //更新扫描应答包

          GAP_UpdateAdvertisingData(simpleBLEPeripheral_TaskID,

                                    FALSE,

                                    nGUA_I,

                                    aGUA_ScanRspData_Temp);                      

         

          //返回数据

          GUAprofile_Notify(GUAPROFILE_CHAR1, nGUA_NotifyHandle, aGUA_AT_OK, sizeof(aGUA_AT_OK));

        }

        else

        {

          //通过串口发送出去

          NPI_WriteTransport(aGUA_Buf, gnGUA_len);         

        }    

        break;

      }

     

default:break;

  }

}

如果是AT指令,则为修改名称,香瓜在此添加了实时修改名称的代码处理。如果不是AT指令,则为串口透传。

八、注意事项

1、手机可能缓存了之前固件的数据(在更新过固件之后,都需要清除手机端的缓存!!!),因此要清除缓存,清除缓存的方法如下:

方法一:关闭app、关闭蓝牙总开关、打开蓝牙总开关、打开app。

方法二:手机重启。

九、实验结果

   

上述三张图,分别为默认设备名称、修改名称指令、修改后的设备名称。

香瓜实现的是不需要重启即可实现的修改设备名称。

因此,实验成功。


原文地址:https://blog.csdn.net/feilusia/article/details/145169427

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!