各位仁兄好! 现在我在调试FFT的时候遇见好多问题,前面都解决掉了,就是FFT转换成幅值mag的时候怎么都不正确。 我的调用方法如下(刚刚从网上直接修改的网友代码,和我的大同小异):
#include "DSP281x_Device.h" // DSP281x Headerfile Include File #include "DSP281x_Examples.h" // DSP281x Examples Include File
/* for test fft */ #include "fft.h"
// Prototype statements for functions found within this file. interrupt void adc_isr(void);
// Global variables used in this example: Uint16 LoopCount; Uint16 ConversionCount; Uint16 Voltage1[128];
#define N 128 //FFT Length #pragma DATA_SECTION(ipcb, "FFTipcb"); #pragma DATA_SECTION(mag,"FFTmag");
RFFT32 fft=RFFT32_128P_DEFAULTS;
long ipcb[N+2]; //In place computation buffer(这里直接用的RFFT,所以长度是N+2) long mag[N/2+1]; //Magnitude buffer const long win[N/2]=HAMMING128; //Window coefficient array
RFFT32_ACQ acq=FFTRACQ_DEFAULTS; //Instance the module
main() { int i;
InitSysCtrl();//初始化cpu DINT;//关中断 InitPieCtrl();//初始化pie寄存器
/* Initialize acquisition module */ acq.buffptr=ipcb; acq.tempptr=ipcb; acq.size=N; acq.count=N; acq.acqflag=1;
/* Initialize FFT module */ fft.ipcbptr=ipcb; fft.magptr=mag;// 这里是调用新的存储空间存储幅值 fft.init(&fft);
IER = 0x0000;//禁止所有的中断 IFR = 0x0000;
InitPieVectTable();//初始化pie中断向量表
// Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected register PieVectTable.ADCINT = &adc_isr; EDIS; // This is needed to disable write to EALLOW protected registers
AdcRegs.ADCTRL1.bit.RESET = 1; // Reset the ADC module asm(" RPT #10 || NOP"); // Must wait 12-cycles (worst-case) for ADC reset to take effect AdcRegs.ADCTRL3.all = 0x00C8; // first power-up ref and bandgap circuits AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3; // Power up bandgap/reference circuitry AdcRegs.ADCTRL3.bit.ADCPWDN = 1; // Power up rest of ADC
// Enable ADCINT in PIE
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; IER |= M_INT1; // Enable CPU Interrupt 1 EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM
LoopCount = 0; ConversionCount = 1;
// Configure ADC AdcRegs.ADCMAXCONV.all = 0x0001; // Setup 2 conv's on SEQ1 AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA3 as 1st SEQ1 conv. AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Setup ADCINA2 as 2nd SEQ1 conv. AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1; // Enable EVASOC to start SEQ1 AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Enable SEQ1 interrupt (every EOS)
// Configure EVA // Assumes EVA Clock is already enabled in InitSysCtrl(); EvaRegs.T2CMPR = 0x0000; // Setup T1 compare value 这里改了 我的采样是6.4k的,用的t2计数器,具体设置应该没错
EvaRegs.T1PR = ; // Setup period register EvaRegs.GPTCONA.bit.T1TOADC = 1; // Enable EVASOC in EVA EvaRegs.T1CON.all = 0x1042; // Enable timer 1 compare (upcount mode)
// Wait for ADC interrupt while(1) { //LoopCount++; if (acq.acqflag==0) // If the samples are acquired { DINT; //RFFT32_brev(ipcb,ipcb,N); //RFFT32_brev(ipcb,ipcb,N); // Input samples in Real Part // 这里不知道为什么 会调用两次(FFT库的调用例子是这样做的) fft.win(&fft);
//RFFT32_brev(ipcb,ipcb,N); //RFFT32_brev(ipcb,ipcb,N); // Input samples in Real Part // 这里不知道为什么 会调用两次(FFT库的调用例子是这样做的)
fft.calc(&fft); fft.split(&fft); fft.mag(&fft); for(i=0;i<N;i++) { mag=sqrt(mag); //这里调用后mag只有在i==0,i==1的时候有比较大的值,其他点都很小, //我用的是50hz的正弦信号,理论上mag[0]应该是DC分量(好像是N倍的关系), //mag[1]应该是50hz的信号幅值(N/2倍的关系),但是实际计算出来不对, //我不送信号和送信号的时候这里的计算值基本上不变,我再调节信号幅值后, //mag[1]是变化的(不稳定),理论上这里出来的值是稳定的,信号的幅值, //实际不是,请网友们帮我看看问题出在哪里。我实在是头大了。 } acq.acqflag=1; // Enable the next acquisition EINT; } } }
interrupt void adc_isr(void) { Voltage1[ConversionCount] = AdcRegs.ADCRESULT0>>4;
if(acq.acqflag==1) { acq.input=((unsigned long)Voltage1[ConversionCount])<<16; acq.update(&acq); } // Reinitialize for next ADC sequence AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; // Reset SEQ1 AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear INT SEQ1 bit PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge interrupt to PIE }
|