JL7094系列-入门到进阶开发指导
📎 原始文档:https://www.kdocs.cn/l/clL0ShkYC8Ft JL7094系列-入门到进阶开发指导
第1章 入门指南
1.1 杰理开发资料获取介绍
1.1.1 软件SDK开发包获取
此系列芯片软件使用JLStudio工具开发;
JLStudio工具获取途径:通过杰理方案商或者深圳杰理公司助理获取;
下载工具后请详细阅读工具使用说明:
芯片SDK需要绑定账号使用,账号以及分支获取途径:通过杰理方案商或者深圳杰理公司助理获取
SDK分支如下:
1.1.2 原理图、规格书、芯片用户手册获取
通过杰理方案商或者深圳杰理公司助理获取
1.1.3 硬件烧录&下载开发工具获取
通过杰理方案商获取
1.1.4 烧录加密KEY文件获取
通过杰理方案商获取
1.1.5 工程样片(芯片)获取
通过杰理方案商获取
1.1.6 量产芯片购买说明
通过杰理方案商获取
1.2 软件开发环境搭建
1.2.1 Windocs 系统下安装和编译
1.2.2 Linux 系统下安装和编译
1.2.3 杰理工具链相关说明
1.3 硬件开发板/demo板使用介绍
1.3.1 开发板/demo板使用说明
其他IO口以及外设使用根据丝印内容接线即可;
1.3.2 开发板/demo板使用视频讲解
暂无;
1.4 固件烧录&下载介绍
1.4.1 下载目录&下载文件介绍

jl_isd.bin //代码以及资源文件合并后文件,一般说代码文件大小指此文件大小
jl_isd.fw //烧录文件,用于一拖二/一拖八工具烧录程序使用
update.ufw //升级文件,用于日常项目升级程序使用
stream.bin //音效文件
tone_zh.cfg //提示音文件
ota.bin //单备份升级使用的加载的代码文件
cfg_tool.bin //工具生成文件,一般包括蓝牙名字,蓝牙功率等参数配置
1.4.2 固件加密介绍
一般固件使用key文件方式加密,带key的芯片只有加入key文件编译后的下载文件才能下载,所以下载程序报key错误情况下,请加入方案商的key文件编译后生成新的下载文件后下载。
编译配置key文件方式:
1.4.3 一拖二工具烧录介绍
芯片烧录程序使用,一般用于方案商烧录芯片出货使用,用户手册:
1. 杰理科技一拖二烧录器用户手册 — JL Project Documentation
1.4.4 一拖八工具烧录介绍
整机烧录程序使用,一般用于产线更新程序使用,接线使用USB口类似强制升级工具接线,建议搭配治具使用,用户手册:
2. 杰理科技一拖八烧录器用户手册 — JL Project Documentation
1.4.5 强升(下载)工具介绍
烧录方式:
- 所有挡位都不拨的情况下,接到demo板上后,按下载器按键,绿灯闪烁->绿灯灭,则进入下载状态;
- 一档开启后,直接接到demo板上后,绿灯闪烁->绿灯灭,则进入下载状态;
其他强制升级工具使用说明请详细阅读此文档:
强制升级工具说明文档.docx
1.4.6 蓝牙测试盒升级固件介绍
用于无线或者有线串口升级整机使用,用户手册:
3. 杰理科技一拖二蓝牙测试盒用户手册 — JL Project Documentation
1.4.7 手机APP OTA 升级介绍
第2章 硬件调试
2.1 XX系列硬件设计指南
2.2 底噪调试
2.3 距离调试
2.4 静电认证测试
1)静电的解释
静电介绍.otl
2)静电测试及整改方法
静电测试及整改方法-20220706.pdf
2.5 常规设备使用说明
第3章 声学相关开发
3.1 声学相关基础知识
3.1.1 频响
3.1.2 腔体
3.1.3 EQ
3.2 音箱产品声学调试
3.2.1 不带话筒的音箱声学调试
3.2.2 带有线话筒的音箱声学调试
3.2.3 带无线话筒的音箱声学调试
3.3 耳机产品声学调试
3.3.1 TWS 耳机声学调试
3.3.2 OWS 耳机声学调试
3.3.3 ENC声学调试
3.3.4 ANC声学调试
第4章 SDK开发说明
4.1 SDK架构说明
4.1.1 SDK总体架构说明
4.1.2 蓝牙模式子架构说明
4.1.2 音乐模式子架构说明
4.1.2 录音模式子架构说明
4.1.2 混响模式子架构说明
4.1.2 收音模式子架构说明
4.1.2 PC模式子架构说明
4.1.2 RTC时钟模式子架构说明
4.2 软件debug说明
4.2.1 打印开启设置说明
4.2.1.1 打印开启

4.2.1.2 开启断言打印

4.2.1.3 开启复位源打印

4.2.1.4 开启库打印

4.2.1.5 开启蓝牙协议打印
打开库打印的同时,针对遇到问题的大概问题点,开启对应的蓝牙协议打印:
4.2.1.6 开启系统时间打印

4.2.1.7 开启内存打印
函数 mem_stats(); 需打开库打印(库打印打开参考上面修改)
[HEAP_MEM]Current free heap 124904 bytes, minimum ever free heap 124700 bytes, physics memory size 100480 bytes
physics memory size %d bytes ,这个表示现在剩下可用的物理内存
4.2.1.8 cpu占比信息、堆栈
cpu占比的信息,堆栈
config_system_info = 1; //开启,若没有该变量可以不理会
void os_system_info_output(void); //输出信息,可以定时器5秒调用一次
void os_system_info_reset(void); //重置运行时间
// 可视化SDK,周期调用以下函数输出任务信息
// 具体可参考audio_debug.h audio_debug.c文件
void task_info_output(int size);
task_info_output(0);
注意:如果程序使用task_create 函数创建任务里面会默认把任务加进记录,输出能看到对应的任务输出
task_create(app_task_handler, NULL, "app_core");
如果使用 os_task_create 是没有把该任务加进记录的此时需要调用多一条函数 :
void task_info_add(TaskHandle_t task) 把任务加进记录
void task_info_add(TaskHandle_t task)
//demo
task_info_add(os_task_get_handle("my_task")); //my_task 为创建的任务
4.2.1.9 生成反汇编文件

4.2.2 死机问题debug
参考以下文档:
软件调试方法.otl
4.3 蓝牙模式
4.3.1 EDR经典蓝牙基础知识介绍
CSDN或者AI搜索,建议不懂先deepseek或者其他AI软件搜索,比看文档快。
比如使用腾讯元宝:

4.3.2 BLE基础知识介绍
建议自行AI搜索或者CSDN查找文档;
4.3.3 Auracast基础知识介绍
简述:使用BLE广播的方式将LC3/LC3plus编解码音频发送或者接收;
1->n是BIS广播,单向;
1->(2-31)固定最大数量,可能是CIS广播,带双向通信;
以下是AI回复:
一、Auracast技术概述
Auracast是蓝牙技术联盟(Bluetooth SIG)在2022年推出的全新广播音频功能,基于蓝牙5.2核心规范引入的LE Audio(低功耗音频)技术
。这项技术允许单个音频发射源向范围内无限数量的接收设备广播高质量音频流,无需传统蓝牙的配对过程。
核心特点:
- 一对多广播:与一对一传统蓝牙配对不同,Auracast对接收设备数量没有理论限制,仅受发射器范围限制
- 高质量音频:支持未压缩的CD音质传输,采用LC3/LC3plus编解码器,相比传统蓝牙的SBC/AAC有显著提升
- 低延迟同步:通过LE Audio的同步通道(ISOC)协议确保多设备播放同步,延迟显著低于传统蓝牙
- 低功耗:基于BLE(蓝牙低功耗)协议优化,延长设备电池寿命
- 灵活访问控制:支持开放广播和加密私人广播两种模式
二、技术原理与工作方式
Auracast的技术实现基于蓝牙LE Audio的三大创新机制:
- 广播式传输机制:
- 使用蓝牙LE的3个广播信道(37、38、39),结合跳频技术减少干扰
- 类似于无线电广播,音频源通过广播信道发送音频流,兼容接收器可自由接入
- 同步播放机制:
- 采用ISOC(同步通道)协议确保所有接收设备在同一时间戳解码音频数据
- 同步误差通过公式Δt ≤ 1/(2fₘₐₓ)控制(fₘₐₓ为音频最高频率)
- 高效编码技术:
- 使用LC3(低复杂度通信编解码器),在保证音质的同时显著降低比特率和延迟
- 相比传统蓝牙音频编解码器,LC3在相同音质下可节省50%带宽 工作流程:
- 音频源编码音频流
- 通过广播信道发送
- 接收设备同步解码
- 多设备同步播放
4.3.4 TWS 基础知识介绍
4.3.5 TWS 连接机制
4.3.5.1 TWS 配对接口
4.3.5.2 TWS 回连接口
4.3.5.3 TWS 其他相关接口
4.3.6 BLE开发相关接口
开发BLE应用前可以先找下代码内是否已经有开发好的demo应用:
自定义的一些APP开发使用可以参考 custom_protocol.c文件内的ble部分应用接口,以下以此文件内接口做简单的应用介绍:
//BLE广播包数据填充
static u8 custom_fill_adv_data(u8 *adv_data)
//BLE扫描响应数据填充
static u8 custom_fill_rsp_data(u8 *rsp_data)
//连接事件回调
custom_cbk_packet_handler
//读写事件回调
custom_att_read_callback/custom_att_write_callback
//发送ble数据接口
custom_demo_ble_send,实际调用接口:app_ble_att_send_data
//BLE服务功能
custom_demo_profile_data
详细BLE应用讲解:
doc/software/蓝牙/BLE开发流程.md · 珠海杰理科技FAE/IOT-AC630N - Gitee.com
4.3.7 SPP开发相关接口
参考 custom_protocol.c文件内的接口使用,接口较简单,不做具体说明;
4.3.8 Auracast开发相关接口
功能开启,使能le_audio应用,角色固定和不固定看实际项目需求,其他项建议不修改:
BIS参数配置,不了解配置项意义以及影响的情况下,不建议做修改,按照每个版本默认的配置进行使用,不用修改跟下图一致;
代码使用接口说明:
APP_MSG_LE_BROADCAST_SW //程序参考使用消息,用于广播开关切换使用
app_auracast_switch(); //广播开关实际调用到的接口
app_auracast_open(); //广播开启api,未初始化前不能调用,详情见实际代码调用方式
is_auracast_as_source();//广播开机角色判断,可根据需求自行修改,比如程序默认是蓝牙
//播放歌曲情况下是主机,也可自行修改为比如链接手机的就是主机不需要播放歌曲
app_auracast_sink_close();//广播接收关闭,详情见实际代码调用方式
app_auracast_source_close();//广播发送关闭,详情见实际代码调用方式
PADV字段:用于主机->从机数据传输,无数量限制
//1. TX 端更新的接口,下面是个更新的例子,source open后,用定时器触发
//建议使用数据是 LTV 格式,建议用 0xFF 字段
extern int auracast_source_update_padv_data(u8 *data, u8 len);
u8 tttt_cnt = 0;
void tttt(void *priv)
{
printf("tttt %d", tttt_cnt);
u8 dddata[3];
tttt_cnt++;
dddata[0] = 2;
dddata[1] = 0xFF;
dddata[2] = tttt_cnt;
auracast_source_update_padv_data(dddata, 3);
}
//2、RX 端实时接收的接口,数据是 LTV 格式,需要解析出来 0xFF 字段
case AURACAST_SINK_PADV_REPORT_EVENT:
log_info(" AURACAST_SINK_PADV_REPORT_EVENT");
//默认存在46byte偏移,即主机不发送数据的情况下会有46byte数据,自定义数据解析注意偏移后再读(可能随版本改变)
put_buf(packet, length);
break;
4.3.9 PAWR功能开发相关接口
一般用于auracast 主机<->从机的双向交互,存在数量限制,1.2.0-SDK限制:2*5
使能:
开启auracast功能后,配置以下两处:
开启以上两处后,auracast主机和从机链接后,PAWR协议也会链接上,能直接看到TX和RX的接收数据回调打印;
具体使用接口:
TX接口:
void app_speaker_start_pawr(void); //初始化pawr ap
void app_speaker_stop_pawr(void); //关闭pawr ap
static void ble_pawr_tx_data_callback(uint8_t *packet, uint16_t size);
//收到 Receiver 的rsp响应数据回调
static void ble_pawr_tx_update_adv_data(const uint8_t *data, uint16_t len);
//更新pawr ap周期广播字段数据
RX接口:
void app_speaker_create_pawr_sync(void); //pawr rx初始化(完成周期广播同步后调用)
void app_speaker_cancle_pawr_sync(void); //pawr rx close
static void app_speaker_pawr_scan_callback(uint8_t *packet, uint16_t size);
//rx接收回调
void app_speaker_set_pa_response_data(const uint8_t *data, uint8_t data_len);
//更新receiver 响应内容
默认发送数据数组:
4.3.10 其他常用蓝牙相关接口
4.4 音乐模式(播TF、U盘音频)
4.4.1 文件系统基础知识介绍
4.4.2 文件解码接口
4.4.3 音乐模式其他常用接口
4.5 录音模式
4.5.1 录音功能基础知识介绍
4.5.2 录音模式其他常用接口
4.6 混响模式
4.6.1 混响功能基础知识介绍
4.6.2 录音模式其他常用接口
4.7 FM模式
4.7.1 FM功能基础知识介绍
4.7.2 FM模式其他常用接口
4.8 PC模式
4.8.1 PC功能基础知识介绍
4.8.2 PC模式其他常用接口
4.9 RTC时钟模式
4.9.1 RTC时钟功能基础知识介绍
4.9.2 RTC时钟模式其他常用接口
第5章 普通外设协议
5.1 UART
5.2 SPI
5.3 TIMER
5.4 GPIO
5.5 PWM
5.6 SD&USB协议
SD卡相关:
程序配置位置:
其他相关知识:
SD卡相关.otl
USB协议:
PC相关应用.otl
其他参考文档:
SD&U盘.otl
5.7 GPCNT(时钟脉冲计数器)
参考lpctmu_hw.c文件内相关接口
第6章 音频外设协议
6.1 ADC&LADC
规格参数:
6.2 IIS
程序配置位置:
IIS音频接口应用.otl
6.3 HDMI(ARC)
6.4 SPDIF
程序配置位置:
SPDIF模式相关(HDMI_ARC、光纤、同轴).otl
6.5 PDM LINK
第7章 第三方算法导入
7.1 第三方算法接入
7.2 第三方算法授权
7.3 第三方算法烧录
第8章 认证测试指南
8.1 FCC 认证
8.2 BQB 认证
程序配置对应认证模式导出对应程序去过认证:
8.3 BQB_PROFILE 认证
根据开启的蓝牙协议去过对应的认证项:
协议版本参考此文档,注意要过6.0版本认证
蓝牙参数整理.xlsx
使用认证程序以及遇到问题的修改点:
【金山文档 | WPS云文档】 BQB profile 测试中常遇到的问题点汇总
https://www.kdocs.cn/l/chjD3kml5NTE
8.4 Hi-Res 小金标认证


第9章 UI开发
9.1 数码管
9.2 断码屏
9.3 LCD黑白点阵屏
9.4 TFT 彩屏
第10章 APP 相关开发
10.1 杰理之家APP
10.2 杰理OTA APP
10.3 杰理文件传输APP
10.4 小度APP
第11章 升级相关开发
11.1 维持IO电平跳转升级
11.2 外设串口升级
11.3 杰理测试盒串口&无线升级
11.4 手机OTA升级( BLE RCSP协议)
11.5 双备份升级开发
第12章 功能模块演示
12.1 功能模块演示案例汇总
第13章 产测(生产&测试)
13.1 量产烧录说明
13.2 杰理蓝牙测试盒产测说明
13.3 蓝牙RF产测说明
13.4 音频产测说明
13.5 ANC 产测说明
13.6 ENC 产测说明
13.7 生产安全规范说明
第14章 FAQ环节
14.1 补丁汇总
14.2 软件常见问题处理汇总
第二次通话存在回声问题-lcp 解决方式:更新到最新版本解决;
IIS-48K-24BIT通话出现死机问题-lcp 此分支前对比以下文件修改,此版本之后无需修改:
【金山文档 | WPS云文档】 audio_cvp_ref_task-patch-1.0.0-0010(其他版本对比增加的代码修改)
https://www.kdocs.cn/l/ciF9DUjDLlau蓝牙高码率播放歌曲同时开启auracast存在卡顿问题处理-lcp 此处 | BIT(28):
动态调整auracast-rtn次数;修改频偏方式 br52只能补正的频偏,无法补负的频偏。传入的值要是10的倍数,实际频偏传参之前做好四舍五入再传入。
extern void bt_osc_offset_set(s32 offset);
extern void bt_osc_offset_save();
bt_osc_offset_set(30); //单纯设置的话需要在蓝牙初始化结束后;
bt_osc_offset_save();
//bt_osc_offset_set是一个累加的接口,并非设置参数的接口:
bt_osc_offset_set(10);
bt_osc_offset_set(20);
==
bt_osc_offset_set(30);
//然后这个接口只能设置正的频偏,但设置正的频偏后运行设置负的参数来降低正的频偏的数值,比如:
bt_osc_offset_set(30);
bt_osc_offset_set(-10);
==
bt_osc_offset_set(20);
//所以设置频偏的时候一定要记得之前累加的数值,累加的数值不能是负数
//保存接口说明,在bt_osc_offset_set接口设置到需要的频偏时调用,保存当前设置的频偏
bt_osc_offset_save();
bt_osc_offset_set设置的参数实际是对应底层的挡位,所以设置后需要再测试频偏,根据测试的实际频偏再去修改参数,实际生产前需要找一批板子做批量的验证,再去直接设置代码的参数;
bt_osc_offset_save能保存的参数个数是有限制的,5个以内,超过数量需要全擦升级后才能继续保存,建议是每次测试后还需要修改的话全擦升级后再去修改!!!
直接设置参数:
串口等方式一台一台设置参数的话:
//使用bt_osc_offset_set去设置频偏
//切记这个接口是累加的接口,可以不断调用+10接口直到频偏符合要求:
bt_osc_offset_set(10);
//保存接口说明,在bt_osc_offset_set接口设置到需要的频偏时调用,保存当前设置的频偏
bt_osc_offset_save();
检测是否已经有写入过trim值方式:
一拖二烧录时增加REF-TRIM步骤,优化ADC检测误差 使用SDK版本:008版本及之后版本,一般用于分压到ADC口然后检测电池电量的方式;
程序修改:
需要烧录器上层板以及一拖二工具版本支持,详细操作步骤见此文档:
JL709N,AC689N ADC校准使用说明.doc 旧版本,请联系杰理方案商/工程助理拿最新的工具图选择芯片FT阶段的trim数值做VBAT采集方式 注意:仅适用于JL6894A/JL7094A带JL的芯片 且 直接采集VBAT电压作为检测电量的方式!!!
配置方式:圈出配置项必须在代码内修改成一致的
配置后可视化工具显示则正常:
读取电压方式修改: 此处修改为均值滤波的方式读取

读取VBAT电压接口-测试分别用4.2V,3.7V,3.0V(或者更低)都测试下是否数据正常符合误差后使用:
int vbat_battery = gpadc_battery_get_voltage()+10; //+10mv补偿
- 广播音频距离差的优化方案 auracast音箱主要是两块的带宽竞争:经典蓝牙 | BLE广播
手机和广播主机离得比较近的情况,单纯拉距从机距离短:
- 优先建议测试机器的辐射场(苹果图),有些机器带金属框或者结构原因,存在非常大方向性问题,方向好的位置和方向差的位置相差巨大,无法通过软件去优化!!!
- 查看是否有开启BIT(27),BIS的跳频策略

- LC3补包策略,实测效果:4 > 5 > 2 >其他:

手机和主机拉远,从机和主机拉远的情况:
此时就是经典蓝牙 | BLE广播竞争状态,音频来源是手机,所以正常要开启上图BIT(28)的动态RTN机制优先维持EDR;
在EDR信号差的情况下,此时会调整广播的重发次数:3 - 2 - 1次,经典蓝牙信号越差,RTN越低,最低发送音频次数:1+1(rtn)次,RTN越高,实际广播距离越好;
auracast音箱都建议开启AAC格式解码,AAC是动态码率,会实时调整,EDR信号差->EDR码率降低->EDR信号正常->RTN恢复->auracast距离恢复;
SBC格式是固定码率的,bitpool设置53的情况下开启广播,会存在少部分设备和主机实际只离了10m不到,会出现卡顿的情况,带宽不足以维持当前EDR的重发+auracast的最低RTN需求;
调试方式:
由于存在补包的情况所以调试的时候无法比较直观的感受到当前的声音是否卡顿,所以建议config_bb_optimized_ctrl = |BIT(5) debug调试:
打印:
rtn+1:音频包发送数量;
T:800 两秒 : 4(rtn+1)* 2(s) * 100(1s/10ms)
M:丢包数量;
E:错包数量;
Pe:某个包里面rtn+1都是错包或者丢包的,实际需要补包的包数量
Rssi:信号强度参考
双声道两条链路,所以会打印两行
- 增加音量事件过滤机制,避免因音量条滑动过于频繁导致的丢消息卡死等问题 修改btstack.c文件



#include "timer.h"
#include "avctp_user.h"
/***************************************************************/
static u16 delay_report_timer_id;
static struct _bt_event delay_report_msg[4];
static void report_vol_update_event(void *param)
{
delay_report_timer_id = 0;
os_taskq_post_type("app_core", MSG_FROM_BT_STACK, sizeof(struct _bt_event) / 4, (int *)delay_report_msg);
}
static int event_filter_delay_to_report(int event_type, struct _bt_event *evt)
{
if(event_type == MSG_FROM_BT_STACK && evt->event == BT_STATUS_AVRCP_VOL_CHANGE)
{
memcpy(delay_report_msg, evt, sizeof(struct _bt_event));
if(!delay_report_timer_id)
{
delay_report_timer_id = sys_timeout_add(NULL, report_vol_update_event, 100);
}
else
{
sys_timer_modify(delay_report_timer_id, 100);
}
return 1;
}
return 0;
}
/**************************************************************/
if(!event_filter_delay_to_report(from, evt))
{
os_taskq_post_type("app_core", from, sizeof(*evt) / 4, msg);
/*防止短时间内太多事件,app_core处理不过来导致qfull */
os_time_dly(1);
}
/**************************************************************/
if(evt.event != BT_STATUS_AVRCP_VOL_CHANGE){
tws_api_send_data_to_sibling(&evt, sizeof(evt), 0xC9073872);
}