ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Cyclone II+Nios II软核实现FFT音频信号分析仪

Cyclone II+Nios II软核实现FFT音频信号分析仪 简介2007年全国大学生电子设计竞赛A题「音频信号分析仪」完整设计方案文档面向备赛电赛的本科生、指导教师以及关注音频频谱测量的电子工程师。文档以在Altera Cyclone II FPGA中嵌入Nios II软核、用FFT实现数字式频谱分析为主线逐项论证方案取舍FFT计算方式选择、12位AD1674采样电路、NE5532与TL084前端可控增益放大与峰值保持电路×1、×2、×20、×200四档、8阶IIR切比雪夫II型数字低通滤波替代有源模拟滤波并给出按帕斯瓦尔定律计算总功率与各频率分量功率的方法50mV至5V输入范围内误差控制在1%以内。压缩包为1个docx文件约175KB体积轻便。目前已有365人学习适合赛前梳理系统框架、对照选型依据与电路细节也可作为课程设计报告的模板参考。1. 一块Cyclone II上跑Nios II做频谱分析2007年A题的取舍2007年全国大学生电子设计竞赛A题要求做一个音频信号分析仪四天三夜要测总功率、各频率分量功率、周期性、失真度。拿到题的人大致分两派一派堆模拟滤波器做扫描式频谱仪另一派找DSP芯片或者高性能单片机。真正落地稳的往往是第三条路——用Altera Cyclone II FPGA内嵌Nios II软核把FFT放在软核里用C跑硬件只负责采样控制和数字滤波。反直觉的地方在于FFT是运算密集型很多人以为必须上VHDL硬件实现才够快但四天内写出稳定的VHDL FFT几乎不可能而Nios II支持C语言一份现成的C版FFT稍改就能烧进去。这套方案后来成了不少电赛队伍找参考模板时会翻到的经典结构也适合想搞清FPGA软硬协同分工的工程师顺着看一遍。2. 采样率、频率分辨率与AD1674的选型账2.1 奈奎斯特、二次采样与分辨率三角关系本题输入信号最高频率10kHz奈奎斯特要求采样率不低于两倍也就是20kHz。但直接用20kHz采再送去FFT抗混叠压力全压在前端模拟滤波器上。工程做法是先以较高速率采样在FPGA里用数字滤波器做精确抗混叠滤波后再二次采样降采样把速率降下来减少FFT的运算量。原始采样率一般取二次采样率的3倍左右给数字滤波器的过渡带留余量。三个量里频率分辨率Δf、FFT点数N、二次采样率fs2满足fs2 N × ΔfFFT能表示的最高频率 fs2 / 2要做100Hz分辨率N取2的幂方便蝶形运算N256时fs2 256×100 25.6kHz测量频率上限25.6k/2 12.8kHz覆盖10kHz够用。分辨率和点数不能随便拍浪费点数就是浪费Nios II的CPU周期这在软核上是要命的。2.2 为什么用12位AD1674而不是8位题目要求功率测量误差在5%以内。8位A/D满量程256级双极性输入10Vpp时每级约39mV量化噪声摊到功率上已经吃不消。AD1674是12位、双极性满偏±5V即10Vpp相对5Vpp信号分辨率约1.2mV余量足够。它100kHz的采样速率也覆盖了前面算出的76.8kHz原始采样需求。下面这段脚本用来反推每档分辨率的参数顺手验证选型import math fmax 10000 # 输入信号最高频率 Hz def design(resolution): # N 取满足 N*dF 2*fmax 的最小 2 的幂 n 2 ** math.ceil(math.log2(2 * fmax / resolution)) n max(n, 256) fs2 n * resolution # 二次采样率 fs_raw fs2 * 3 # 原始采样率留 3 倍抗混叠余量 return n, fs2, fs_raw, fs2 / 2 for r in [100, 50, 20, 10]: n, fs2, fs_raw, f_meas design(r) print(f分辨率{r:3}Hz: N{n:4d}, 二次采样{fs2/1000:6.2f}kHz, f原始采样{fs_raw/1000:6.2f}kHz, 测量上限{f_meas/1000:6.2f}kHz)逻辑上2*fmax/resolution就是让测量上限刚好压过fmax所需的最小点数取2的幂是为了复用基2 FFTfs2*3是给数字滤波器的过渡带留空间二次采样前带外已经被压得足够低。参数说明resolution是要设的频率分辨率档位fmax是本设计的10kHz。跑出来会发现100Hz和50Hz两档二次采样率都是25.6kHz20Hz和10Hz档降到20.24kHz附近。2.3 四档分辨率实际参数设计里定了四档分辨率方便在不同场景切换。低分辨率档刷新快、运算省高分辨率档能分辨更密的谱线频率分辨率FFT点数FFT测量频率上限二次采样率原始采样率100Hz25612.8kHz25.6kHz76.8kHz50Hz51212.8kHz25.6kHz76.8kHz20Hz102410.24kHz20.24kHz60.72kHz10Hz204810.24kHz20.24kHz60.72kHz提示分辨率越低不代表越差。测基频低的信号时谱线间隔小才分得开这时才需要往高点数档切。默认档建议停在50Hz或100Hz省CPU。四档的切换由Nios II软件控制采样控制器分频系数和FFT点数硬件侧只改分频寄存器不需要重新综合。这点在FPGA里很关键如果每次改分辨率都要重新编译四天时间根本不够用。3. 可控增益前端与8阶切比雪夫II型IIR滤波器落地3.1 NE5532四档放大通道与峰值保持选档前端要先解决动态范围输入峰峰值从5Vpp一路到50mVpp跨度100倍。如果只用固定增益小信号进A/D后有效位太少精度直接崩。方案是把放大电路分成四档用模拟开关切换放大倍数以当前信号峰值为选择基准档位放大倍数适配输入峰峰值主运放1×110VppNE55322×25VppNE55323×20500mVppNE55324×20050mVppNE5532输入级先用运放跟随器并联一只50欧姆精密电阻满足50欧姆输入阻抗要求同时增强带负载能力再经隔直电容进后级。NE5532是音频信号处理里的经典运放低噪、低失真比通用运放更适合这一档。选档靠峰值保持电路用TL084配精密二极管和47uF充电电容记录一个FFT周期内的峰值和参考电压比较后决定下一次采样的通道。47uF不是随便选的电容太小漏电流会让保持电压往下掉采样还没结束峰值就失真了。每次采样前要对电容放电重新记录。3.2 Chebyshev II型IIR低通滤波器设计FFT前的抗混叠靠数字滤波器做选切比雪夫II型Chebyshev II低通原因是它通带平坦、阻带等波纹、过渡带适中相频和群延迟特性也还过得去很适合音频。8阶、低通用的FIR的话阶数要翻好几倍Nios II扛不住。系数用Matlab的Filter Design Analysis Tool算也可以用命令行直接生成% 8阶 Chebyshev II 型数字低通滤波器系数设计 fs 76800; % 原始采样率 fp 10000; % 通带截止 10kHz fst 12000; % 阻带起始 12kHz Rp 1; % 通带波纹 dBII型通带平坦这里影响阻带 Rs 60; % 阻带最小衰减 dB % 先估算满足指标需要的阶数 [n, Wn] cheb2ord(fp/(fs/2), fst/(fs/2), Rp, Rs); [b, a] cheby2(n, Rs, Wn); % 得到传递函数系数 fprintf(实际阶数 n%d\n, n); fprintf(分子系数 b %s\n, mat2str(b, 6)); fprintf(分母系数 a %s\n, mat2str(a, 6));cheb2ord先根据通带、阻带、波纹指标反推最小阶数cheby2再算出具体的b、a系数。参数说明fst-fp是过渡带宽度越窄需要的阶数越高Rs60dB决定了带外压得有多狠混叠主要靠它挡。得到系数后进Altera DSP Builder在可视化界面里按二阶节biquad级联搭出滤波器每个二阶节一组系数。3.3 定点化与软硬分工DSP Builder搭出来的滤波器默认浮点上FPGA要定点化。常见做法是系数放大2的幂次后取整输出再右移相应位数还原。定点位宽要算好位宽太窄滤波器极点附近的量化误差会放大太宽浪费逻辑资源。8阶IIR级联一般给到18~24位累加器比较稳。分工上自动增益控制、A/D转换控制、数字滤波用VHDL实现FFT、功率计算、周期性判断、失真度、键盘液晶这些交给Nios II软核。两部分并行跑硬核负责实时性强的数据通路软核负责灵活的计算逻辑。这个分工的好处是滤波器改系数不用动C代码FFT算法改逻辑也不影响采样控制。4. FFT结果怎么变成功率、周期性和失真度4.1 帕斯瓦尔定律从连续到离散测功率不用真有效值芯片直接用FFT结果配合帕斯瓦尔定律算。连续形式是时域能量等于频域能量时域积分等于频域积分。离散形式对应到DFT是Σ|x[n]|² (1/N)Σ|X[k]|²对单频余弦信号x[n] A·cos(2πk₀n/N)它在第k₀点的频谱幅度|X[k₀]| A·N/2代回去就能反推出该频率分量的物理功率A²/2。所以每个频点的功率都能从FFT结果直接算同时总功率就是各分量之和。这样做比真有效值芯片强的地方在于真有效值只能测总功率测不了单个频点的功率。4.2 Nios II上的C FFT实现软核跑FFT用的是一份标准的基2 Cooley-Tukey迭代版本稍改就能用。核心是位反转重排加三级循环的蝶形运算#include math.h #define N 256 typedef struct { double re, im; } cpx; static cpx x[N]; static cpx w[N 1]; /* 预计算旋转因子 W_N^k cos(2πk/N) - j·sin(2πk/N) */ void init_twiddle(void) { for (int k 0; k N / 2; k) { w[k].re cos(2.0 * M_PI * k / N); w[k].im -sin(2.0 * M_PI * k / N); } } /* 位反转置换把 x[i] 与二进制倒序的 x[j] 交换 */ void bit_reverse(void) { for (int i 1, j 0; i N; i) { int bit N 1; for (; j bit; bit 1) j ^ bit; j ^ bit; if (i j) { cpx t x[i]; x[i] x[j]; x[j] t; } } } void fft(void) { bit_reverse(); for (int len 2; len N; len 1) { /* 蝶形级数log2(N) 级 */ int half len 1; int step N / len; /* 旋转因子抽取间隔 */ for (int i 0; i N; i len) { for (int k 0; k half; k) { cpx u x[i k]; cpx v x[i k half]; cpx wv; /* v × W_N^{k·step} */ wv.re v.re * w[k*step].re - v.im * w[k*step].im; wv.im v.re * w[k*step].im v.im * w[k*step].re; x[i k].re u.re wv.re; x[i k].im u.im wv.im; x[i k half].re u.re - wv.re; x[i k half].im u.im - wv.im; } } } }init_twiddle只在初始化时算一次旋转因子避免在蝶形里反复调三角函数——软核上三角函数开销很大这是最容易拖慢速度的坑。bit_reverse的循环用位运算做二进制倒序比字符串反转快。fft外层控制级数中层按块走内层做蝶形。参数说明N必须取2的幂旋转因子按N/len的间隔抽取保证每级用到的角度正确。4.3 周期性判断与失真度周期信号的频谱是谐波离散的只含基频和基频整数倍分量谱线间隔就是基频。判断方法是从最小频率分辨率点开始往上扫如果最低那几个点频率分量接近0实际不为0是一个很小的数第一个出现峰值的地方就是基频。这个方法对基频大于最小分辨率的信号有效基频更低的信号测不了得加FFT点数。前面四档分辨率的用意就在这里。失真度用谐波能量和与基波能量之比的开方表示/* 频域法算失真度谐波功率和开方除以基波功率 */ double calc_thd(const double *power, int k0, int kmax) { double fund power[k0]; /* 基波功率 */ double harm 0.0; for (int k 2 * k0; k kmax; k k0) harm power[k]; /* 累加各次谐波功率 */ return sqrt(harm) / fund; /* 结果乘 100% 即失真度 */ }k0是基频对应的谱线索引kmax是测量上限循环从2倍基频开始每次跨一个基频只挑谐波点避免把噪声也累进去。算的时候要记得补偿滤波器对信号的衰减、按放大倍数还原到真实值否则误差会偏大。4.4 功率计算的补偿细节FFT出来的幅度是ADC满量程下的相对值要变成物理功率必须过两关一是除掉前端放大倍数二是补回数字滤波器在通带内的衰减。每档增益对应的还原系数不同滤波器在通带内的衰减也不是常数严格做法是按频点查补偿表。工程上如果通带平坦度足够好可以近似成常数处理但测误差要控制在1%以内时最好还是逐点补偿。5. 实测验证输入阻抗、功率误差与动态范围5.1 分压法测输入阻抗输入阻抗用分压法测简单可靠。在输入端串联一只0.1%精度的50欧姆电阻用61/2位数字万用表分别测电阻两端和系统输入端的电压。实测时用函数发生器输出5kHz、1Vpp正弦波电阻两端测得0.501Vpp系统输入端0.499Vpp。按分压关系 Zin R × (Vin / Vr)代入50 × 0.499/0.501算出约49.8欧姆和50欧姆目标值差距在1%以内说明跟随器加并联电阻这一级做得对。5.2 功率测量误差两路信号叠加测试一路1Vpp0.01W、1kHz另一路2Vpp0.04W、3kHz理论总功率0.05W。实测总功率0.05021W最大功率分量0.0399W次大0.01013W各频点功率和0.05003W各频率功率和与总功率误差0.36%。四组测试下来总功率相对误差小于1%各频率功率误差小于2%。测试组信号频率理论总功率实测总功率误差110kHz 9kHz0.05W0.04978W0.80%21kHz 3kHz0.05W0.05021W0.36%3110Hz 100Hz0.05W0.05034W0.45%430Hz 20Hz0.05W0.05004W0.67%第三组110Hz和100Hz只差10Hz落在100Hz分辨率档下能分开误差0.45%第四组30Hz和20Hz差10Hz得切到20Hz或10Hz档误差0.67%。低频率、近间隔这两组能把误差压到这个水平说明滤波和二次采样没引入额外混叠。5.3 动态范围与转换时间动态范围测的是小信号和强信号共存时能不能分辨。用5V、1kHz信号叠加5kHz小信号从100mV往下调小信号幅度观察频谱图上能否分辨。结果100mV、50mV、30mV、10mV都能分辨到5mV才不可分辨动态范围比题目要求宽。转换时间方面把分辨率设到10Hz档用LED翻转配合秒表测单次转换平均0.83秒对应2048点FFT加全部计算和显示在软核方案里属于合理区间。注意软核跑FFT的刷新速度受分辨率影响最大。需要实时看频谱变化时把档位切到100Hz单次刷新能压到0.1秒量级用10Hz档看稳态谱就行。5.4 失真度测量的门道失真度测试有两组结果值得看。用1kHz方波测理论失真度46%算到10次谐波系统测得46.8%差0.8个百分点说明高次谐波没被滤波器吃掉。用不太理想的正弦波测失真度测试仪读0.9%本系统读0.54%差别来自系统测到的是10次谐波以内的能量而失真度测试仪可能带更宽的带宽或者别的计权方式。这类偏差不是系统不准而是两者测量口径不同比较的时候要看清参考仪器的带宽设置。周期性测试则更直接方波、正弦波、三角波都判为周期波M序列判为非周期波逻辑符合预期。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表