KDocs 研发资料库
  • 音频技术应用文档入口汇总
  • 杰理WINDOWS环境安装及其他事项
  • LINUX安装和编译
  • Linux环境编译SDK教程(ubuntu18.04)
  • 音频类补丁汇总表
  • 认证资料获取汇总(最新资料后台会更新)
  • 《Hi-Res申请指南v1.0》
  • FreeRTOS 开源协议版本
  • uCOS 开源协议版本信息
  • 各个模块关键资料汇总
  • 软件调试方法
  • Makefile编译
  • 提bug的规范
  • 常规设备使用指导
  • 对外特别发布开发注意点信息汇总
  • AD697X软件问题整理
  • AC700N软件问题整理
  • AC701X耳机软件问题整理
  • 951&961软件问题整理
  • AC104X软件问题整理
  • AC128N问题整理文档
  • 可视化工具调试问题整理
  • 耳机资料汇总
  • AC704N、 AC705N相关应用
  • AC695N&AC696N&AC608N音箱问题整理
  • JL701N音箱问题整理
  • AC692X软件问题整理
  • AC706N音箱问题整理
  • JL701N音箱问题整理(可视化工具SDK)
  • JL703N音箱问题整理
  • JL709N(JL689N)音箱问题整理
  • JL7094系列-入门到进阶开发指导
  • AC210N音箱问题整理
  • 无线麦系列版本支持指南
  • AW32N无线麦问题整理
  • lAD697X&JL701X 无线麦软件共性问题整理
  • AC706N无线麦问题整理
  • AW36N无线麦问题整理
  • AC710X无线麦问题整理
  • 唤醒源获取及唤醒IO设置
  • 电源
  • LVD
  • 长按复位配置方法
  • 低功耗应用
  • TIMER
  • UART
  • SPI
  • 内部FLASH空间添加用户自定义区域
  • IIC
  • GPIO
  • MCPWM
  • SD&U盘
  • 时钟&晶振
  • GPCNT
  • IO口crossbar映射功能
  • 文件系统使用总结
  • 复用应用
  • LINEIN_AUX相关应用
  • IIS音频接口应用
  • SPDIF模式相关(HDMI_ARC、光纤、同轴)
  • PDM LINK
  • 外设相关应用
  • 蓝牙相关
  • 杰理蓝牙距离调试文档
  • TWS耳机配对方式使用及生产把控指南
  • GFP谷歌快连及其认证流程指引
  • 蓝牙发射器(bt_emitter)相关
  • BLE应用
  • 关于提升BLE传输速率说明
  • BLE测试数据
  • MUSIC 模式相关应用
  • MIDI音乐实现
  • PC相关应用
  • FM相关应用
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20250107
  • fm应用详细设计说明书
  • 杰理FM硬件指南-20230315
  • ADC模块
  • AUDIO相关应用
  • 新Tools的音效调试使用
  • 混响应用使用说明
  • 音效调式
  • 音箱耳机低音小音量增强实现方法
  • DAC输出功率调试
  • DAC性能测试指南
  • 针对各类底噪、电流声分析流程
  • 录音相关应用
  • OPUS编解码相关
  • RTC相关应用
  • 升级相关
  • UI相关应用
  • 通话调试流程指南
  • 通话相关应用
  • 省电容mic使用手册
  • 如何测试验证手表通话系统的语音失真 V1.0
  • AC695X_AC696X_AD697X 常见通话问题处理参考资料
  • 通话调试问题确定步骤
  • 内置触摸调试指南
  • 低功耗内置触摸介绍V2.2
  • 触摸相关文档
  • AC697X、AC698X内置触摸调试及整改方法V1.0
  • 产测相关应用
  • AC63X BLE DUT测试介绍
  • 兆华序列使用简易说明
  • JL_1T2蓝牙测试盒音频文件更换说明
  • ENC相关应用入口汇总
  • ANC相关应用入口汇总
  • JL DMS通话调试手册-V3.9.4
  • ANC-ENC结构设计要点-20240407
  • 半入耳式ANC耳机器件选型与结构设计指南V1.0
  • JL 耳道自适应调试指南
  • ANC相关问题处理
  • ANC调试文档
  • 评估蓝牙耳机通话上行降噪性能的方法 V1.0 (2)
  • FCC 或者 BQB 认证相关应用
  • BQB profile 测试中常遇到的问题点汇总
  • 蓝牙参数整理20210811
  • 杰理科技认证问题参考
  • 无线音频产品开发指南
  • 无线麦系列从入门到进阶开发指导
  • 量产烧录相关说明
  • 一拖八烧录器远程过程调用说明
  • 量产相关建议
  • EffectTool(eq)调试工具说明文档
  • AC897AD697系列的EQ调试方法-V3
  • 杰理调音指南-20220622
  • 音效模块总结
  • 简要调音步骤指引(可视化)
  • 耳机充电与通信调试指南
  • 充电仓硬件调试指南
  • 充电仓软件问题整理
  • AC951常用说明
  • AC951_AC961_开发板使用说明V1.0
  • 彩屏仓AC982 入门指导及FAQ
  • 蓝牙音频APP相关应用
  • 手机APP的简介和开发流程
  • 蓝牙音频系列-硬件设计指南
  • 静电测试及整改方法-20220706
  • TWS耳机底噪整改指南V1.2
  • 杰理蓝牙距离调试文档
  • 蓝牙RF硬件设计与调试V1.1-20250219
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20241228
  • 音效调试指南
  • 无线话筒K歌音箱标准开发流程
  • 杰理科技 700N TWS耳机产品标准-202303
  • 杰理科技 701N 广播产品标准-202303
  • JL-HAT ANC高效产测自适应
  • 无线话筒测试板使用介绍
  • 一拖八频偏校准使用说明
  • 领夹麦产测工具使用介绍
  • Dongle量产测试说明
  • Dongle+Tws或头戴式 SDK通过工具绑定配对功能说明文档
  • 双麦ENC产测宏配置验证方法 V1.0
  • JL耳机方案麦克风声学测试指令_V1.0
  • JL耳机方案麦克风声学测试指令_V2.0
  • JL_ENC自动测试命令_V0.0.1
  • JL蓝牙测试盒用例说明
  • LDAC自测环境搭建_ubuntu
  • 延迟小板使用手册
  • 杰理库文件的制作及添加实现过程
  • 关于 AC635N&AC636N系列免晶振兼容性补丁 说明
  • 关于 AC63系列VM兼容性修复补丁_20250224 说明
  • 关于 AC632N &AE632N_ 蓝牙& 低功耗兼容性修复补丁 说明
  • AD698N和AC638N电压优化补丁V3说明
  • 关于 AC635N&AC636N漏电和E&G版兼容联合补丁 说明
  • AD698N和AC638N电压优化补丁V2说明
  • 702相关应用
  • 2024-4-30 发布歌词显示SDK开发注意事项
  • BQB RF & FCC 认证测试固件问题汇总及源码
  • BQB profile 测试中常遇到的问题点汇总
  • 进dut测试模式方法及固件
  • 704-频偏修改bin文件合集
  • 701手表BQB PROFILE认证注意事项
  • 认证的干扰规避整改
  • 海外CRA认证报告生成说明
  • JL700N可视化工具问题处理文档
  • JL701X可视化工具问题处理文档
  • JL701N_earphone_release_v1.6.0_ANC 低功耗问题补丁
  • JL708X可视化工具问题处理文档
  • JL709N可视化工具问题处理文档
  • JLstudio可视化工具使用说明
  • 一拖二-串口_蓝牙_app在线EQ、通话参数及调试方式和内置触摸调试
  • 可视化JL701M_DONGLE_SDK添加MIC为发射源
  • 可视化JL701M_DONGLE_SDK添加按键切换usb audio与MIC发射源
  • JL701M_DONGLE_SDK_1.0.0_dongle输入linein输出dac
  • 701可视化_a2dp_to_le_demo说明
  • 耳机系列demo汇总
  • JL7018F&JL7006F_7003F AUX IIS
  • 一键连接应用
  • 普通SDK动态开关一拖二功能
  • 蓝牙分析仪(EllisysBluetoothAnalyzer)抓包例程
  • TWS配对常见应用
  • APP自定义按键的demo
  • AC700N 播歌双EQ DEMO示例及说明
  • AC698V164 MIC与蓝牙音乐共同输出DAC demo
  • 添加第三方算法以及多算法授权流程
  • 空间音频配置方法
  • 普通高低电平TWS耳机控制通讯
  • 入耳检测状态更新demo解析
  • 资源优化(非可视化的SDK)
  • 资源优化(可视化SDK)
  • 翻译耳机、语音识别应用demo
  • 耳机抗干扰问题排查和优化
  • AC698D2 抗干扰优化
  • AC696X软件问题整理
  • AC695X软件问题整理
  • AC695X软件问题整理_1722249702
  • AC608X软件问题整理
  • JL701N_2T1_DUPLEX 应用软件问题汇总
  • le_audio_1.0.0_patch05 以及之前的版本IRkey 功能异常修改
  • AC706N-le_audio-200SDK有线_无线麦录音demo
  • jl701n_le_audio_v200patch02 IO串口升级修改串口单次发送字节长度的修改办法
  • 703创建IIS 输入dac输出音频流demo
  • 703将媒体流音频同时上传PC_mic录音demo实现
  • 703四路IIS输入输出demo
  • 底噪调试
  • AW328A烧录说明
  • 文档合集
  • AC706N_wireless_mic_release_PATCH_20240712 补丁 说明
  • AC706N_wireless_mic_release_PATCH_20240726 补丁 说明
  • AC706N_wireless_mic_release_V1.0.0、1.0.1、1.0.2 补丁 说明
  • AC706N_wireless_mic_release_V1.1.2 中的2T1应用 RX端不绑定配对,TX端实现绑定配对的修改方法
  • 各系列省晶振实现方法
  • iis tx rx说明文档
  • spdif信号
  • 蓝牙电话本
  • 安卓手机同步时间补丁
  • CDC配置
  • PC模式下增加Teams唤起功能
  • 杰理HDMIARC开发实现过程
  • AC701N patch06之前的版本用第三方算法节点实现新版本的pcm delay节点功能
  • (K歌音箱)各SDK音效配置相关说明
  • 长文件录音
  • 点阵屏歌词字库相关(蓝牙歌词,普通歌词)
  • 字模提取工具说明
  • 音箱可视化彩屏-入门到进阶开发指导
  • 彩屏LVGL UI设计及工具使用
  • 使用内部UI框架进行UI调试的系列步骤
  • AD101C使用强制升级工具spi 烧录不了问题处理(测试版本)
  • AD161扩展灯板说明文档
  • 歌词显示器开发注意项
  • 使用硬件数字增益控制通话下行音量(可视化)
  • 杰理小牛产测资料
  • ENC配置说明
  • 通话调试流程指引
  • ANC相关功能demo
  • 无线麦硬件资料汇总
  • 无线麦相关应用
  • 无线麦复杂功能补丁包汇总
  • 无线话筒形态SDK程序&开发经验&问题点分享
  • 双模式结合应用问题汇总
  • 无线麦距离优化案例
  • 无线麦系列中的双工形态(duplex)演变开发对讲机方案开发资料
  • 音箱入门到进阶指导文档(编写中)
  • 蓝牙耳机品控和生产技巧
  • 982过_欠压标志获取异常
  • 如何获取最新涂鸦SDK及库文件
  • 无线话筒K歌音响-调音标准流程
  • 无线话筒产测流程

手机APP的简介和开发流程

📎 原始文档:https://www.kdocs.cn/l/cum5StN3CwWL 手机APP的简介和开发流程
本文是关于手机APP功能的说明文档,会从APP应用的原理、示例、实例来介绍其开发流程,希望大家耐心看完。

  1. 初步了解手机APP应用

1.1 APP的应用场景

  1. 耳机 手机APP一般用于控制耳机的功能、修改音效,获取耳机的电量音量等信息并在APP界面显示出来,以及进行OTA升级。本文主要讲的是这种应用场景。
    image
  2. 音箱 除可能实现跟耳机相同的功能之外,音箱可能还有灯效、SD卡U盘等功能,修改灯效,显示SD卡U盘内的歌曲列表,都是APP可以实现的功能。
    image
  3. 穿戴 穿戴类常见的是智能手表,这种场景的APP的功能一般比较复杂,手机APP端可以显示手表上传感器的数据,比如心率、运动数据(步数),还可以给手表同步手机上的图片和音乐,表端就是则可以接收和显示手机APP发过来的通知、播放手机的音乐等。
    image
  4. 视频 视频相关的APP比较重要的功能是在手机上回放视频,但这种APP一般用WIFI连接比较多。

1.2 APP应用的框架

flowchart 框架中的两个大的个体:手机和耳机,它们之间通过蓝牙的BLE或者SPP进行数据传输,传输的内容是数据包,数据包是按照协议有序排列的一组数据。APP应用的功能,是由手机中安装的APP和耳机中的APP流程实现的。
2. APP应用中每个角色的作用

2.1 手机端

flowchart

  1. 手机 手机的作用,是提供APP运行的环境,提供蓝牙的连接和传输功能,提供数据传输的接口(BLE、SPP等)。
    手机无法决定APP实现的具体功能,但是能够限制APP功能的实现方式。由于苹果手机不支持SPP,所以在苹果手机上运行的APP一般使用BLE的方式来跟我们的进行数据交互,安卓手机BLE和SPP都支持,所以在安卓手机上运行的APP既可以用BLE通信,也可以用SPP通信,但是具体用哪种,或者是否两种都支持,则需要咨询APP。
  2. APP APP一般作为控制者存在,其作用一般为:控制耳机的功能,获取耳机的信息,提供耳机需要的数据。以上三个作用里面的具体功能,是由产品功能定义来决定的。
    控制耳机的功能:一般为控制耳机的暂停播放、上下曲等,如果产品定义里面有ANC、低延时这些功能,可能还会涉及这些功能的开关切换。更复杂的可能还涉及对耳机功能的修改,常见的是修改耳机的按键功能,修改耳机的声音效果(EQ)。
    获取耳机的信息:凡是可以用数据来表示的信息,APP都有可能来获取,例如获取耳机当前的播放状态(暂停还是播放中)、各个功能的开关状态、当前生效的EQ参数、音量等,当然具体APP会来获取什么信息,也是由产品定义决定的。
    提供耳机需要的数据:根据产品定义的功能,提供数据给耳机执行,例如提供EQ参数给耳机用于切换音效,在OTA升级中给耳机提供升级文件的数据。
    手机端数据包的加密和打包也是在APP上进行的,APP打包好数据包之后,会使用手机提供的数据传输接口将数据包发送出去。
  3. 数据传输接口BLE、SPP 数据传输接口由手机提供,使用者是APP,常见的接口就是我们目前用到的BLE和SPP(当然手机还有其他可以用来传数据的接口,比如WIFI、蜂窝网络、USB,但本文不涉及)。
    APP将数据包给到数据传输接口后,会由接口择机发送出去;接口收到耳机发过来的数据之后,也会通知并将数据传给APP。
    数据传输接口不仅提供数据传输的功能,还会提供BLE和SPP的连接功能。目前的APP应用中,都是由APP使用手机提供的接口来发起连接,耳机的连接是被动的,无法主动发起。

2.2 耳机端

flowchart

  1. 耳机 从功能上来说,耳机这个角色的作用与手机类似,同样提供APP流程运行的环境,提供蓝牙的连接和数据传输功能,提供数据传输的接口(BLE、SPP)。
    而耳机上的功能也是由产品定义来决定,APP最终要控制的就是耳机的功能。
  2. APP流程 耳机上的APP流程其实就是一个功能模块,它的主要作用就是解析收到的数据,获取耳机的各个信息,打包要发送的数据。
    对应手机APP的三个作用,耳机上的APP流程主要完成以下三件事情:
    接收手机APP的控制命令,控制耳机的功能;
    收集耳机的状态信息,打包发送给手机APP;
    接收手机APP的数据,修改各项参数或进行OTA升级。
  3. 数据传输接口BLE、SPP 跟手机端一样的原理,APP流程需要用到的数据传输接口也是由耳机提供,数据传输接口给APP流程提供数据收发服务,但是与手机端不一样的是,在我们讨论的APP应用中,APP流程不能控制BLE和SPP主动发起连接,只能主动断开。
  4. 协议和数据包 协议在APP应用中十分重要,就像人与人交流时需要使用相同的语言一样,在APP应用中需要手机和耳机使用同样的”语言“交互。
    使用相同的语言,就是要求手机和耳机使用相同的协议进行数据的打包、解析和交互。
    协议的定义:协议(计算机学科概念)。
    按照协议打包的一组数据,我们称之为数据包。

3.1 简单理解协议

1. 按照约定的方式交互 -- 按照约定好的格式来打包和解析数据包
2. 按照约定的步骤做事情 -- 约定好交互的先后顺序,谁先发起通信,如何交换数据
3. 按照预定的时间点做事情 -- 约定好在什么时间点该进行什么样的交互,发什么样的数据

3.2 数据包的打包

简单理解,打包就是把一些零散的东西通过某种方式合并成一个统一的整体,这里涉及到三个角色:零散的东西、某种方式、统一的整体。

  1. 零散的东西 零散的东西可以是任何信息、数据,每个零散个体可以有它自己的含义和作用,但是如果这些东西是零散杂乱无章地堆在那里,我们很难快速从中找到我们需要的信息。在APP应用中,协议确定了哪些数据是需要打包的,但如果手机将数据杂乱无章地发过来给耳机(尤其是因为数据都是同样的16进制数值),则耳机根本无法从中获取想要的数据。
  2. 某种方式 像第1点说的那样,如果手机将数据杂乱无章地发过来给耳机,耳机根本无法从中获取想要的数据。因此在实际应用中,手机APP和耳机会约定,传输的数据要按照一定的方式(规则)来进行排列组合,这个规则就是由协议决定的。
  3. 统一的整体 我们将需要的信息,按照协议规定的规则排列好之后,就形成了数据包。如此所有的数据交互都按照同样的规则打包、传输、解析,将零散的数据统一了起来,我们只需要根据协议定好的规则去解析数据包,就能拿到我们想要的信息。

3.3 数据包的解析

数据解析是数据打包的逆过程,从排列好的数据组合中,按照协议拆解数据,获取零散的信息。这个过程就不详述了。

3.4 数据包中可能包含的信息

  1. 命令:通过特定协商好的数值来表示需要执行的动作 例如,耳机和手机提前协商好,0x01这个命令用来切换低延时,0x02这个命令用来切换anc模式,0x03这个命令用来设置EQ参数,0x04这个命令用来获取当前的EQ参数。
  2. 参数:一个或者一些数据,用来表示某些信息,一般跟在命令后面 例如,耳机和手机提前协商好,跟在命令0x01后面的一个字节,如果这个字节是0x01,则是要打开低延时,如果是0x00,则是要关闭低延时。
  3. 数据校验信息:可能存在于数据包的任意位置 例如,在数据包中规定数据包必须以某个数据作为开头(包头),在数据包中规定某一个字节用来存放数据包的大小,在数据包中规定某一个字节用来存放数据包的CRC校验码,耳机或者APP收到数据包后,可以根据这些信息来确认收到的数据是否完整和正确。
  4. 一个数据包(协议)的示例(实际项目数据包格式需要和手机APP协商定好)
包头LENCMDPARAMCRC
0x1234n一个字节n个字节一个字节

3.5 数据包加密

有些APP可能会对数据包进行加密,加密方式也是要与手机APP沟通。
4. 一个简单的APP应用示例

4.1 结构图

flowchart

4.2 功能介绍:

耳机的功能:一个按键,单击暂停播放,双击下一曲,三击上一曲,长按开关机,内置3种EQ模式,支持修改EQ模式和EQ参数,支持双备份OTA升级。
手机APP的功能:可以控制耳机执行暂停播放和上下曲,可以修改耳机的音量,可以修改耳机的EQ模式和EQ参数,可以获取耳机的播放状态,可以获取耳机的音量,可以获取耳机的EQ模式和EQ参数,可以给耳机进行OTA升级。
手机和耳机约定使用SPP进行通信,同时约定使用如下的协议进行数据传输:

包头LENCMDPARAMCRC
0x1234n一个字节n个字节一个字节

CMD命令列表:

0x01控制耳机的暂停播放,后接1个字节PARAM数据,0x00表示要控制耳机暂停,0x01表示要控制耳机播放,耳机执行成功后需要给手机回复相同数据。
0x02控制耳机端上下曲功能,后接1个字节PARAM数据,0x00表示要控制耳机下一曲,0x01表示要控制耳机上一曲,耳机执行成功后需要给手机回复相同数据。
0x03修改耳机的音量,后接1个字节PARAM数据,表示需要修改的音量大小,范围是0~16,耳机执行成功后需要给手机回复相同数据。
0x04修改耳机的EQ模式,后接1个字节PARAM数据,表示需要修改的模式,范围0~2,耳机执行成功后需要给手机回复相同数据。
0x05修改耳机的EQ参数,后接10个字节PARAM数据,每个字节表示一个EQ频点的增益,增益的范围是-12~12,耳机执行成功后需要给手机回复相同数据。
0x06获取耳机当前的播放状态,后面没有PARAM数据,耳机收到该指令,要按照协议格式给手机回复耳机状态,回复时CMD填0x06,耳机正在播放时PARAM填写0x01,否则PARAM填写0x00。耳机本地播放状态变化时,也需要主动上报变化后的状态。
0x07获取耳机当前的音量大小,后面没有PARAM数据,耳机收到该指令,要按照协议格式给手机回复耳机音量,回复时CMD填0x07,PARAM填写音量大小,范围是0~16。耳机本地音量变化时,也需要主动上报变化后的音量。
0x08获取耳机当前的EQ模式,后面没有PARAM数据,耳机收到该指令,要按照协议格式给手机回复耳机当前的EQ模式,回复时CMD填0x08,PARAM填写EQ模式,范围是0~2。耳机本地EQ模式变化时,也需要主动上报变化后的模式。
0x09获取耳机当前的EQ参数,后面没有PARAM数据,耳机收到该指令,要按照协议格式给手机回复耳机当前的EQ参数,回复时CMD填0x09,PARAM填写10个字节的EQ参数,每个字节表示一个EQ频点的增益,增益的范围是-12~12。
0x0a通知耳机进入OTA升级模式,后接4个字节PARAM数据,表示升级文件的大小,耳机执行成功后需要给手机回复相同数据。
0x0b表示这包是升级文件的数据,后接255字节的升级文件数据,耳机收到数据后,要按照协议格式给手机回复升级文件数据的接收状态,回复时CMD填0x0b,PARAM填写状态,范围0~2,0表示写入成功,1表示写入失败,2表示数据校验不通过。

4.3 数据包打包demo

/**
 * @brief 计算crc
 * 
 * @param ptr 
 * @param len 
 * @return u8 
 */
static u8 crc8(u8 *ptr, u8 len)
{
    u8 i, crc;
    crc = 0;
    while (len--) {
        crc ^= *ptr++;
        for (i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc = (crc >> 1) ^ 0x8c;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

/**
 * @brief 打包
 * 
 * @param tx_buff 数据包缓存
 * @param cmd 命令
 * @param data 需要打包的参数
 * @param len 需要打包的参数长度
 * @return u16 数据包的长度
 */
u16 data_package(u8 *tx_buff, u8 cmd, u8 *data, u8 len)
{
    u16 length = len + 5;
    u8 *buff = tx_buff;
    if(!buff){
        return;
    }
    memset(buff, 0x00, length);
    buff[0] = 0x34;
    buff[1] = 0x12;
    buff[2] = len;
    buff[3] = cmd;
    if(date && len){
        memcpy(buff + 4, data, len);
    }
    buff[length - 1] = crc8(buff, length - 1);
    return length;
}

u8 tx_buff[255 + 5];
void data_package_send_test(void)
{
    u16 tx_len = 0;
    u8 cmd = 0x01;
    u8 data = 0x01;
    tx_len = data_package(tx_buff, cmd, &data, 1);
    //send_data(tx_buff, tx_len);
}

4.4 数据包解析demo

/**
 * @brief 解析
 * 
 * @param rx_data 收到的数据包
 * @param rx_len 收到的数据包长度
 * @param data 参数缓存指针
 * @param data_len 参数长度指针
 * @return u8 cmd命令
 */
u8 data_parse(u8 *rx_data, u16 rx_len, u8 **data, u8 *data_len)
{
    if(!rx_data || rx_len < 5){
        return 0xff; //指针异常或者数据包长度异常
    }
    u8 cmd = 0xff;
    u8 *buff = rx_data;
    u8 len = buff[2];
    if(len + 5 > rx_len){
        return 0xff; //参数长度异常
    }
    if(data_len){
        *data_len = len;
    }
    u8 crc = crc8(buff, 4 + len);
    u8 rx_crc = buff[4 + len];
    if(buff[0] == 0x34 && buff[1] == 0x12 && crc == rx_crc){
        if(len && data){ //命令后面有数据
            *data = (u8 *)malloc(len);
            memset(*data, 0x00, len);
            memcpy(*data, buff + 4, len);
        }
        cmd = buff[3];
    }

    return cmd;
}

/**
 * @brief demo
 * 
 * @param rx_data 收到的数据包
 * @param rx_len 收到的数据包长度
 */
void rx_data_parse(u8 *rx_data, u16 rx_len)
{
    u8 *data = NULL; //data_parse会给这个指针malloc内存,用完要释放掉
    u8 data_len = 0;
    u8 cmd = data_parse(rx_data, rx_len, &data, &data_len);
    switch(cmd){
        //todo
        default;
            break;
    }
    if(data){ //data_parse会给这个指针malloc内存,用完要释放掉
        free(data);
    }
}
  1. 耳机端的APP流程 flowchart
  2. 打开耳机的SPP功能

6.1 SPP功能开关

#define USER_SUPPORT_PROFILE_SPP                  1

6.2 SPP连接状态和数据接口

标准UUID

用到的回调函数注册接口

extern void spp_data_deal_handle_register(void (*handler)(u8 packet_type, u16 channel, u8 *packet, u16 size)); /*支持串口功能的数据处理接口*/

回调函数demo

void spp_data_handler(u8 packet_type, u16 ch, u8 *packet, u16 size)
{
    switch (packet_type) {
    case 1: //SPP连接成功
        log_info("spp connect\n");
        break;
    case 2: //SPP连接断开
        log_info("spp disconnect\n");
        break;
    case 7: //SPP收到数据
        log_info("spp_rx:");
        put_buf(packet,size);
        break;
    }
}
//蓝牙初始化成功后再调用注册接口注册回调函数
/*spp_data_deal_handle_register(spp_data_handler);*/

SPP发数据接口

/**
USER_CTRL_SPP_SEND_DATA命令有参数,参数会先存起来,
param_len是数据长度,param发送数据指针
返回0,表示准备成功,会PENDing发完才返回
返回3,表示上一包数据没发完
要求:size <= 512,data必须是全局或者静态数组
*/
user_send_cmd_prepare(USER_CTRL_SPP_SEND_DATA, size, data);

自定义UUID

修改自定义UUID
image 添加回调函数(无需注册,底层会直接调用)

int mutil_handle_data_deal(u8 local_id, u8 packet_type, u16 channel, u8 *packet, u16 size)
{
    printf("%s[packet_type = %d, packet:]\n",__func__, packet_type);
    put_buf(packet, size);
    switch (packet_type){
    case 0x01:
        log_info("SPP_CONNECT");
        break;
    case 0x02:
        log_info("SPP_DISCONNECT");
        break;
    case 0x07:
        log_info("RECEIVE_DATA");
        break;
    
    default:
        break;
    }
}

发数接口

extern int multi_spp_send_data(u8 local_cid, u8 rfcomm_cid,  u8 *buf, u16 len);
//调用方法
int user_spp_send_data(u8 *data, u16 len)
{
    return multi_spp_send_data(0x0A, 0, data, len);
}

可视化SDK接口

添加回调函数

//spp收数回调
void app_spp_recieve_callback(void *hdl, void *remote_addr, u8 *buf, u16 len)
{
    log_info("%s %x\n", __func__, (u32)hdl);
    put_buf(buf, len);
}

//spp连接状态回调
void app_spp_state_callback(void *hdl, void *remote_addr, u8 state)
{
    log_info("%s %x state %d\n", __func__, (u32)hdl, state);
}

//发数结束、spp空闲回调
void app_spp_send_wakeup_callback(void *hdl)
{
    log_info("%s %x\n", __func__, (u32)hdl);
}

在multi_protocol_common_callback_init函数中添加代码
注意:app_spp_hdl_alloc(u8 local_id);// local_id:0:标准SPP uuid;0xa:自定义SPP uuid,自定义id方法同普通SDK

    if (multi_protocol_spp_hdl == NULL) {
        multi_protocol_spp_hdl = app_spp_hdl_alloc(0);//0:标准SPP uuid;0xa:自定义SPP uuid
        if (multi_protocol_spp_hdl == NULL) { 
            log_info("multi_protocol_spp_hdl alloc err !!\n"); 
            return; 
        }
    }

    app_spp_recieve_callback_register(multi_protocol_spp_hdl, app_spp_recieve_callback);
    app_spp_state_callback_register(multi_protocol_spp_hdl, app_spp_state_callback);
    app_spp_wakeup_callback_register(multi_protocol_spp_hdl, app_spp_send_wakeup_callback);

image 发数接口

app_spp_data_send(multi_protocol_spp_hdl, data, len);
  1. 打开BLE功能

7.1 BLE功能开关

#define TCFG_USER_BLE_ENABLE                      1
/**********以下内容会由SDK根据宏定义修改,不了解的话严禁随意修改**********/
const int config_stack_modules = BT_BTSTACK_CLASSIC | BT_BTSTACK_LE;
const int config_btctler_modules        = BT_MODULE_CLASSIC | BT_MODULE_LE;
const int config_btctler_le_roles    = (LE_ADV | LE_SLAVE);
/**********以上内容会由SDK根据宏定义修改,不了解的话严禁随意修改**********/

7.2 BLE接口

接口文件:include_lib\btstack\le\ble_api.h
关键的初始化函数:void ble_profile_init(void)

7.3 BLE修改UUID服务

工具:make_gatt_services:https://kdocs.cn/l/cj0hbnJgvG3r
工具压缩包内有说明文档和demo
app开发profile服务UUID汇总(仅供参考,具体服务由APP定)

可视化SDK(支持两路RCSP的版本)修改UUID的方法.

通过上面的方法生成profile后,用下面的方法合入代码

//收数回调,底层蓝牙收到数据会调用,功能跟att_write_callback类似  
void bt_rcsp_custom_recieve_callback(u16 ble_con_hdl, void *remote_addr, u8 *buf, u16 len, uint16_t att_handle)
{
    printf("%s  %d\n", __func__, att_handle);
    put_buf(buf, len);
}

extern void *rcsp_server_ble_hdl;
extern void *rcsp_server_ble_hdl1;
extern int app_ble_profile_set(void *_hdl, const uint8_t *db);
app_ble_profile_set(NULL, NULL);
app_ble_profile_set(rcsp_server_ble_hdl, multi_profile_data);
app_ble_profile_set(rcsp_server_ble_hdl1, multi_profile_data);

image

7.4 BLE广播

常用的接口,demo可参考数传

/*************************************************************************************************/
/*!
 *  \brief      开关BLE广播.
 *
 *  \function   ble_cmd_ret_e ble_op_adv_enable(int enable).
 *
 *  \param      [in] enable     广播使能 :0(dis) or 1(en).
 *
 *  \return     see ble_cmd_ret_e.
 *
 *  \note       !!!注意:开广播前必现先配置好广播的参数.
 */
/*************************************************************************************************/
/* ble_cmd_ret_e ble_op_adv_enable(int enable) */
#define ble_op_adv_enable(enable)     \
    ble_user_cmd_prepare(BLE_CMD_ADV_ENABLE, 1, (int)enable)

/*************************************************************************************************/
/*!
 *  \brief      配置广播参数.
 *
 *  \function   ble_cmd_ret_e ble_op_set_adv_param(u16 adv_interval,u8 adv_type).
 *
 *  \param      [in] adv_interval     广播周期,Range: 0x0020 to 0x4000 (unit: 0.625ms).
 *  \param      [in] adv_type         广播类型,Range: 0x00 to 0x04.
 *  \param      [in] adv_channel      广播类型通道,range:Range: 0x01 to 0x07.
 *
 *  \return     see ble_cmd_ret_e.
 *
 *  \note       !!!注意:设置的时候必现在广播关闭的状态下.
 */
/*************************************************************************************************/
/* ble_cmd_ret_e ble_op_set_adv_param(u16 adv_interval,u8 adv_type) */
#define ble_op_set_adv_param(adv_interval,adv_type,adv_channel)     \
    ble_user_cmd_prepare(BLE_CMD_ADV_PARAM, 3, (int)adv_interval, (int)adv_type, (int)adv_channel)

/*************************************************************************************************/
/*!
 *  \brief      配置广播 Advertising Data内容.
 *
 *  \function   ble_cmd_ret_e ble_op_set_adv_data(u8 adv_len,const *u8 adv_data).
 *
 *  \param      [in] adv_len     adv 数据包长度,Range: 0x00 to 0x1f.
 *  \param      [in] adv_data    (全局变量地址),adv数据包地址.
 *
 *  \return     see ble_cmd_ret_e.
 *
 *  \note       !!!注意:设置的时候必现在广播关闭的状态下.
 */
/*************************************************************************************************/
/* ble_cmd_ret_e ble_op_set_adv_data(u8 adv_len,const *u8 adv_data) */
#define ble_op_set_adv_data(adv_len,adv_data)     \
    ble_user_cmd_prepare(BLE_CMD_ADV_DATA, 2, (int)adv_len, (void*)adv_data)

/*************************************************************************************************/
/*!
 *  \brief      配置广播 Scan Response Data内容.
 *
 *  \function   ble_cmd_ret_e ble_op_set_rsp_data(u8 rsp_len,const *u8 rsp_data).
 *
 *  \param      [in] rsp_len      rsp 包长度,Range: 0x00 to 0x1f.
 *  \param      [in] adv_data     (全局变量地址),rsp数据包地址.
 *
 *  \return     see ble_cmd_ret_e.
 *
 *  \note       !!!注意:设置的时候必现在广播关闭的状态下.
 */
/*************************************************************************************************/
/* ble_cmd_ret_e ble_op_set_rsp_data(u8 rsp_len,const *u8 rsp_data) */
#define ble_op_set_rsp_data(rsp_len,rsp_data)     \
    ble_user_cmd_prepare(BLE_CMD_RSP_DATA, 2, (int)rsp_len, (void*)rsp_data)

7.5 BLE连接状态和数据接口

  1. BLE连接状态 连接状态会反馈到cbk_packet_handler函数中
static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
{
    //......
    switch (packet_type) {
    case HCI_EVENT_PACKET:
        switch (hci_event_packet_get_type(packet)) {
        //......
        case HCI_EVENT_LE_META:
            switch (hci_event_le_meta_get_subevent_code(packet)) {
            //......
            case HCI_SUBEVENT_LE_CONNECTION_COMPLETE://BLE连接成功
            //......
            }
        //......
        case HCI_EVENT_DISCONNECTION_COMPLETE://BLE连接断开
        //......
}
  1. 耳机接收手机APP发过来的数据 手机APP发给耳机的数据最终会进入att_write_callback这个函数,用户需要在对应的UUID handle下接收处理数据
static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
/***以下是demo***/
    case ATT_CHARACTERISTIC_00000001_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE:
        log_info("\nTUYA msg receive, handle = 0x%x, size = %d\n", handle, buffer_size);
        receive_data(buffer, buffer_size);
        break;
/***以上是demo***/

可视化SDK(支持两路RCSP的版本)的收数接口

见:可视化SDK(支持两路RCSP的版本)修改UUID的方法
3. 手机APP获取耳机的数据 手机APP获取耳机数据的方式有两种:
第一种是靠手机APP自己来读(READ),需要在att_read_callback函数对应的UUID handle下回填数据

static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size)
/***以下是demo***/
    case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE:
        att_value_len = gap_device_name_len;
        if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) {
            break;
        }
        if (buffer) {
            memcpy(buffer, &gap_device_name[offset], buffer_size);
            att_value_len = buffer_size;
            log_info("\n------read gap_name: %s \n", gap_device_name);
        }
        return att_value_len;
/***以上是demo***/

第二种是靠耳机通知手机APP(NOTIFY),需要通知到指定的UUID handle

/***以下是demo***/
static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type)
{
    u32 ret = APP_BLE_NO_ERROR;

    if (!con_handle) {
        return APP_BLE_OPERATION_ERROR;
    }

    if (!att_get_ccc_config(handle + 1)) {
        log_info("fail,no write ccc!!!,%04x\n", handle + 1);
        return APP_BLE_NO_WRITE_CCC;
    }

    ret = ble_op_att_send_data(handle, data, len, handle_type);
    if (ret == BLE_BUFFER_FULL) {
        ret = APP_BLE_BUFF_FULL;
    }

    if (ret) {
        log_info("app_send_fail:%d !!!!!!\n", ret);
    }
    return ret;
}
//使用方法:
    att_set_ccc_config(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY);
    app_send_user_data(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE, data, len, ATT_OP_NOTIFY);
/***以上是demo***/

其他具体内容可以参看数传功能
8. 数传

8.1 SDK打开数传功能

  1. #define CONFIG_APP_BT_ENABLE APP功能必须定义这个宏
  2. #define TRANS_DATA_EN 1 使能数传功能
  3. #define CONFIG_DOUBLE_BANK_ENABLE 1
    控制单双备份OTA的宏。1是双备份,0是单备份。数传功能要做OTA的话只能也必须用双备份,升级文件使用db_update_data.bin。
  4. #define CONFIG_DB_UPDATE_DATA_GENERATE_EN 1 用于生成db_update_data.bin。
  5. #define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 1
    手机OTA升级必须打开这个宏,ufw只生成1份4K对齐的代码。
  6. .ini文件参考配置(一般耳机SDK已经配置好,这里只是给大家参考):
#if CONFIG_DOUBLE_BANK_ENABLE
BR22_TWS_DB = YES;//dual bank flash framework enable
FLASH_SIZE = CONFIG_FLASH_SIZE;//flash_size cfg
BR22_TWS_VERSION = 0; //default fw version
#if CONFIG_DB_UPDATE_DATA_GENERATE_EN
DB_UPDATE_DATA = YES; //generate db_update_data.bin
#endif
#if 1//CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE  //如果支持双备份升级默认4K对齐,否则会因为对齐方式不一致升级过程中将vm区域擦除
FORCE_4K_ALIGN = YES; // force aligin with 4k bytes
SPECIAL_OPT = 0;// only generate one flash.bin
#endif
#else
NEW_FLASH_FS = YES;//enable single bank flash framework
#endif //CONFIG_DOUBLE_BANK_ENABLE

8.2 相关文件

apps\common\third_party_profile\jieli\trans_data_demo\le_trans_data.c
apps\common\third_party_profile\jieli\trans_data_demo\le_trans_data.h
apps\common\third_party_profile\jieli\trans_data_demo\spp_trans_data.c
apps\common\third_party_profile\jieli\trans_data_demo\spp_trans_data.h
9. 杰理之家

9.1 SDK打开杰理之家的方法

  1. #define CONFIG_APP_BT_ENABLE APP功能必须定义这个宏
  2. #define RCSP_ADV_EN 1 杰理之家必须开这个宏,用于使能RCSP协议
  3. #define JL_EARPHONE_APP_EN 1 需要使用杰理之家APP的话,必须开这个宏
  4. #define BT_CONNECTION_VERIFY 0
    是否支持杰理之家加密认证:0是支持,1是不支持
  5. #define RCSP_UPDATE_EN 1
    可选是否支持rcsp升级(杰理之家OTA、RCSP OTA)
  6. #define CONFIG_DOUBLE_BANK_ENABLE 1
    可选。控制单双备份OTA的宏。1是双备份,0是单备份。如果是512K的芯片只能用单备份了,升级文件使用update.ufw。
  7. #define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 1
    手机OTA升级必须打开这个宏,ufw只生成1份4K对齐的代码。
  8. .ini文件参考配置(一般耳机SDK已经配置好,这里只是给大家参考):
#if CONFIG_DOUBLE_BANK_ENABLE
BR22_TWS_DB = YES;//dual bank flash framework enable
FLASH_SIZE = CONFIG_FLASH_SIZE;//flash_size cfg
BR22_TWS_VERSION = 0; //default fw version
#if CONFIG_DB_UPDATE_DATA_GENERATE_EN
DB_UPDATE_DATA = YES; //generate db_update_data.bin
#endif
#if 1//CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE  //如果支持双备份升级默认4K对齐,否则会因为对齐方式不一致升级过程中将vm区域擦除
FORCE_4K_ALIGN = YES; // force aligin with 4k bytes
SPECIAL_OPT = 0;// only generate one flash.bin
#endif
#else
NEW_FLASH_FS = YES;//enable single bank flash framework
#endif //CONFIG_DOUBLE_BANK_ENABLE

9.2 相关文件

带rcsp的文件,主要有:
apps\common\third_party_profile\jieli\JL_rcsp\bt_trans_data\le_rcsp_adv_module.c
apps\common\third_party_profile\jieli\JL_rcsp\bt_trans_data\le_rcsp_adv_module.h
apps\common\third_party_profile\jieli\JL_rcsp\bt_trans_data\rcsp_adv_spp_user.c
apps\common\third_party_profile\jieli\JL_rcsp\adv_rcsp_protocol\rcsp_adv_bluetooth.c

9.3 DEMO 程序

杰理之家_AC695N_soundbox_sdk_release_3.0.5

9.4 APP连接操作

操作视频
10. 涂鸦 做好的demo:蓝牙音频APP相关应用.otl

10.1 SDK打开涂鸦功能

  1. #define CONFIG_APP_BT_ENABLE APP功能必须定义这个宏
  2. #define TUYA_DEMO_EN 1 使能涂鸦功能
  3. #define CONFIG_DOUBLE_BANK_ENABLE 1
    控制单双备份OTA的宏。1是双备份,0是单备份。涂鸦要做OTA的话只能也必须用双备份,升级文件使用db_update_data.bin。
  4. #define CONFIG_DB_UPDATE_DATA_GENERATE_EN 1 用于生成db_update_data.bin。
  5. #define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 1
    手机OTA升级必须打开这个宏,ufw只生成1份4K对齐的代码。
  6. .ini文件参考配置(一般耳机SDK已经配置好,这里只是给大家参考):
#if CONFIG_DOUBLE_BANK_ENABLE
BR22_TWS_DB = YES;//dual bank flash framework enable
FLASH_SIZE = CONFIG_FLASH_SIZE;//flash_size cfg
BR22_TWS_VERSION = 0; //default fw version
#if CONFIG_DB_UPDATE_DATA_GENERATE_EN
DB_UPDATE_DATA = YES; //generate db_update_data.bin
#endif
#if 1//CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE  //如果支持双备份升级默认4K对齐,否则会因为对齐方式不一致升级过程中将vm区域擦除
FORCE_4K_ALIGN = YES; // force aligin with 4k bytes
SPECIAL_OPT = 0;// only generate one flash.bin
#endif
#else
NEW_FLASH_FS = YES;//enable single bank flash framework
#endif //CONFIG_DOUBLE_BANK_ENABLE

10.2 相关文件

带tuya的文件,主要有:
apps\earphone\tuya\tuya_demo.c
apps\earphone\tuya\tuya_demo.h
apps\earphone\tuya\tuya_app.c
apps\common\third_party_profile\tuya_protocol\app\demo\tuya_ble_app_demo.c
apps\common\third_party_profile\tuya_protocol\app\demo\tuya_ble_app_demo.h
11. ANCS

11.1 SDK打开ANCS功能

(以下以jl701n_soundbox_release_v1.2.1做为例子)

//ANCS 需要使能BLE 
//相关文件:apps\soundbox\board\br28\board_jl701n_demo\board_jl701n_demo_cfg.h
#define TCFG_USER_BLE_ENABLE                      1   //BLE功能使能


//需要打开ANCS的使能
//相关文件:apps\common\third_party_profile\jieli\trans_data_demo\le_trans_data.c
//添加需要的头文件
#include "ble_user.h"

//ANCS profile enable
#define TRANS_ANCS_EN                     1

//相关文件:apps\soundbox\log_config\lib_btctrler_config.c
const uint64_t config_btctler_le_features = LE_ENCRYPTION;

//相关文件:apps\common\third_party_profile\jieli\trans_data_demo\le_trans_data.c
const int config_le_sm_support_enable = 1; //是否支持加密配对

jl701n_soundbox_release_v1.2.1:替换库文件 :【金山文档】 添加ANCS_jl701n_soundbox_release_v1.2.1

  1. #define CONFIG_APP_BT_ENABLE APP功能必须定义这个宏
  2. #define TRANS_DATA_EN 1 使能数传功能
  3. #define CONFIG_DOUBLE_BANK_ENABLE 1
    控制单双备份OTA的宏。1是双备份,0是单备份。数传功能要做OTA的话只能也必须用双备份,升级文件使用db_update_data.bin。
  4. #define CONFIG_DB_UPDATE_DATA_GENERATE_EN 1 用于生成db_update_data.bin。
  5. #define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 1
    手机OTA升级必须打开这个宏,ufw只生成1份4K对齐的代码。
  6. .ini文件参考配置(一般耳机SDK已经配置好,这里只是给大家参考):
#if CONFIG_DOUBLE_BANK_ENABLE
BR22_TWS_DB = YES;//dual bank flash framework enable
FLASH_SIZE = CONFIG_FLASH_SIZE;//flash_size cfg
BR22_TWS_VERSION = 0; //default fw version
#if CONFIG_DB_UPDATE_DATA_GENERATE_EN
DB_UPDATE_DATA = YES; //generate db_update_data.bin
#endif
#if 1//CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE  //如果支持双备份升级默认4K对齐,否则会因为对齐方式不一致升级过程中将vm区域擦除
FORCE_4K_ALIGN = YES; // force aligin with 4k bytes
SPECIAL_OPT = 0;// only generate one flash.bin
#endif
#else
NEW_FLASH_FS = YES;//enable single bank flash framework
#endif //CONFIG_DOUBLE_BANK_ENABLE

11.2 相关文件

apps\common\third_party_profile\jieli\trans_data_demo\le_trans_data.c
apps\common\third_party_profile\jieli\trans_data_demo\le_trans_data.h
apps\common\third_party_profile\jieli\trans_data_demo\spp_trans_data.c
apps\common\third_party_profile\jieli\trans_data_demo\spp_trans_data.h

11.3 demo程序

系列链接
AC695N【金山文档】 ac695n_ANCS测试_soundbox_sdk_3.1.0
  1. 其他第三方APP(APP_PROTOCOL) 公版已实现的一些第三方APP功能

12.1 SDK打开其他第三方APP功能

  1. #define CONFIG_APP_BT_ENABLE APP功能必须定义这个宏
  2. #define AI_APP_PROTOCOL 1
  3. 修改app_protocol_api.h
#define APP_PROTOCOL_GMA_CODE       0/*阿里天猫协议接口ID*/
#define APP_PROTOCOL_AMA_CODE       0/*亚马逊的AMA协议接口ID*/
#define APP_PROTOCOL_DMA_CODE       0/*百度DMA协议接口ID*/
#define APP_PROTOCOL_TME_CODE       0/*腾讯酷狗TME协议接口ID*/
#define APP_PROTOCOL_MMA_CODE       0/*小米MMA协议接口ID*/
#define APP_PROTOCOL_REALME_CODE    0/*oppo真我的协议接口ID*/
#define APP_PROTOCOL_GFPS_CODE      1/*谷歌快对的协议接口ID*/
#define APP_PROTOCOL_NECM_CODE      0/*网易云音乐协议接口ID*/
  1. #define CONFIG_DOUBLE_BANK_ENABLE 1
    控制单双备份OTA的宏。1是双备份,0是单备份。APP要做OTA的话只能也必须用双备份,升级文件使用db_update_data.bin。
  2. #define CONFIG_DB_UPDATE_DATA_GENERATE_EN 1 用于生成db_update_data.bin。
  3. #define CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE 1
    手机OTA升级必须打开这个宏,ufw只生成1份4K对齐的代码。
  4. .ini文件参考配置(一般耳机SDK已经配置好,这里只是给大家参考):
#if CONFIG_DOUBLE_BANK_ENABLE
BR22_TWS_DB = YES;//dual bank flash framework enable
FLASH_SIZE = CONFIG_FLASH_SIZE;//flash_size cfg
BR22_TWS_VERSION = 0; //default fw version
#if CONFIG_DB_UPDATE_DATA_GENERATE_EN
DB_UPDATE_DATA = YES; //generate db_update_data.bin
#endif
#if 1//CONFIG_ONLY_GRENERATE_ALIGN_4K_CODE  //如果支持双备份升级默认4K对齐,否则会因为对齐方式不一致升级过程中将vm区域擦除
FORCE_4K_ALIGN = YES; // force aligin with 4k bytes
SPECIAL_OPT = 0;// only generate one flash.bin
#endif
#else
NEW_FLASH_FS = YES;//enable single bank flash framework
#endif //CONFIG_DOUBLE_BANK_ENABLE
  1. 设计说明文档 杰理第三方APP通信协议设计说明文档.pdf

12.2 相关文件

app_protocol开头的文件,主要有:
apps\common\third_party_profile\interface\app_protocol_api.c
apps\common\third_party_profile\interface\app_protocol_api.h
apps\common\third_party_profile\interface\app_protocol_common.c
13. 其他资料 app开发profile服务UUID汇总
升级相关.otl
固件升级介绍.md
杰理所有升级方式汇总
蓝牙音频APP相关应用.otl
APP自定义按键的demo.otl

BLE速率提升:

BLE从机修改MTU大小
IOT(BLE-AD-MCU)资料链接入口汇总.otl
14. 认证码烧录

应用场景

如果您需要在烧写固件程序的同时烧写认证码(序列号, 三元组) 等第三方数据, 可参考本
文步骤导入认证码到烧写器中。
认证码数据需要使用 csv 文件方式导入, 建议认证码最大长度不超过 127bytes。
认证码烧写步骤说明.pdf
15. APP问题排查调试方法

15.1 连接类问题

排查BLE UUID、SPP UUID是否正确
排查BLE广播数据是否正确
排查连接上之后,上报数据是否符合协议要求

15.2 APP界面显示异常问题

排查耳机上报数据是否符合协议要求
排查耳机是否正确按照协议解析手机下发的数据
排查耳机是否给手机回复正确数据

15.3 耳机功能异常问题

排查耳机是否正确按照协议解析手机下发的数据
TWS的场景要将主机收到的数据同步给从机(也可由主机解析后再研判是否需要主从同步执行)
16. 各种APP常见问题汇总

  1. 杰理之家
    1. BLE和EDR相同地址导致OTA升级失败问题 imageimage
    2. AC695N_soundbox_sdk_release_3.0.5/AC695N_soundbox_sdk_relea se_3.0.6 无法连接问题 需要把SPP打开
      image

c.RCSP选择连接方式

image

  1. 涂鸦
    1. 耳机主从切换会导致APP断连,目前无法解决,BLE不支持主从切换
    2. 唤醒siri爆ram image
    3. 双备份flash空间优化
    4. 提示音使用aac格式,关掉wts image
    5. VM改为8K(改了之后要先强制升级) image
    6. 关闭ble加密配对 image
    7. 提示音使用单备份方案(提示音不放在代码区) 注意:此方法提示音不放在代码区,因此手机APP双备份升级时无法更新提示音,需要更新提示音时只能使用串口升级
      此方法把提示音放在flash的一个独立区域
      修改提示音路径
      image download.bat去掉 tone.cfg
      image 修改ini文件(或者isd_config_rule.c)
      image TON_ADR值确定方式:
      双备份flash结构如下
uboot
code1
code2
VM
BTIF
其他预留区自定义区域1
自定义区域2
......
4K预留区
  1. 假设“其他预留区“中的自定义区域个数为0,也就是自定义预留区只需要用来放提示音,那么TON_ADR = flash大小 - 4K - TON_LEN。 举例:假设实际flash为1MB(1MB = 1024KB = 1024 * 1024byte = 1048576byte = 0x100000byte),tone.cfg的大小为33K(4K对齐后占用36K空间),则
    TON_ADR=0x100000-4K-36K
    =0x100000-0x1000-0x9000
    =0xF6000
  2. 假设“其他预留区“中已有其他区域,比如开了ANC之后还有ANC的区域(占用4K),则TON_ADR = flash大小 - 4K - TON_LEN - 其他区域(ANC区域)大小。 举例:假设实际flash为1MB(1MB = 1024KB = 1024 * 1024byte = 1048576byte = 0x100000byte),tone.cfg的大小为33K(4K对齐后占用36K空间),ANC的区域大小4K,则
    TON_ADR=0x100000-4K-36K-4K
    =0x100000-0x1000-0x9000-0x1000
    =0xF5000
    4. 重置的demo
void local_tuya_key_func_reset(void)
{
    u8 key_value_record[6][6] = {0};
    key_table_l[0][0] = tuya_key_event_swith(0);
    key_table_l[0][1] = tuya_key_event_swith(1);
    key_table_l[0][4] = tuya_key_event_swith(2);
    key_table_r[0][0] = tuya_key_event_swith(0);
    key_table_r[0][1] = tuya_key_event_swith(1);
    key_table_r[0][4] = tuya_key_event_swith(2);
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 6; j++) {
            key_value_record[i][j] = key_table_l[i][j];
            key_value_record[i + 3][j] = key_table_r[i][j];
        }
    }
    syscfg_write(TUYA_SYNC_KEY_INFO, key_value_record, sizeof(key_value_record));
}

//用这个函数重置
void tuya_reset(void)
{
    if(tws_api_get_role() == TWS_ROLE_MASTER){
        tuya_ble_gap_disconnect();
    }
    user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);
    tuya_ble_device_factory_reset();
    local_tuya_key_func_reset();
    char eq_info[11] = {0};
    syscfg_write(CFG_RCSP_ADV_EQ_DATA_SETTING, eq_info, 11);
    u8 name[LOCAL_NAME_LEN];
    memset(name, 0x00, sizeof(name));
    syscfg_read_string(CFG_BT_NAME, name, sizeof(name), 0);
    syscfg_write(CFG_BT_NAME, name, LOCAL_NAME_LEN);
    void sys_enter_soft_poweroff(void *priv);
    sys_timeout_add((void *)1, sys_enter_soft_poweroff, 1000);
}

以上接口可以放在按键那里,也可以放在涂鸦指令(如果有的话)那里
image 代码demo见:蓝牙音频APP相关应用.otl
3. 酷狗 1. 700N合入新的PID和信息组 添加下面的代码到app_protocol_api.c,库里面会调用。

#define ECHD_KeyX "15207009984421a6586f9fc3fe7e4329d2809ea51125f8ed" //ECHD_KeyX
#define ECHD_KeyY "b09d42b81bc5bd009f79e4b59dbbaa857fca856fb9f7ea25" //ECHD_Keyy
#define TME_PID  "1000"
#define TME_BID  "0001"

static const u8 key_x[] = {ECHD_KeyX};
static const u8 key_y[] = {ECHD_KeyY};

const char * Get_TME_PubKey_x()
{
    put_buf(key_x, sizeof(key_x));
    return key_x;
}

const char * Get_TME_PubKey_y()
{
    put_buf(key_y, sizeof(key_y));
    return key_y;
}

u32 kugou_pid = 0;
u8 *Get_TME_pid()
{
    kugou_pid = atoi(TME_PID);
    printf("%s  %d\n", __func__, kugou_pid);
    return (u8 *)&kugou_pid;
}

u32 kugou_bid = 0;
u8 *Get_TME_bid()
{
    u32 temp = 0;
    temp = atoi(TME_BID);
    kugou_bid = temp & 0xffff;
    printf("%s  %d\n", __func__, kugou_bid);
    return (u8 *)&kugou_bid;
}

  1. 百度

  2. 小爱同学

  3. 天猫精灵

  4. 亚马逊

  5. Realme Link

  6. 谷歌快连

  7. 网易云音乐

本文档包含以下子页面

  • 杰理第三方APP通信协议设计说明文档
  • 认证码烧写步骤说明
Prev
蓝牙音频APP相关应用
Next
蓝牙音频系列-硬件设计指南