AC210N音箱问题整理
📎 原始文档:https://www.kdocs.cn/l/cbJLPaQQ9Pes AC210N音箱问题整理
前言:本文档整理将以各个SDK遇到的共性问题做整理汇总,可直接根据所使用的sdk版本及功能快速索引相关问题点
开发注意点
- AC210N 系列开发需要使用CKEY,跟之前KEY不兼容 需要联系工程助理申请

- AC210N 系列开发使用PB1需要注意 IO默认对电压1/2分压,还要开下拉
- 查看生成代码大小的方法
- 查看编译信息中的 | FLASH_BIN_SIZE : 0xd0000 |

共性问题
- AC210N_le_audio_1.2.0 带ckey的升级固件,使用测试盒升级会出现异常 根本原因:测试盒暂未兼容带ckey的AC210N的升级固件。
处理方法:测试盒升级以下的临时版本1.3.5进行调试,最新版本会在5月底更新。
1.3.5_test.rar - AC210N_le_audio_1.2.0 配置单声道后播放右声道音频无声 处理方法:
直接删除音频流程内的vocal_remover节点。如果需要用到该节点,需要等版本更新,新版本已修复该问题。
- AC210N_le_audio_1.2.0 配置蓝牙PA不起作用 使用注意点:
不带后台的方案:退出蓝牙需要把PA的使能关掉。
带后台的方案:打开蓝牙初始化一次即可。不需要重复初始化。
替换掉原来的蓝牙PA控制函数
1.3.0 SDK版本 该函数已经加进SDK
#include "gpio.h"
void rf_pa_io_set(u8 tx_io, u8 rx_io, u8 en)
{
static u8 last_en = 0xff;
if (last_en == en) {
printf("The PA of rf_pa_io has been switched on!!!!!!!!!!!!!!!!\n");
return;
}
last_en = en;
if (en) {
gpio_och_sel_output_signal(tx_io, OCH_WL_AMPE);
gpio_och_sel_output_signal(rx_io, OCH_WL_LNAE);
} else {
gpio_och_disable_output_signal(tx_io, OCH_WL_AMPE);
gpio_och_disable_output_signal(rx_io, OCH_WL_LNAE);
}
gpio_hw_set_direction(IO_PORT_SPILT(tx_io), 0);
gpio_hw_write(tx_io, 0);
gpio_hw_set_direction(IO_PORT_SPILT(rx_io), 0);
gpio_hw_write(rx_io, 0);
}
- AC210N_le_audio_1.3.2beta.01 媒体使用2.1声道音频流没声音 媒体使用2.1声道音频流dac没有声音
修改:
- AC210N 不带DMA的UART2串口API配置使用问题 AC210的uart2硬件没有DMA,也没有uart空闲中断,因此系统忙时容易丢中断。
底层库函数设计baud只支持9600或以下
库里面的uart2驱动只支持 固定帧长 接收,.frame_size。
当接收的数据量累计等于设置的frame_size,才会读取返回、或者触发中断。
- AC210N_le_audio_1.3.1 开auracast时手机抢播会触发死机 问题描述:设备开启一拖二和音频抢播,然后连接两台手机,其中一台播放再进入Aurocast,再用另一台手机播放抢播会出现死机。
处理方法:
需要在截图这里加个&,建议直接更新到最新的1.4.0版本,已修复该问题。
- AC210N_le_audio_1.3.1-经典蓝牙自定义HID-编译不通过-底层库缺少函数实现bt_sdp_create_diy_hid_service 解决方案:
使用AC210N_le_audio_1.4.0版本或者以上,已经修复了这个编译报错问题
参考这个提供的hid_user.c进行二次开发,需要注意到API接口命名有所变化。 比如原来的bt_sdp_create_diy_hid_service函数,要改为 bt_sdp_create_diy_hid_service_overwrite
hid_user.c
问题处理
- 外挂FLASH下载的IO供电口不受控
处理办法:更换loader.bin
br31loader处理外挂FLASH下载.7z - AC210升级工具合成带有固件的固件升级程序无法打开正常使用。
处理办法:换新的固件升级程序。
固件升级程序_1.4.48.d(修改AC210合并固件升级程序异常).7z - AC210N_le_audio_1.4.1 ADkey 开内置上拉, 无效问题处理 大家配内置上拉的时候,要注意填写正确的上拉电阻。不然会不起作用。
5K -> 50
10K -> 100
200K -> 2000


- AC210N_le_audio_1.4.0 FM发射需要FM-TX和DAC同时出声音 修改音频流



- 概率出现打印auto_abandon_a2dp_data无声问题 原因:
一般是由于 a2dp解码器在跑,但是却没有对应的音频流运行去消耗buf,从而导致的
如果是正常单箱模式,那么可能是a2dp_player没有创建成功所导致
// 参考修复代码,或者需要自行从源头上排查自身业务的合理性
if (get_a2dp_decoder_status() == 1 && !g_play_addr_vaild()) {
if (addr)
a2dp_player_open(addr);
}
- 如果是广播模式,那么可能是le_audio_player没有创建成功所导致,打印查看相关音频流创建是否成功或者是否有调用到
- 或者确认只要a2dp解码器在运行,那么也要打开le_audio_player_open。从而解决无声的问题
资料下载
案例分享:
AC210N_le_audio_1.2.0 无限循环播放提示音 目前只支持mp3格式提示音循环播放
Files · feature_无限循环播放提示音 · JL-Studio / Leaudio / 210N / AC210_le_audio_1.0.0 · GitLab
主要修改如下:


AC210N_le_audio_1.3.1 内部flash自定义区的读写 dmeo:内置flash自定义区
挂载路径与文件名:


获取自定义区域的flash对应的地址
初始化之后info_data_init把每个自定义区对应的flash起始地址保存在flash_addr中文件读写接口 tzflash_write、tzflash_read
AC210N_le_audio_1.3.1 播放内部flash自定义区的提示音 demo:播放flash自定义区提示音
AC210N_le_audio_1.3.2beta01 程序调节"ReverbEcho封装节点"参数 dmeo:调节ReverbEcho封装节点参数
介绍:
ReverbEcho封装节点:将Reverb、Echo、原声三条通路多节点封装成一个节点,简化流程图,优化运行效率
节点配置截图:
注意点:
AC210N_le_audio_1.4.0 外挂flash与sd卡一样做当作设备来播放里面的歌曲 dmeo:feature_140_play_ex_flash_dev
- 生成fat文件系统img
- 工具:FAT镜像文件生成工具_1.0.11.exe
- 生成的文件保存到download.bat所在目录下,并重命名为fat.img
- 其他相关资料:SPI.otl

- usb强制工具下载代码同时下载fat文件系统到外挂flash
- 配置ini的spi引脚 isd_config_rule.c中配置(有些sdk有两个配置,需要删除一个)
- 生成fat文件系统img
//外部FLASH 硬件连接配置
#if (defined CONFIG_EXTERN_FLASH_SIZE) || ((defined TCFG_NORFLASH_DEV_ENABLE) && TCFG_NORFLASH_DEV_ENABLE)
EX_FLASH = PB10_1A_NULL; //CS_pin / spi (0/1/2) /port(A/B) / power_io
EX_FLASH_IO = 2_PB07_PB08_PB09_PC05_PC00; //data_width / CLK_pin / DO_pin / DI_pin / D2_pin / D3_pin 当data_width为4的时候,D2_pin和D3_pin才有效
#endif
- download.c添加下载命令
- 使能下载
#define FLASH_DEV_FATFS_DOWNLOAD_EN 1//是否支持下载功能,如果不支持下载功能,则不需要挂载到电脑上,可以节省flash空间
- 文件系统在flash中的起始地址配置(不是特殊情况设置为0)
#define CONFIG_EXTERN_FLASH_RES_START_ADDR 0x100//起始地址
- 打标签:使用isd_download.exe -ex_flash下载的文件系统必须要使用packres.exe打上标签之后才能被识别到
//文件系统打标签
#if ((defined FLASH_DEV_FATFS_DOWNLOAD_EN) && FLASH_DEV_FATFS_DOWNLOAD_EN)
packres.exe -n res -o res.bin fat.img CONFIG_EXTERN_FLASH_RES_START_ADDR -normal
set UEXFILE= -ex_flash res.bin
#endif

3. 外置flash挂载为一个设备
- 在app_config.h中添加添加相关宏定义
#define FLASH_SIZE_256K (0x40000)
#define FLASH_SIZE_512K (0x80000)
#define FLASH_SIZE_1M (0x100000)
#define TCFG_NORFLASH_EX_DEV_ENABLE 1 //是否开启norflash extern设备支持
#define CONFIG_EXTERN_FLASH_SIZE (FLASH_SIZE_1M*4)//配置外挂FLASH大小
#define CONFIG_EXTERN_FLASH_RES_START_ADDR 0x0//起始地址
// #define TCFG_FLASH_EXDEV_FLASH_READ_WIDTH 2// flash线宽 由工具配置
#define TCFG_FLASH_EXDEV_SPI_CS_PORT IO_PORTB_10// CS片选IO
#define TCFG_FLASH_EXDEV_SPI_HW_NUM 1 // 硬件SPI号 工具配置优先
#define TCFG_EX_FLASH_POWER_IO IO_PORTC_08// flash电源IO
#define TCFG_PC_DEV_MANAGER_ENABLE 1 //是否开启PC设备管理器支持
#define FLASH_DEV_FATFS_DOWNLOAD_EN 1//是否支持下载功能,如果不支持下载功能,则不需要挂载到电脑上,可以节省flash空间
#define FLASH_DEV_MUSIC_EN 1//是否支持音乐功能
#define FLASH_DEV_FATFS_LOGO "ex_fat" //设备 logo
#define FLASH_DEV_FATFS_NAME FLASH_DEV_FATFS_LOGO//"ex_fatfs" //设备名称
#define FLASH_DEV_FATFS_TYPE "fat" //fs_type
#define FLASH_DEV_FATFS_STORAGE_PATH "storage/ex_fat" //app区:/app 扩展区: /EXT_RESERVED
#define FLASH_DEV_FATFS_ROOT_PATH FLASH_DEV_FATFS_STORAGE_PATH "/C" //app区:/app 扩展区: /EXT_RESERVED
#if ((defined TCFG_PC_DEV_MANAGER_ENABLE) && TCFG_PC_DEV_MANAGER_ENABLE)
//其他设备比如sd卡也需要pc设备管理器支持,如果没有开启这个宏,sd卡设备不会在pc模式下挂载到电脑上被识别成U盘
#define TCFG_USB_ISERIALNUMBER 1 //是否开启多磁盘支持,开启之后USB_ISERIALNUMBER会置3
#endif
- 在dev_reg.c中配置外置flash路径相关信息
const struct __dev_reg dev_reg[] = {
#if TCFG_NORFLASH_EX_DEV_ENABLE
//flash sfc fat
{
/*logo*/ FLASH_DEV_FATFS_LOGO,
/*name*/ FLASH_DEV_FATFS_NAME,
/*storage_path*/ FLASH_DEV_FATFS_STORAGE_PATH,
/*root_path*/ FLASH_DEV_FATFS_ROOT_PATH,
/*fs_type*/ FLASH_DEV_FATFS_TYPE,
},
#endif
- 在device_config.c 配置外置flash硬件信息

#if TCFG_NORFLASH_EX_DEV_ENABLE
NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_ex_dev_data)
.spi_hw_num = TCFG_FLASH_EXDEV_SPI_HW_NUM,
.spi_cs_port = TCFG_FLASH_EXDEV_SPI_CS_PORT,
//工具配置优先
#if (defined(TCFG_FLASH_DEV_SPI_HW_NUM) && (TCFG_FLASH_DEV_SPI_HW_NUM == 1))
.spi_pdata = &spix_p_data[1],
#elif(defined(TCFG_FLASH_DEV_SPI_HW_NUM) && (TCFG_FLASH_DEV_SPI_HW_NUM == 2))
.spi_pdata = &spix_p_data[2],
#elif(defined(TCFG_FLASH_EXDEV_SPI_HW_NUM) && (TCFG_FLASH_EXDEV_SPI_HW_NUM == 1))
.spi_pdata = &spix_p_data[1],
#elif(defined(TCFG_FLASH_EXDEV_SPI_HW_NUM) && (TCFG_FLASH_EXDEV_SPI_HW_NUM == 2))
.spi_pdata = &spix_p_data[2],
#endif
#if (defined(CONFIG_EXTERN_FLASH_RES_START_ADDR))
.start_addr = CONFIG_EXTERN_FLASH_RES_START_ADDR,
#else
.start_addr = 0,
#endif
#if (defined(CONFIG_EXTERN_FLASH_SIZE))
.size = CONFIG_EXTERN_FLASH_SIZE,
#else
.size = 2 * 1024 * 1024,
#endif
NORFLASH_DEV_PLATFORM_DATA_END()
#endif
- 在device_config.c中注册外置flash设备
把设备名称、设备硬件信息、设备驱动接口关联起来
REGISTER_DEVICES(device_table) = {
#if TCFG_NORFLASH_EX_DEV_ENABLE
{FLASH_DEV_FATFS_LOGO,&norflash_dev_ops,(void *)&norflash_norfs_ex_dev_data},
#endif
- 在device_config.c中开机时把外置flash挂载为一个设备
static void dev_manager_task(void *p)
{
int res;
int msg[16] = {0};
///过滤隐藏 和 .开头名名的字文件
hidden_file(1);
///设备初始化,
devices_init();
#if TCFG_SD_ALWAY_ONLINE_ENABLE
#if (defined(TCFG_SD0_ENABLE) && (TCFG_SD0_ENABLE))
sdmmc_dev_force_online("sd0");
int err = dev_manager_add("sd0");
#elif (defined(TCFG_SD1_ENABLE) && (TCFG_SD1_ENABLE))
sdmmc_dev_force_online("sd1");
int err = dev_manager_add("sd1");
#endif
if (err != 0) {
printf("sd add fail\n");
}
#endif
#if TCFG_NORFLASH_EX_DEV_ENABLE
{
int ret = dev_manager_add(FLASH_DEV_FATFS_LOGO);
g_printf("%s add ret = %d\n", FLASH_DEV_FATFS_LOGO,ret);
#if((defined(FLASH_DEV_MUSIC_EN))&&FLASH_DEV_MUSIC_EN)
dev_manager_set_valid_by_logo(FLASH_DEV_FATFS_LOGO, 1);///将设备设置为无效设备
#else
dev_manager_set_valid_by_logo(FLASH_DEV_FATFS_LOGO, 0);///将设备设置为无效设备
#endif
}
#endif
4. PC模式下通过磁盘管理器管理外置flash
- 在msd.c中增加pc可以管理个数
inline static u8 __get_max_msd_dev()
{
u8 cnt = 0;
#if TCFG_PC_DEV_MANAGER_ENABLE
cnt++;
#endif
- 进pc之后把外置flash挂载到电脑磁盘
void usb_start(const usb_dev usbfd)
{
log_info("enter usb slave mode");
u32 class = 0;
#if TCFG_USB_SLAVE_MSD_ENABLE
class |= MASSSTORAGE_CLASS;
#endif
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
class |= SPEAKER_CLASS;
#endif
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
class |= MIC_CLASS;
#endif
#if TCFG_USB_SLAVE_HID_ENABLE
class |= HID_CLASS;
#endif
#if TCFG_USB_SLAVE_CDC_ENABLE
class |= CDC_CLASS;
#endif
#if TCFG_USB_CUSTOM_HID_ENABLE
class |= CUSTOM_HID_CLASS;
#endif
#if TCFG_USB_SLAVE_MTP_ENABLE
class |= MTP_CLASS;
#endif
#if TCFG_USB_SLAVE_MIDI_ENABLE
class |= MIDI_CLASS;
#endif
#if TCFG_USB_SLAVE_PRINTER_ENABLE
class |= PRINTER_CLASS;
#endif
#if TCFG_USB_APPLE_DOCK_EN
class |= IAP_CLASS;
#endif
#if TCFG_USB_WEBUSB_ENABLE
class |= WEBUSB_CLASS;
#endif
g_printf("USB_DEVICE_CLASS_CONFIG:%x", class);
usb_device_mode(usbfd, class);
#if TCFG_PC_DEV_MANAGER_ENABLE
dev_manager_set_valid_by_logo(FLASH_DEV_FATFS_LOGO, 1);
msd_register_disk(FLASH_DEV_FATFS_LOGO, NULL);
#endif
- TWS碰一碰快捷连接 备注:碰一碰功能,需要有一个机器发起配对。(发起配对后,才会根据RSSI值进行连接)
#define CONFIG_TWS_CONN_WITH_RSSI 1
#define CONFIG_TWS_CONN_RSSI_LEVEL -30 //根据需要的配对距离调节 - 硬件DAC为单声道TWS主从实时切换声道 硬件dac为单声道输出,TWS的主从声道调换,效果如下:
主为R从为L切换之后主为L从为R
feature_硬件dac单声道_tws时切换dac数据的声道
切换接口的调用:
case APP_MSG_TWS_CHANNEL_SWITCH:
r_printf("app msg tws channel switch\n");
bt_tws_channel_switch();
break;
DAC为单声道:
媒体音频流:
- AC210N_le_audio_1.3.1 使能发送端切模式不重置广播配置,打开auracast,从BT切换到Linein模式的时候死机 原因:函数指针与函数实现不匹配,函数指针只传入了一级指针,但函数实现是二级指针。导致访问非法地址死机
修改如下:
- AC210N_le_audio_1.4.0普通io口做串口从机升级(双备份) Files · feature_140_普通io做串口从机升级 · JL-Studio / Leaudio / 210N / AC210_le_audio_1.0.0 · GitLab
主要修改如下: - 开普通io串口升级功能

- 编译报找不到对应接口,添加编译c文件

- 修改编译报错

- 串口升级通信不成功(小机没有回包)修改串口升级使用的串口号

- pc串口升级工具连接小机升级时报超时 SerialUpdateDemo-20260716.exe
