各位仁兄好!
现在我在调试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
}
|