资讯动态

基于杰理AC6904的便携式音频信号发生器DIY全解析:从芯片选型到DAC波形生成

发布时间:2026/8/15 7:18:24 来源:尧图企业网站定制
基于杰理AC6904的便携式音频信号发生器DIY全解析从芯片选型到DAC波形生成最近在调试模拟电路时总觉得手边缺一个趁手的信号源。专业的信号发生器太笨重手机软件又不够稳定输出阻抗也不匹配。于是我琢磨着自己动手做一个。正好手头有几片从旧蓝牙音箱上拆下来的杰理AC6904芯片这玩意儿功能强大、功耗又低用来做个手持音频信号发生器再合适不过了。今天我就把这个从芯片选型到代码实现的完整DIY过程分享给大家希望能给同样喜欢动手的你一些启发。1. 项目需求与芯片选型1.1 我们要做个什么东西简单说我想做一个手持、低功耗、能用电池供电的音频信号发生器。它的核心任务就是产生稳定、可调的音频波形比如正弦波、三角波用来调试功放电路、测试滤波器或者给一些需要信号源的模块用。具体来说我希望它具备以下几个功能波形与频率能输出1Hz到3kHz范围内的正弦波和三角波。人机交互有一个彩色的液晶屏显示菜单用几个按键就能操作。便携与续航体积要小能单手握着用用锂电池供电待机时间要长。输出接口输出要方便接到待测电路上比如用个探针。1.2 为什么是杰理AC6904市面上单片机那么多为什么偏偏选中了杰理AC6904这颗蓝牙音频芯片呢这得从它的“老本行”说起。AC6904本来就是设计用来做蓝牙音箱、播放音乐的。这意味着它内部集成了高质量的立体声DAC数模转换器和耳放耳机放大器。对于我们做信号发生器来说这简直是“专业对口”DAC质量好音频级的DAC输出波形纯净谐波失真小正好满足我们对信号质量的要求。自带耳放芯片输出的信号经过内部耳放驱动可以直接带动一定的负载比如我们的探针省去了外加运放放大电路的麻烦。低功耗作为便携音频芯片低功耗是它的看家本领特别适合电池供电的设备。资料显示在深度待机时整机功耗可以低至4微安以下。集成度高芯片内部还集成了电源管理、时钟等模块外围电路可以做得非常简洁。所以用AC6904来做音频信号发生器可以说是“物尽其用”能用最少的元件实现我们需要的所有核心功能。2. 硬件设计极简主义的艺术我的设计原则是“如无必要勿增实体”。既然AC6904已经集成了大部分功能我们的硬件电路就可以做得非常精简基本就是在它的标准应用电路上做“减法”。2.1 系统框图整个系统的构成非常简单如下图所示[锂电池] --- [AC6904电源管理] | |----------------|----------------| | | [两个按键] [芯片内部核心] (开关/菜单) | | | [彩色LCD屏] ------------------[人机交互逻辑] (160*80) | | | ----------------- [内部DAC耳放] --- [探针输出] | [板载喇叭] (可选)各部分解读输入就两个独立按键。一个负责开关机另一个负责在菜单里选择功能比如切换波形、调整频率。够用就好操作简单。处理核心就是杰理AC6904芯片本身所有波形生成、界面显示的逻辑都在这里运行。输出这是关键信号直接来自芯片内部的DAC经过耳放放大后输出。我特意用缝衣针作为输出端子并固定在板子边缘。这样在调试那些贴片元件密集的小板子时可以像用万用表笔一样轻松地戳到测试点上非常方便。人机界面一块160*80分辨率的彩色LCD屏用来显示当前输出的波形类型、频率、幅度等信息。电源全部交给AC6904内部的电源管理模块外围只需要接几个滤波电容就行。使用一块带保护板的锂电池供电。可选功能板子上还留了一个小喇叭的位置可以开启监听功能让你“听”到输出的音频信号是什么样子的。2.2 硬件设计注意事项避坑指南虽然电路简单但布局布线时有些细节不注意轻则信号有噪声重则芯片不工作。下面这几个坑我踩过你最好避开注意以下要点均基于原始设计资料是保证项目成功的关键。DCDC电源电路如果板子上有开关电源芯片比如给系统供电的它的电感要尽量靠近芯片的SW引脚走线要短而粗避免打孔。电感要选绕线或功率叠层型的直流电阻要小比如小于0.5欧姆额定电流要大于120mA。地线处理电源芯片的功率地PGND不要单独分割直接就近连接到数字地GND上避免形成地环路。模拟信号走线DAC输出的模拟音频走线一定要远离开关电源部分和数字地线防止开关噪声耦合到干净的信号里。唤醒与复位引脚AC6904有几个唤醒IOPR1, PR2, PR3。我们的按键用来唤醒开机的话务必使用PR2引脚并配置为低电平唤醒。因为PR2引脚还有一个特殊功能长按可以触发芯片复位。万一程序跑飞了死机长按这个键就能强制复位重启是个救命的后门。退耦电容芯片每个电源引脚旁边的退耦电容通常为0.1uF必须紧挨着引脚放置并且它的接地端要以最短的路径回到该电源引脚对应的地引脚形成最小的回流环路。电池安全必须使用带保护板的锂电池防止过充、过放、短路这是安全底线。USB限流如果板子有USB充电口在输入端最好串联一个小电阻用来限制最大充电电流保护芯片和电池。3. 软件核心DAC驱动与波形生成硬件是骨架软件才是灵魂。如何让AC6904的DAC输出我们想要的精确频率的波形是本次DIY最核心的部分。3.1 理解AC6904的Audio模块AC6904的音频模块主要包含DAC和ADC。我们只用到DAC部分。它的几个关键特性决定了我们的编程思路立体声DAC包含左右两个声道可以独立工作。我们做单通道信号发生器两个声道输出同样的数据即可。数据格式DAC数据深度是16位即-32768到32767。缓冲区里左右声道的数据是交叉排列的L, R, L, R...并且缓冲区地址要求4字节对齐。采样率支持多种采样率从8kHz到48kHz共10档可选。采样率越高能还原的信号频率上限也越高奈奎斯特定律。双缓冲官方驱动通常使用“乒乓缓冲”结构一个缓冲区播放时另一个缓冲区准备下一帧数据用于连续播放音乐。但对于我们信号发生器这种周期性重复输出同一段波形的场景可以简化只用一段缓冲区循环播放即可。3.2 波形数据生成策略我们的目标是产生1Hz到3kHz的波形。如果为每一个频率都预先计算并存储一个周期的波形数据那需要海量的存储空间显然不现实。我的策略是预存高精度基准波形通过“抽点”的方式生成不同频率。第一步准备基准波形包我生成了两组高采样点的正弦波数据包第一组1200个采样点1200 5*5*3*2*2*2*2第二组2205个采样点2205 7*7*5*3*3为什么选这两个数因为它们能被很多整数整除方便后续做抽点计算。这两个数据包包含了非常细腻的一个正弦波周期信息。第二步构建频率数据表为了编程方便我定义了4个“采样矩阵”矩阵的大小是目标频率的最小公倍数。然后我使用一个结构体数组来管理所有目标频率的关键参数。这个结构体大概长这样// 这是一个示意结构体用于说明思路 typedef struct { uint16_t target_freq; // 目标频率如 50, 100, 1000 uint16_t base_wave_len; // 所使用的基准波形包的长度如 1200 uint16_t step; // 抽点步长 uint16_t play_buf_len; // 最终填入DAC缓冲区的数据长度 uint8_t dac_sample_rate; // 使用的DAC采样率编码 const int16_t *wave_data_ptr; // 指向基准波形数据的指针 } freq_config_t; // 示例一个预设的频率配置表 const freq_config_t freq_table[] { {50, 1200, 24, 100, DAC_SR_48000, sin_wave_1200[0]}, // 50Hz从1200点中每24点抽1个 {100, 1200, 12, 100, DAC_SR_48000, sin_wave_1200[0]}, // 100Hz每12点抽1个 {1000, 2205, 2, 1102, DAC_SR_48000, sin_wave_2205[0]}, // 1000Hz每2点抽1个 // ... 更多频率配置 };注以上代码为原理示意具体参数需根据实际计算调整step抽点步长是这个算法的核心。它的计算公式原理是step (基准波形长度 * 目标频率) / DAC采样率通过改变step我们从长长的基准波形中间隔性地抽取数据点。step越大抽出来的点越少组合成的波形周期就越短频率就越高。3.3 核心驱动函数有了上面的配置表驱动DAC输出的函数就变得非常清晰和简单了。它的任务就是根据选择的频率编号n从freq_table中取出参数然后执行抽点填充DAC缓冲区最后启动DAC。下面是根据原始文章代码整理的核心函数#include jl_audio.h // 假设的杰理音频寄存器头文件 // 定义DAC缓冲区注意4字节对齐要求 __attribute__((aligned(4))) int16_t Audio_Dac_Buf[2048]; /** * brief 根据频率索引配置DAC输出特定频率的波形 * param n 频率配置表中的索引号 */ void Dac_Out_freq(unsigned char n) { unsigned short i, j; // 获取该频率对应的基准波形数据指针 const unsigned short *ptr freq_tab[n].ptr_tab; j 0; // 第一遍循环填充左声道数据缓冲区偶数索引 for(i 0; i freq_tab[n].Buf_len; i freq_tab[n].step) { Audio_Dac_Buf[j] ptr[i]; // 左声道 Audio_Dac_Buf[j] ptr[i]; // 右声道输出相同数据 } // 第二遍循环通常用于填充缓冲区剩余部分或第二个周期 // 这里原文进行了两次相同操作可能是为了确保缓冲区长度满足DAC要求。 // 实际可根据缓冲区大小和单周期数据长度调整。 for(i 0; i freq_tab[n].Buf_len; i freq_tab[n].step) { Audio_Dac_Buf[j] ptr[i]; Audio_Dac_Buf[j] ptr[i]; } // 配置DAC硬件寄存器 JL_AUDIO-DAC_ADR (uint32_t)Audio_Dac_Buf; // 设置缓冲区地址 JL_AUDIO-DAC_LEN freq_tab[n].Buf_len / freq_tab[n].step; // 设置缓冲区数据长度 JL_AUDIO-DAC_CON_bit.DACSR freq_tab[n].DACSR; // 设置采样率 JL_AUDIO-DAC_CON_bit.DACEN 1; // 使能DAC模块开始输出 }代码解读抽点填充两个for循环从基准波形数据ptr中以step为间隔抽取数据并交叉放入Audio_Dac_Buf同时填充左右声道。硬件配置最后三行是配置AC6904的DAC寄存器。DAC_ADR告诉DAC你的数据在内存的哪个地方。DAC_LEN告诉DAC这段缓冲区里有多少个立体声样本对L,R算一对。这里长度是Buf_len/step。DAC_CON设置采样率并使能DAC模块。一旦使能DAC就会自动循环播放缓冲区里的数据持续产生我们想要的波形。3.4 频率上限的考量原文提到DAC最高采样率是48kHz。根据奈奎斯特采样定理能无失真还原的最高信号频率是24kHz这远高于我们3kHz的需求。那为什么上限只做到2kHz呢这里有一个工程上的权衡输出波形的质量。我们是用离散的点来“画”出连续波形。如果一个周期内用来“画图”的点太少波形就会失真变成锯齿状。原文要求1/4周期内至少要有5个数据点那么一个周期至少20个点。在48kHz采样率下能保证这个质量要求的最高频率就是 48000 / 20 2400Hz所以保守设计在2kHz。对于低频比如1Hz如果也用48kHz采样一个周期要48000个点数据量太大。所以低频部分比如20Hz以下可以采用更低的DAC采样率如8kHz来生成以节省缓冲区空间和计算量。4. 效果验证与总结按照上面的设计我打样了PCB焊接好元件烧录程序。用一根音频线将输出探针连接到电脑声卡再配合声卡示波器软件如REW, Audacity等进行测试。从测试截图可以看到输出50Hz、70Hz、90Hz、700Hz、900Hz的正弦波都非常纯净频谱分析显示谐波成分很少证明我们的“基准波形抽点法”和DAC驱动是成功的。回顾整个项目有几点心得选对芯片事半功倍利用AC6904内置的高质量DAC和耳放让我们跳过了最复杂的模拟电路设计直接聚焦于数字波形生成。软件算法的巧妙用“大数组抽点”代替“实时计算”在有限的单片机资源下是一种非常务实高效的频率合成方法。工具要为人服务用缝衣针做输出端这个小小的改动让这个信号发生器在调试贴片电路时变得无比顺手。DIY的乐趣就在于解决实际痛点。这个项目代码结构清晰Dac_Out_freq函数是核心频率配置表freq_tab是灵魂。你可以在此基础上扩展更多波形三角波、方波或者增加频率微调、幅度调节等功能。希望这个详细的解析能帮你打造出属于自己的那款便携、好用的音频信号发生器。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价