1、 1 / 16音频信号的 FFT 分析一、实验目的: .2二、实验内容: .2三、实验程序功能与结构说明: .3四、实验流程图: .3五、实验步骤: .41、实验演示: .42、实验的调试: .5六、实验主要程序: .51、主函数: .52、中断程序: .123、异步串口初始化程序: .134、AD 初始化: .14七、实验结果: .151、SEEDDEC2812 单元的 D3 灯由闪烁变成常暗。 .152、可以看到失真比较大的 FFT 波形,如下图所示: 151)、失真信号及频域图: .152)、期信号时域和频域曲线图: .16八、实验心得: .162 / 16一、实验目的:1、 熟悉 CC
2、S 集成开发环2、 熟悉 SEED-DTK 实验环境3、 加深对 DFT 算法原理和基本性质的理解4、 学习用 FFT 对连续信号和时域信号地频谱分析的方法5、 熟悉 FFT 的算法原理和 FFT 子程序的算法流程和应用6、 了解 DSP 处理 FFT 算法的特殊寻址方式二、实验内容:1、 DSP 的初始化2、 A/D 采样3、 FFT 的位倒序程序4、 FFT 的蝶形运算程序5、 求功率谱的程序6、 串口发送与接收三、实验程序功能与结构说明:在数字滤波器实验中,主要包含以下文件:1、 DTK_BPD_FFT.c:这是实验的主程序,包含了包含定时器中断程序、AD 中断程序、FFT 参数的初始化
3、,完成与 SEED-MMI5402 的系统的异步通讯、信号采集与 FFT 计算。2、 DSP28_Sci.c:包含量了异步串口初始化程序。3、 DSP28_Adc.c:包含了 AD 初始化。4、 DSP28_Defaultlsr.c:包含了异步串口接收中断服务程序。5、 Cfft32c.asm、cfft32i.asm、rfft32br.asm 、rfft32m.asm、rfft32s.asm、rfft32w.asm:TI源代码。6、 SRAM.cmd:声明了系统的存贮器配置与程序各段的链接关系。7、 DTK_BPD_FFT.out:DSP 上可执行的程序,即实验程序。3 / 16四、实验流程图
4、:4 / 16五、实验步骤:1、实验演示:在脱机(不接 CCS)的情况下,可以首先进行实验的演示。在实验选项的菜单下,选择 FFT 实验一项。先择不使用 CCS,确定后,LCD 显示屏将显示“程序装载中,请稍侯” ,并且用状态条显示程序装载进度,等待装载程序后,SEEDDEC2812 单元的 D3 灯由闪烁变暗。LCD 显示屏将显示“FFT 实验装载成功” 。一段时间后,可以看到在 LCD 上显示 FFT 前的原始信号与实验后的功率谱图,如下图(a 与 b)所示:2、实验的调试:1) 、将 DSP 仿真器与计算机连接好:2) 、将 DSP 仿真器的 JTAG 插关与 SEED-DEC2812
5、单元的 J1 相连接3) 、启动计算机,当计算机启动后,打开 SEED-DTK BPD 的电源。观察 SEEK-DTK_IO 单元的+5V 、+3.3V、+15V、-15V 的电源指示灯是否均亮,若有不亮的,请断开电源,检查电源。4) 、在实验选项的菜单下,选择定时器实验一项,选择使用 CCS。5) 、打开 CCS,进入 CCS 的操作环境。6) 、装入 DTK_BPD_FFT.wks 调试环境。7) 、进行调度,通过 Probe Points 来观察 FFT 的结果。5 / 16六、实验主要程序:1、主函数:void main(void)/*初始化系统*/InitSysCtrl();/*关中
6、断*/DINT;IER = 0x0000;IFR = 0x0000;/*初始化 PIE 中断*/InitPieCtrl();/*初始化 PIE 中断矢量表*/InitPieVectTable();/*初始化 SCIA 寄存器*/InitSci();/初始化 cputimerInitCpuTimers();for(i= 0; iLength = FRAMLONGTH;psend-Type = UARTCOMMAND;psend-Data0 = INITOVER;psend-Mutul = UARTCONT;uart_send();for(;)if(CommandSave=FFTDATASEND)
7、CommandSave=0;/*不满 buffer 的数据*/if(datasendlength Datai = Ad_datai+sendcount*256;psend-Length = datasendlength;psend-Type = UARTDATA;7 / 16psend-Mutul = UARTCONT;uart_send();else/*满 buffer 数据*/for(k = 0; kDatak = Ad_datak+sendcount*256;psend-Length = 256;psend-Type = UARTDATA;psend-Mutul = UARTMUTL;u
8、art_send();datasendlength= datasendlength - 256;sendcount+; uart_s =uart_recive();/* 返回值 0:接受完成 */* 1:数据未准备好 */* 3: 较验出错 */if(uart_s=1)continue;/*数据较验出错*/if(uart_s = 3)for(i= 0; iLength = FRAMLONGTH;psend-Type = UARTCOMMAND;psend-Data0 = RECIEVEERROR;psend-Mutul = UARTCONT;uart_send();8 / 16continue
9、;/*接收完成*/if(uart_s =0)/*不是命令帧*/if(precieve-Type != UARTCOMMAND)/*无效命令*/psend-Length = FRAMLONGTH;psend-Type = UARTCOMMAND;psend-Data0 = COMMANDNODO;psend-Mutul = UARTCONT;uart_send();precieve-Type = UARTCOMMAND;continue;/*接收从主机的数据*/precieve = (PuartForDec5416)(switch(precieve-Data0)/*FFT 设置*/case FF
10、TSET:for(i=0;iDatai+1;/*设置数据发送长度*/datasendlong = padset-SampleLong;datasendlength= 3*datasendlong/2;precieve-Data0 = 0;break;/*启动 AD 采样和 fft 计算*/case FFTSTART:convcount=0;adconvover=0;sendcount=0;convfirstN=1000;9 / 16/*AD 采样率*/switch( padset-SampleRate)case ADSAMPL8K: /0xd /采样率为 8kDINT;/*设置 CPU*/Co
11、nfigCpuTimer(StartCpuTimer2();/*开中断*/IER |= M_INT14;EINT;InitAdc();break;case ADSAMPL44K: / 0x23 /采样率为 44k DINT;/*设置 CPU*/ConfigCpuTimer(StartCpuTimer2();/*开中断*/IER |= M_INT14;EINT;InitAdc();break;case ADSAMPL96K:/0x1d /采样率为 96k DINT;/*设置 CPU*/ConfigCpuTimer(StartCpuTimer2();/*开中断*/IER |= M_INT14;EI
12、NT;InitAdc96k();break;default:break; for(;)if (adconvover=1)break;/*AD 采样结束*/10 / 16/*fft 转换*/* Initialize FFT module */switch(datasendlong)case 128:fft128.ipcbptr=ipcb;fft128.init(for(i=0;i4)-0x555;/偏移量 1v。ipcbi = (ipcbi4)-0x555;RFFT32_brev(ipcb,ipcb,FFTN128);fft128.calc(fft128.split(break;case 256
13、:fft256.ipcbptr=ipcb;fft256.init(for(i=0;i4)-0x555;/偏移量 1v。ipcbi = (ipcbi4)-0x555;RFFT32_brev(ipcb,ipcb,FFTN256);fft256.calc(fft256.split(break;case 512:fft512.ipcbptr=ipcb;fft512.init(for(i=0;i4)-0x555;/偏移量 1v。ipcbi = (ipcbi4)-0x555;RFFT32_brev(ipcb,ipcb,FFTN512);fft512.calc(fft512.split(11 / 16bre
14、ak;default:break;/*求模*/ m=0;for(i=0;iLength = 1;psend-Type = UARTCOMMAND;psend-Data0 = FFTOVER;psend-Mutul = UARTCONT;uart_send();precieve-Data0 = 0;break;/*FFT 数据传送*/case FFTDATASEND:precieve-Data0 = 0;CommandSave=FFTDATASEND;break;case RECIEVEERROR:datasendlength = datasendlength + 256;sendcount-;
15、precieve-Data0 = 0;CommandSave=FFTDATASEND;break;/*系统复位*/case SYSRESET:sys_reset();12 / 16default:break; 2、中断程序:interrupt void ad(void)IFR=0x0000;PieCtrl.PIEACK.all=0xffff;if(convfirstN=0)Ad_dataconvcount = AdcRegs.RESULT1;if(Ad_dataconvcount=0)convcount-;convcount+;if (convcount=(padset-SampleLong)
16、convcount=0;adconvover=1;/接满标志DINT;/*停止计数*/StopCpuTimer2();/*关中断*/IER EINT; elseconvfirstN-;3、异步串口初始化程序:void InitSci(void)*UART_MODE = 0x44;13 / 16EALLOW;GpioMuxRegs.GPFMUX.all = 0x0030;EDIS;/* loopback 8 bit data */SciaRegs.SCICCR.all = 0x07;SciaRegs.SCICTL1.all = 0x03;SciaRegs.SCICTL2.all = 0x02;S
17、ciaRegs.SCIHBAUD = 0x00;SciaRegs.SCILBAUD = 0xF3;SciaRegs.SCICTL1.all = 0x23;PieCtrl.PIEIER9.bit.INTx1 = 1;4、 AD 初始化:void InitAdc(void)AdcRegs.ADCTRL1.bit.RESET=1;AdcRegs.ADCTRL2.bit.RST_SEQ1=1;AdcRegs.MAX_CONV.bit.MAX_CONV=15;NOP;AdcRegs.ADCTRL1.bit.RESET=0;AdcRegs.ADCTRL1.bit.SUSMOD=3;AdcRegs.ADCT
18、RL1.bit.ACQ_PS=0;AdcRegs.ADCTRL1.bit.CPS=0;AdcRegs.ADCTRL1.bit.CONT_RUN=0;AdcRegs.ADCTRL1.bit.SEQ_CASC=1;AdcRegs.MAX_CONV.bit.MAX_CONV=15;AdcRegs.CHSELSEQ1.bit.CONV00=14;/硬件连接到了 ADCINB6AdcRegs.CHSELSEQ1.bit.CONV01=1;AdcRegs.CHSELSEQ1.bit.CONV02=2;AdcRegs.CHSELSEQ1.bit.CONV03=3;AdcRegs.CHSELSEQ2.bit.
19、CONV04=4;AdcRegs.CHSELSEQ2.bit.CONV05=5;AdcRegs.CHSELSEQ2.bit.CONV06=6;AdcRegs.CHSELSEQ2.bit.CONV07=7;14 / 16AdcRegs.CHSELSEQ3.bit.CONV08=8;AdcRegs.CHSELSEQ3.bit.CONV09=9;AdcRegs.CHSELSEQ3.bit.CONV10=10;AdcRegs.CHSELSEQ3.bit.CONV11=11;AdcRegs.CHSELSEQ4.bit.CONV12=12;AdcRegs.CHSELSEQ4.bit.CONV13=13;A
20、dcRegs.CHSELSEQ4.bit.CONV14=14;AdcRegs.CHSELSEQ4.bit.CONV15=15;AdcRegs.ADCTRL3.bit.ADCBGRFDN=3;AdcRegs.ADCTRL3.bit.ADCPWDN=1;AdcRegs.ADCTRL3.bit.ADCCLKPS=8;AdcRegs.ADCTRL3.bit.SMODE_SEL=1;AdcRegs.ADC_ST_FLAG.bit.INT_SEQ1_CLR=1;AdcRegs.ADC_ST_FLAG.bit.INT_SEQ2_CLR=1;AdcRegs.ADCTRL2.bit.EVB_SOC_SEQ=0;
21、AdcRegs.ADCTRL2.bit.RST_SEQ1=0;AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1=1;AdcRegs.ADCTRL2.bit.INT_MOD_SEQ1=0;AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1=0;AdcRegs.ADCTRL2.bit.EXT_SOC_SEQ1=0;AdcRegs.ADCTRL2.bit.RST_SEQ2=0;AdcRegs.ADCTRL2.bit.SOC_SEQ2=0;AdcRegs.ADCTRL2.bit.INT_ENA_SEQ2=0;AdcRegs.ADCTRL2.bit.INT_MOD_SEQ2
22、=0;AdcRegs.ADCTRL2.bit.EVB_SOC_SEQ2=0;15 / 16七、实验结果:1、SEEDDEC2812 单元的 D3 灯由闪烁变成常暗。2、可以看到失真比较大的 FFT 波形,如下图所示:1) 、失真信号及频域图:2) 、周 期信号时域和频域曲线图:含有随机噪声的周期信号频域圈16 / 16八、实验心得:熟悉了在 CCS 集成开发环境下,新建工程,并且运行,在此过程中,可以通过观察内存中的位变化来查看实验结果,除此之外还可以通过在计算机上查看与实验箱平台相同步的波形查看器,可以清楚地看到它的 FFT 波形,虽然不是很准确。加深了对 DFT 算法及 FFT 算法的了解
23、,快速傅氏变换(FFT)是离散傅氏变换的快速算法,它是根据离散傅氏变换的奇、偶、虚、实等特性,对离散傅立叶变换的算法进行改进获得的。它对傅氏变换的理论并没有新的发现,但是对于在计算机系统或者说数字系统中应用离散傅立叶变换,可以说是进了一大步。 设 x(n)为 N 项的复数序列,由 DFT 变换,任一 X(m)的计算都需要 N 次复数乘法和N-1 次复数加法,而一次复数乘法等于四次实数乘法和两次实数加法,一次复数加法等于两次实数加法,即使把一次复数乘法和一次复数加法定义成一次“运算”(四次实数乘法和四次实数加法),那么求出 N 项复数序列的 X(m),即 N 点 DFT 变换大约就需要 N2 次
24、运算。当 N=1024 点甚至更多的时候,需要 N2=1048576 次运算,在 FFT 中,利用 WN 的周期性和对称性,把一个 N 项序列(设 N=2k,k 为正整数),分为两个 N/2 项的子序列,每个 N/2点 DFT 变换需要(N/2)2 次运算,再用 N 次运算把两个 N/2 点的 DFT 变换组合成一个 N 点的 DFT 变换。这样变换以后,总的运算次数就变成 N+2(N/2)2=N+N2/2。继续上面的例子,N=1024 时,总的运算次数就变成了 525312 次,节省了大约 50%的运算量。而如果我们将这种“一分为二”的思想不断进行下去,直到分成两两一组的 DFT 运算单元,
25、那么 N 点的DFT 变换就只需要 Nlog2N 次的运算,N 在 1024 点时,运算量仅有 10240 次,是先前的直接算法的 1%,点数越多,运算量的节约就越大,这就是 FFT 的优越性;FFT 算法的输出 X(K)为自然顺序,但为了适应原位计算,其输入序列不是按 x(n)的自然顺序排序,这种经过 M-1 次奇偶抽选后的排序为序列的倒序。因此,在运算之前应先对序列 x(n)进行倒序。倒序的规律就是把顺序数的二进制位倒置,即可得到倒序值。倒序数是在 M 位二进制数最高位加一,逢 2 向右进位。对于 FFT,M 位二进制数最高位的权值为 N/2,且从左到右二进制位的权值依次为你 N/4,N/8,2,1。因此,最高位加一相当于十进制运算J+N/2。 (J 表示当前倒序数的十进制数值) 。