首页 > 其他分享 >【CC2640R2F】香瓜CC2640R2F之每30ms发80字节数据

【CC2640R2F】香瓜CC2640R2F之每30ms发80字节数据

时间:2025-01-17 15:01:10浏览次数:3  
标签:gnGUA GUA CC2640R2F naGUA Num 30ms IO 80 Buf

本文最后修改时间:2022年01月25日 10:19

一、本节简介

本节以simple_peripheral工程为例,介绍CC2640R2F如何使用定时器每30ms,发4个数据包(每个数据20字节),共发送80字节给app。

二、实验平台

1)CC2640R2F平台

①协议栈版本:CC2640R2 SDK v1.40.00.45

②编译软件:CCS7.3.0.00019

③硬件平台:香瓜CC2640R2F开发板、HC42的蓝牙5模块(作为主机使用)

④仿真器:香瓜XDS100V3下载器

2)手机平台

①手机型号:小米10至尊版

②安卓版本:安卓11

③安卓app:BLE Scanner

3)电脑平台

①HC-T串口助手(汇承公司自己的串口助手,买HC42模块时带的资料)

三、版权声明

1)作者:甜甜的大香瓜

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

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

4)香瓜BLE之CC2640R2F群:557278427

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

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

opengua.taobao.com

四、实验前提

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

1)《简单粗暴学蓝牙5》的“第一章至第四章”章节​。

2)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之连接参数》。

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

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

2)《简单粗暴学蓝牙5》的《香瓜CC2640R2F之指令读写IO》。

五、基础知识

1、本文的通信协议是?

答:

图片有点小,放大看。

2、本文的连接间隔修改为多少?

答:

本文的连接间隔范围设置为10ms~10ms,定时器定时每30ms发送一次。

要注意这个连接间隔不符合IOS连接参数要求,也不符合部分安卓手机的连接参数要求。本文是牺牲兼容性的前提下,来提升通信速率。如果要能兼容更多的手机,只能降低速率,自行修改。

3、本文的速率是多少?

答:每30ms发送4包(每包20字节,共80字节)。

由于每秒有(1000/30)次通信,所以通信速率=(1000/30)*80=2666.7字节/秒

4、本文的速率是极限值吗?

答:不是极限值,不同手机有不同极限值。如果是像两个CC2640R2F主从机都确定的通信,即可以实际去改至极限值,再在极限值基础上留一点余量。

另外也可以使用蓝牙5的大数据包通信,pdf第一章有资料链接。理应比这种蓝牙4.0就有的通信方式快。

六、硬件原理

暂无

七、实验步骤

一、修改连接参数(simple_peripheral.c

#ifndef FEATURE_OAD

// Minimum connection interval (units of 1.25ms, 80=100ms) for automatic

// parameter update request

#define DEFAULT_DESIRED_MIN_CONN_INTERVAL     8     //10ms

// Maximum connection interval (units of 1.25ms, 800=1000ms) for automatic

// parameter update request

#define DEFAULT_DESIRED_MAX_CONN_INTERVAL     8    //10ms

#else // FEATURE_OAD

// Increase the the connection interval to allow for higher throughput for OAD

// Minimum connection interval (units of 1.25ms, 8=10ms) for automatic

// parameter update request

#define DEFAULT_DESIRED_MIN_CONN_INTERVAL     8

// Maximum connection interval (units of 1.25ms, 8=10ms) for automatic

// parameter update request

#define DEFAULT_DESIRED_MAX_CONN_INTERVAL     8

#endif // FEATURE_OAD

// Slave latency to use for automatic parameter update request

#define DEFAULT_DESIRED_SLAVE_LATENCY         0

// Supervision timeout value (units of 10ms, 1000=10s) for automatic parameter

// update request

#define DEFAULT_DESIRED_CONN_TIMEOUT          100   //连接超时时间,连接IOS时此参数必须小于6S

// After the connection is formed, the peripheral waits until the central

// device asks for its preferred connection parameters

#define DEFAULT_ENABLE_UPDATE_REQUEST         GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS//GAPROLE_LINK_PARAM_UPDATE_WAIT_REMOTE_PARAMS

// Connection Pause Peripheral time value (in seconds)

#define DEFAULT_CONN_PAUSE_PERIPHERAL         1     //有时当从机断开连接时,主机端过10S才会断开,此时将此数值改小可让主机快速发现断开连接

修改了上述红色字体的五处。注意如果连接间隔范围是10ms~20ms,香瓜实测有丢包现象,所以后来改成10ms~10ms。

2、定义数据通信事件

1)定义数据通信的宏(simple_peripheral.c中)

//GUA

#define SBP_GUA_PERIODIC_EVT                Event_Id_02                             //香瓜周期事件

#define SBP_GUA_UART_EVT                    Event_Id_03                             //香瓜串口处理事件

#define SBP_GUA_DATA_EVT                    Event_Id_04                             //香瓜数据通信事件

#define SBP_GUA_ALL_EVENTS                  SBP_GUA_PERIODIC_EVT | SBP_GUA_UART_EVT  | SBP_GUA_DATA_EVT //所有事件的集合

//GUA

SBP_GUA_DATA_EVT是新定义的,其他是香瓜其他例程定义的,注意添加定义的位置。

2)添加周期事件的处理(simple_peripheral.c的SimpleBLEPeripheral_taskFxn中)

//GUA

      //香瓜数据通信事件

      if (events & SBP_GUA_DATA_EVT)

      {

          GUA_U16 nGUA_ConnHandle;

          //再次启动定时器

          Util_startClock(&GUA_DataClock);

          //获取连接句柄

          GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);

          //数据通信处理

          //第一包

          for(GUA_U8 i=0; i<=19; i++)

          {

              gaGUA_Data[i++] = gnGUA_Num >> 8;     //高8位

              gaGUA_Data[i] = (GUA_U8)(gnGUA_Num);  //低8位

              if(++gnGUA_Num > 10000)

              {

                  gnGUA_Num = 0;

              }

          }

          GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, gaGUA_Data, 20);    //发送数据

          //第二包

          for(GUA_U8 i=0; i<=19; i++)

          {

              gaGUA_Data[i++] = gnGUA_Num >> 8;     //高8位

              gaGUA_Data[i] = (GUA_U8)(gnGUA_Num);  //低8位

              if(++gnGUA_Num > 10000)

              {

                  gnGUA_Num = 0;

              }

          }

          GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, gaGUA_Data, 20);    //发送数据

          //第三包

          for(GUA_U8 i=0; i<=19; i++)

          {

              gaGUA_Data[i++] = gnGUA_Num >> 8;     //高8位

              gaGUA_Data[i] = (GUA_U8)(gnGUA_Num);  //低8位

              if(++gnGUA_Num > 10000)

              {

                  gnGUA_Num = 0;

              }

          }

          GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, gaGUA_Data, 20);    //发送数据

          //第四包

          for(GUA_U8 i=0; i<=19; i++)

          {

              gaGUA_Data[i++] = gnGUA_Num >> 8;     //高8位

              gaGUA_Data[i] = (GUA_U8)(gnGUA_Num);  //低8位

              if(++gnGUA_Num > 10000)

              {

                  gnGUA_Num = 0;

              }

          }

          GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, gaGUA_Data, 20);    //发送数据

      }

//GUA

此处发送4包数据,每包20字节。内容是0~10000,当超过10000时又会从0开始。每个数字是16位的,占用两个字节空间,所以一包20字节的可以发10个16位的数据。

此处连续调用4次发送函数,会被传到底层缓存区,在下一次连接事件(本文的每次连接事件为10ms~10ms)到来时发送出去。

3、初始化定时器

1)定义定时器结构体数据(simple_peripheral.c中)

//GUA 

static Clock_Struct GUA_DataClock; 

//GUA 

2)设置定时时间(simple_peripheral.c中)

//GUA 

#define SBP_GUA_DATA_EVT_PERIOD           30                   //香瓜定时时间

//GUA 

这里设置为30ms。

3)初始化定时事件(simple_peripheral.c的SimpleBLEPeripheral_init函数末尾中)

//GUA 

//初始化定时器 

Util_constructClock(&GUA_DataClock, SimpleBLEPeripheral_clockHandler, 

                        SBP_GUA_DATA_EVT_PERIOD, 0, false, SBP_GUA_DATA_EVT); 

//GUA

注意:这里仅仅是对定时器初始化函数,还需要一个“Util_startClock”函数(启动定时器函数)。必须两个都有,定时器才能被启动起来。

本文中的“Util_startClock”函数在特征值回调函数中被调用。

4、定义全局变量(simple_peripheral.c中)

//GUA

GUA_U8 gaGUA_Data[20] = {0};  //特征值的20字节缓存区

GUA_U16 gnGUA_Num = 0;        //用于计数数据内容0~10000的变量

//GUA

5、添加手机app指令处理函数

替换simple_peripheral.c的GUA_Profile_CharValueChangeEvt

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

//name:         GUA_Profile_CharValueChangeEvt

//introduce:    香瓜服务的应用层处理函数

//parameter:    nGUA_ParamID:特征值ID

//return:       none

//author:       甜甜的大香瓜

//email:        897503845@qq.com

//QQ group:     香瓜BLE之CC2640R2F(557278427)

//shop:         opengua.taobao.com

//changetime:   2021.12.27

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

static void GUA_Profile_CharValueChangeEvt(GUA_U8 nGUA_ParamID)

{

  GUA_U16 nGUA_ConnHandle;

  GUA_U8 naGUA_Buf[20] = {0};

  GUA_U8 *pGUA_Value = naGUA_Buf;

  //判断是哪个特征值

  switch(nGUA_ParamID)

  {

//特征值1

case GUAPROFILE_CHAR1:

{

        //获取连接句柄

        GAPRole_GetParameter(GAPROLE_CONNHANDLE, &nGUA_ConnHandle);

        //获取读到的数据

        GUAProfile_GetParameter(GUAPROFILE_CHAR1, naGUA_Buf);

        //根据读到的数据头字节判断是读IO还是写IO,0x00是读IO,0x01是写io

        switch(naGUA_Buf[0])

        {

            //读IO

            case 0x00:

            {

                //根据第二个字节,判断是读第几个IO

                switch(naGUA_Buf[1])

                {

                    //第0个IO(DIO15,LEFT键)

                    case 0x00:

                    {

                        //判断该IO是高还是低

                        if(PIN_getInputValue(IOID_15) == 0)

                        {

                            naGUA_Buf[2] = 0x00;    //低电平

                        }

                        else

                        {

                            naGUA_Buf[2] = 0x01;    //高电平

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //第1个IO(DIO18,RIGHT键)

                    case 0x01:

                    {

                        //判断该IO是高还是低

                        if(PIN_getInputValue(IOID_18) == 0)

                        {

                            naGUA_Buf[2] = 0x00;    //低电平

                        }

                        else

                        {

                            naGUA_Buf[2] = 0x01;    //高电平

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //第2个IO(DIO19,UP键)

                    case 0x02:

                    {

                        //判断该IO是高还是低

                        if(PIN_getInputValue(IOID_19) == 0)

                        {

                            naGUA_Buf[2] = 0x00;    //低电平

                        }

                        else

                        {

                            naGUA_Buf[2] = 0x01;    //高电平

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //第3个IO(DIO12,DOWN键)

                    case 0x03:

                    {

                        //判断该IO是高还是低

                        if(PIN_getInputValue(IOID_12) == 0)

                        {

                            naGUA_Buf[2] = 0x00;    //低电平

                        }

                        else

                        {

                            naGUA_Buf[2] = 0x01;    //高电平

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //其他

                    default:break;

                }

                break;

            }

            //写IO

            case 0x01:

            {

                //根据第二个字节,判断是写第几个IO

                switch(naGUA_Buf[1])

                {

                    //第0个IO(DIO25,LED1)

                    case 0x00:

                    {

                        //根据第2个字节的高低来写IO

                        if(naGUA_Buf[2] == 0)

                        {

                            GUA_Led_Set(GUA_LED_NO_1, GUA_LED_MODE_OFF);    //拉低

                        }

                        else

                        {

                            GUA_Led_Set(GUA_LED_NO_1, GUA_LED_MODE_ON);     //拉高

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //第1个IO(DIO27,LED2)

                    case 0x01:

                    {

                        //根据第2个字节的高低来写IO

                        if(naGUA_Buf[2] == 0)

                        {

                            GUA_Led_Set(GUA_LED_NO_2, GUA_LED_MODE_OFF);    //拉低

                        }

                        else

                        {

                            GUA_Led_Set(GUA_LED_NO_2, GUA_LED_MODE_ON);     //拉高

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //第2个IO(DIO7,LED3)

                    case 0x02:

                    {

                        //根据第2个字节的高低来写IO

                        if(naGUA_Buf[2] == 0)

                        {

                            GUA_Led_Set(GUA_LED_NO_3, GUA_LED_MODE_OFF);    //拉低

                        }

                        else

                        {

                            GUA_Led_Set(GUA_LED_NO_3, GUA_LED_MODE_ON);     //拉高

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //第3个IO(DIO0,LED4)

                    case 0x03:

                    {

                        //根据第2个字节的高低来写IO

                        if(naGUA_Buf[2] == 0)

                        {

                            GUA_Led_Set(GUA_LED_NO_4, GUA_LED_MODE_OFF);    //拉低

                        }

                        else

                        {

                            GUA_Led_Set(GUA_LED_NO_4, GUA_LED_MODE_ON);     //拉高

                        }

                        //发送数据

                        GUA_Profile_Notify(GUAPROFILE_CHAR1, nGUA_ConnHandle, naGUA_Buf, 3);

                        break;

                    }

                    //其他

                    default:break;

                }

                break;

            }

            //数据通信控制

            case 0x02:

            {

                //根据第二个字节,判断是停止数据通信,还是开始数据通信控制

                switch(naGUA_Buf[1])

                {

                    //停止数据通信

                    case 0x00:

                    {

                        //停止定时器

                        Util_stopClock(&GUA_DataClock);

                        //清除数据

                        gnGUA_Num = 0;

                        break;

                    }

                    //开始数据通信

                    case 0x01:

                    {

                        //启动定时器

                        Util_startClock(&GUA_DataClock);

                        //清除数据

                        gnGUA_Num = 0;

                        break;

                    }

                    //其他

                    default:break;

                }

                Break;

            }

            default:break;

        }

        break;

}

//其他

default: break;

  }

}

//GUA

这里大部分代码都是前例程的代码,真正添加的是“case 0x02”的数据通信部分。

可通过0x0201来打开定时器,启动数据通信事件;可通过0x0200来关闭定时器,停止数据通信事件。

八、注意事项

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

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

方法二:手机重启。

九、实验结果

仿真并全速运行,手机app连接并找到0xffe1的香瓜特征值,需要在app上打开该通道的通知开关。

1、开始数据通信

写入“0x0201”,即可看到快速收到数据。

2、停止数据通信

写入“0x0200”,即可停止收到数据。

不过手机app测试无法看清楚实际速率和是否丢包。

使用HC42模块进行速度实测:

正常连接时(详细连接过程看HC42说明书),发送0201开始通信、计时10秒后,发送0200关闭通信,可看到27340个字节,也就是2.734K字节/秒。任意选取一段数据查看都没有问题。

因此实验成功。

标签:gnGUA,GUA,CC2640R2F,naGUA,Num,30ms,IO,80,Buf
From: https://blog.csdn.net/feilusia/article/details/145207634

相关文章

  • 手把手教你学simulink(80.2)--智能家居语音助手系统场景实例:基于Simulink设计和仿真语音
    目录语音助手集成场景下的命令识别与响应建模项目实例项目背景介绍系统架构1. 语音采集模块(AudioCapture)2. 语音处理模块(SpeechProcessing)3. 命令识别模块(CommandRecognition)4. 响应生成模块(ResponseGeneration)5. 通信模块(Communication)仿真......
  • 洛谷P1803
    凌乱的yyy/线段覆盖-洛谷代码区:#include<stdio.h>#include<stdlib.h>structGAME{ intstart; intend;};intcmp(constvoid*a,constvoid*b){ structGAME*game1=(structGAME*)a; structGAME*game2=(structGAME*)b; returngame1->end-game2->......
  • HP惠普笔记本重装系统无法引导无法进操作系统的终极解决方法.210804
    F9进入BIOS-先进(Advanced)-安全引导配置-启用传统支持和禁用安全引导......
  • 【CC2640R2F】香瓜CC2640R2F之串口
    本文最后修改时间:2021年09月09日10:36一、本节简介本节以simple_peripheral工程为例,介绍如何使用串口。二、实验平台1)CC2640R2F平台①协议栈版本:CC2640R2SDKv1.40.00.45②编译软件:CCS7.3.0.00019③硬件平台:香瓜CC2640R2F开发板④仿真器:香瓜XDS100V3下载器2)PC端平......
  • 【CC2640R2F】香瓜CC2640R2F之自定义服务
    本文最后修改时间:2023年09月06日12:19一、本节简介本节以simple_peripheral工程为例,介绍如何添加自定义服务。二、实验平台1)CC2640R2F平台①协议栈版本:CC2640R2SDKv1.40.00.45②编译软件:CCS7.3.0.00019③硬件平台:香瓜CC2640R2F开发板④仿真器:香瓜XDS100V3下载器2......
  • XS2186八通道、供电设备(PSE)电源控制器,IEEE® 802.3at/af兼容PSE,单个端口提供最高达30W
    XS2186是一个八通道、供电设备(PSE)电源控制器,设计用于IEEE®802.3at/af兼容PSE。器件提供用电设备(PD)检测、分级、限流以及负载断开检测。器件支持全自动工作、软件编程和外挂eeprom。器件还支持最新二事件分级。采用单电源供电,能够为单个端口提供最高达30......
  • centos 7 不用yum安装mysql80
    要在CentOS7上不使用yum安装MySQL8.0,可以使用RPM包进行安装。以下是详细的步骤:下载MySQL8.0的RPM包首先,需要下载MySQL8.0的RPM包。可以从MySQL官方网站下载,或者使用wget命令直接下载。以下是一个示例:wgethttps://dev.mysql.com/get/Downloads/MySQL-......
  • JSP乐乐大学生二手书交易平台p1180(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表技术要求:开发语言:JSP前端使用:HTML5,CSS,JSP动态网页技术后端使用SpringBoot,Spring技术主数据库使用MySQL开题报告内容一、课题名称乐乐大学生二手书交易......
  • Hetao P3804 Cut 题解 [ 蓝 ] [ AC 自动机 ] [ 差分 ]
    Cut:AC自动机简单题。思路看见多个模式串以及求前缀,很显然能想到构建一个AC自动机。那么在用\(T\)查询时,当前指针的深度就是该位置的最长前缀匹配长度。这个在字典树insert的时候就能求出来。求出每一位的最长前缀后,因为这些部分都不能作为分割点,所以将这些区域用差分......
  • SamOut v3 发布-感叹转义词表能力太强【用em(voc_size=8000多,h)表达2000w 词汇 竟然
    项目地址说明v3主要更换了sky-pile数据集v3使用了转义词表技术,使得8000多的emsize能够表达2000多w的词表v3由于词表是使用jieaba分词,自然在相同token_id数量的情况下信息量更多(更多的字符)v3解码速度保持不变,同样训练消耗算力不变v3幻觉不变v3解码消耗显存......