打印

TMS320F28335 FFT后发现与真实幅值差别很大

[复制链接]
5036|60
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 williamzjy 于 2017-4-5 14:48 编辑
用TMSF28335的ADC模块以8.3MHz的采样率采样函数发生器产生的24KHz正弦波(0--2V)做FFT分析验证,现发现采样是准确的,运算的频点分布也是正确的,可是FFT后的RFFTmagBuff怎么和真实的信号幅值对不上啊,直流分量1V,信号幅值1V,不知道我理解的对不对,
还有就是
RFFT_adc_f32u(&rfft_adc);   // This version of FFT doesn't need buffer alignment这个和RFFT_f32u(&rfft_adc)有什么区别,我同时还发现AdcMirror.ADCRESULT0不用右移4位了,本身就是右对齐的,之前右移四位,运算完全是0,求各位指点怎么和信号真实幅值对上,好像*2/N也不对啊。。。表示疑惑
/*采样不连续率提高到8.3M,之前的不准确,连续采样可以有8.3M的采样率 2017.03.19*/
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File

#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include "math.h"
#include "fpu_rfft.h"

#define RFFT_STAGES 10
#define RFFT_SIZE (1 << RFFT_STAGES)

#define ADC_BUF_LEN RFFT_SIZE // ADC buffer length
//#define ADC_SAMPLE_PERIOD 3124 // 3124 = (3125-1) = 48 KHz sampling w/ 150 MHz SYSCLKOUT

#define F_PER_SAMPLE 8300000.0L/(float)RFFT_SIZE //Internal sampling rate is 48kHz

RFFT_ADC_F32_STRUCT rfft_adc;
RFFT_F32_STRUCT rfft;

float RFFToutBuff[RFFT_SIZE]; //Calculated FFT result
float RFFTF32Coef[RFFT_SIZE]; //Coefficient table buffer
float RFFTmagBuff[RFFT_SIZE/2+1]; //Magnitude of frequency spectrum

//--- Global Variables
//uint16_t AdcBuf[ADC_BUF_LEN]; // ADC buffer allocation

volatile uint16_t FFTStartFlag = 0; // One frame data ready flag



// ADC start parameters
#if (CPU_FRQ_150MHZ) // Default - 150 MHz SYSCLKOUT
#define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
#endif
#if (CPU_FRQ_100MHZ)
#define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2) = 25.0 MHz
#endif

#define CPU_FREQ 150E6
#define LSPCLK_FREQ CPU_FREQ/4
#define SCI_FREQ 115200
#define SCI_PRD (LSPCLK_FREQ/(SCI_FREQ*8))-1

interrupt void sciaRxFifoIsr(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void scia_msg(Uint16 *msg);

Uint16 sdataA[160]; // Send data for SCI-A
Uint16 rdataA[160]; // Received data for SCI-A


#define ADC_CKPS 0x0 // ADC module clock = HSPCLK/1 = 25.5MHz/(1) = 25.0 MHz
#define ADC_SHCLK 0x1 // S/H width in ADC module periods = 2 ADC cycle
//#define BUF_SIZE 160 // Sample buffer size

// Global variable for this example
//Uint16 j = 0,ADC_END = 0; // ADC finish flag

//#pragma DATA_SECTION(ADC_Result,"DMARAML4");
//volatile float ADC_Result[160];

#pragma DATA_SECTION(AdcBuf,"DMARAML6L7");
//volatile Uint16 AdcBuf[ADC_BUF_LEN];
uint16_t AdcBuf[ADC_BUF_LEN];
float AdcBuf2[ADC_BUF_LEN];

volatile Uint16 *DMADest;
volatile Uint16 *DMASource;
interrupt void local_DINTCH1_ISR(void);



main()
{
uint16_t i,j;
float freq; // Frequency of single-frequency-component signal

InitSysCtrl();
InitSciaGpio();

EALLOW;
SysCtrlRegs.HISPCP.all = ADC_MODCLK; // HSPCLK = SYSCLKOUT/ADC_MODCLK
EDIS;


DINT;

InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;

InitPieVectTable();

// #ifdef FLASH
// MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
// InitFlash();
// #endif

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // Allow access to EALLOW protected registers
PieVectTable.DINTCH1= &local_DINTCH1_ISR;
PieVectTable.SCIRXINTA = &sciaRxFifoIsr;

EDIS; // Disable access to EALLOW protected registers

rfft_adc.Tail = &rfft.OutBuf; //Link the RFFT_ADC_F32_STRUCT to
//RFFT_F32_STRUCT. Tail pointer of
//RFFT_ADC_F32_STRUCT is passed to
//the OutBuf pointer of RFFT_F32_STRUCT
rfft.FFTSize = RFFT_SIZE; //Real FFT size
rfft.FFTStages = RFFT_STAGES; //Real FFT stages
rfft_adc.InBuf = &AdcBuf[0]; //Input buffer
rfft.OutBuf = &RFFToutBuff[0]; //Output buffer
rfft.CosSinBuf = &RFFTF32Coef[0]; //Twiddle factor
rfft.MagBuf = &RFFTmagBuff[0]; //Magnitude output buffer

RFFT_f32_sincostable(&rfft); //Calculate twiddle factor

//Clean up output buffer
for (i=0; i < RFFT_SIZE; i++)
{
RFFToutBuff[i] = 0;
}

//Clean up magnitude buffer
for (i=0; i < RFFT_SIZE/2+1; i++)
{
RFFTmagBuff[i] = 0;
}


scia_fifo_init(); // Init SCI-A

// EnableInterrupts();
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block
PieCtrlRegs.PIEIER9.bit.INTx1=1; // PIE Group 9, int1


PieCtrlRegs.PIEIER7.bit.INTx1 = 1;
IER |= 0x100; // Enable CPU INT
IER |= M_INT7 ; //Enable INT7 (7.1 DMA Ch1)

EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

InitAdc(); // For this example, init the ADC

// Specific ADC setup for this example:
AdcRegs.ADCTRL1.bit.ACQ_PS = ADC_SHCLK; // Sequential mode: Sample rate = 1/[(2+ACQ_PS)*ADC clock in ns]
// = 1/(3*40ns) =8.3MHz (for 150 MHz SYSCLKOUT)
// = 1/(3*80ns) =4.17MHz (for 100 MHz SYSCLKOUT)
// If Simultaneous mode enabled: Sample rate = 1/[(3+ACQ_PS)*ADC clock in ns]
AdcRegs.ADCTRL3.bit.ADCCLKPS = ADC_CKPS;
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 1 Cascaded mode
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1;// Enable SOCA from ePWM to start SEQ1
AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Enable SEQ1 interrupt (every EOS)
AdcRegs.ADCTRL2.bit.RST_SEQ1 = 0x1;
// AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0;

AdcRegs.ADCTRL1.bit.CONT_RUN = 1; // Setup continuous run

AdcRegs.ADCTRL1.bit.SEQ_OVRD = 0; // Enable Sequencer override feature

AdcRegs.ADCCHSELSEQ1.all = 0x0; // Initialize all ADC channel selects to A0
AdcRegs.ADCCHSELSEQ2.all = 0x0; // Initialize all ADC channel selects to A0
AdcRegs.ADCCHSELSEQ3.all = 0x0; // Initialize all ADC channel selects to A0
AdcRegs.ADCCHSELSEQ4.all = 0x0; // Initialize all ADC channel selects to A0

AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 15; // convert and store in 8 results registers



// Assumes ePWM1 clock is already enabled in InitSysCtrl();
// EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // Select SOC from from CPMA on upcount
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EPwm1Regs.CMPA.half.CMPA = 150; // Set compare A value
EPwm1Regs.TBPRD =300; // Set period for ePWM1
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // count up and start



// EALLOW;
/* 在 InitSysCtrl()中已经将ePWM1的时钟进行了使能 */
/* 用来配置ADC的采样率 */

// SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Disable TBCLK within the ePWM

/* ePWM1的相关配置,以供片内ADC的启动 */
// EPwm1Regs.TBCTL.bit.CLKDIV = 0;
// EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; /* TBCLK = SYSCLK/2 = 75MHz*/
// EPwm1Regs.ETSEL.bit.SOCAEN = 1; /* 使能ADC开始转换A脉冲,使能ePWMxSOCA脉冲 */
// EPwm1Regs.ETSEL.bit.SOCASEL = 4;/* 使能,ePWMxSOCA脉冲当定时器递增时时间基准计数器等于CMPA */
// EPwm1Regs.ETPS.bit.SOCAPRD = 1; /* 在第一个事件上生成ePWMxSOCA脉冲 */

// EPwm1Regs.TBPRD = 750; /* 设置时间基准计数器的周期,决定 PWM1的频率 */
// EPwm1Regs.CMPA.half.CMPA = 150; // Set compare A value
// EPwm1Regs.TBCTR = 0; /* 清空计数器 */
// EPwm1Regs.TBCTL.bit.CTRMODE = 0; /* 设置计数器模式为递增计数模式 */
// SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Enable TBCLK within the ePWM

// EDIS;



// Initialize DMA
DMAInitialize();

// Clear Table
for (i=0; i<ADC_BUF_LEN; i++)
{
AdcBuf[i] = 0x0000;
}


// Configure DMA Channel
DMADest = &AdcBuf[0]; //Point DMA destination to the beginning of the array
DMASource = &AdcMirror.ADCRESULT0; //Point DMA source to ADC result register base
DMACH1AddrConfig(DMADest,DMASource);
DMACH1BurstConfig(15,2,2);
DMACH1TransferConfig(63,-14,2);
DMACH1WrapConfig(600,600,600,600); //Don't use wrap function
DMACH1ModeConfig(DMA_SEQ1INT,PERINT_ENABLE,ONESHOT_DISABLE,CONT_ENABLE,SYNC_DISABLE,SYNC_SRC,
OVRFLOW_DISABLE,THIRTYTWO_BIT,CHINT_END,CHINT_ENABLE);



StartDMACH1();


EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group

while(1)
{
// Waiting ADC finish





if(FFTStartFlag) // If one frame data ready, then do FFT
{
for (i=0; i<ADC_BUF_LEN; i++)
{
AdcBuf2[i] = (float)((AdcBuf[i]) * 3.0 / 4096.0);//不用右移4位了?之前一直右移4位,发现全是0
}


RFFT_adc_f32u(&rfft_adc); // This version of FFT doesn't need buffer alignment
RFFT_f32_mag(&rfft); // Calculate spectrum amplitude

j = 1;
freq = RFFTmagBuff[1];
for(i=2;i<RFFT_SIZE/2+1;i++)
{
//Looking for the maximum valude of spectrum magnitude
if(RFFTmagBuff[i] > freq)
{
j = i;
freq = RFFTmagBuff[i];
}
}

freq = F_PER_SAMPLE * (float)j; //Convert normalized digital frequency to analog frequency

FFTStartFlag = 0; //Start collecting the next frame of data
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOC on A group
AdcRegs.ADCTRL1.bit.CONT_RUN = 1;
}


}




}

// INT7.1
interrupt void local_DINTCH1_ISR(void) // DMA Channel 1
{

// To receive more interrupts from this PIE group, acknowledge this interrupt
DMADest = &AdcBuf[0]; //Point DMA destination to the beginning of the array
DMASource = &AdcMirror.ADCRESULT0; //Point DMA source to ADC result register base
EPwm1Regs.ETSEL.bit.SOCAEN = 0; // DISable SOC on A group
AdcRegs.ADCTRL1.bit.CONT_RUN = 0;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
FFTStartFlag = 1; // One frame data ready
// EPwm1Regs.TBCTL.bit.CTRMODE = 1; // count up and start
// EPwm1Regs.TBCTR = 0; /* 清空计数器 */





}

interrupt void sciaRxFifoIsr(void)
{
// rdataA[0]=SciaRegs.SCIRXBUF.all; // Read data
// scia_xmit(rdataA[0]);
Uint16 i;

for(i=0; i< 12; i++)
{
rdataA[i]=SciaRegs.SCIRXBUF.all; // Read data
}

for(i=0; i< 12; i++)
{
SciaRegs.SCITXBUF=rdataA[i]; // Send data
}

//SciaRegs.SCIFFRX.bit.RXFFOVRCLR=1; // Clear Overflow flag
SciaRegs.SCIFFRX.bit.RXFFINTCLR=1; // Clear Interrupt flag
PieCtrlRegs.PIEACK.all|=0x100; // Issue PIE ack
}

void scia_fifo_init()
{
SciaRegs.SCICCR.all =0x0007; // 1 stop bit, No loopback
// No parity,8 char bits,
// async mode, idle-line protocol
SciaRegs.SCICTL1.all =0x0003; // enable TX, RX, internal SCICLK,
// Disable RX ERR, SLEEP, TXWAKE
SciaRegs.SCICTL2.bit.TXINTENA =1;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;
SciaRegs.SCIHBAUD = 0x0000;
SciaRegs.SCILBAUD = SCI_PRD;
SciaRegs.SCICCR.bit.LOOPBKENA =0; // disEnable loop back
SciaRegs.SCIFFTX.all=0xC021;
SciaRegs.SCIFFRX.all=0x0021;//接收12个字节中断
SciaRegs.SCIFFCT.all=0x00;

SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
SciaRegs.SCIFFTX.bit.TXFIFOXRESET=1;
SciaRegs.SCIFFRX.bit.RXFIFORESET=1;


}


// Transmit a character from the SCI
void scia_xmit(int a)
{
while (SciaRegs.SCICTL2.bit.TXRDY == 0) {}
SciaRegs.SCITXBUF=a;

}


void scia_msg(Uint16 * msg)
{
int i;
i = 0;
while(msg[i] != '\0')
{
scia_xmit(msg[i]);
i++;
}
}

//===========================================================================
// No more.
//===========================================================================

</P>

111.png (44.85 KB )

仿真寄存器值

仿真寄存器值

相关帖子

沙发
uiint| | 2017-4-5 21:52 | 只看该作者
你的变量定义的对不对

使用特权

评论回复
板凳
uiint| | 2017-4-5 21:56 | 只看该作者
这个149/采样频率才是最后数值

使用特权

评论回复
地板
williamzjy|  楼主 | 2017-4-6 09:46 | 只看该作者
谢谢回复,仔细想了下,考虑到采样的不完整,频谱泄漏的情况,得到的模值大体符合傅立叶公式

使用特权

评论回复
5
youtome| | 2017-4-6 15:25 | 只看该作者
直流分量在0位置上。

使用特权

评论回复
6
youtome| | 2017-4-6 15:34 | 只看该作者
幅值和采样频率、采样点数有计算关系。

使用特权

评论回复
7
jstgotodo| | 2017-4-7 22:11 | 只看该作者
你的其他数据呢?

使用特权

评论回复
8
jstgotodo| | 2017-4-7 22:12 | 只看该作者
计算的幅值/数组个数计算。

使用特权

评论回复
9
232321122| | 2017-4-8 22:11 | 只看该作者
你使用波形显示看过了吗

使用特权

评论回复
10
232321122| | 2017-4-8 22:14 | 只看该作者
可能ADC采样有什么问题吧。

使用特权

评论回复
11
febgxu| | 2017-4-9 16:24 | 只看该作者
你算的幅值是多大?

使用特权

评论回复
12
febgxu| | 2017-4-9 16:24 | 只看该作者
楼主的FFT计算之后的频率是多大的?

使用特权

评论回复
13
febgxu| | 2017-4-9 16:28 | 只看该作者
如果是做固定频率识别可以做DFT。

使用特权

评论回复
14
williamzjy|  楼主 | 2017-4-10 09:07 | 只看该作者
谢谢大家的热情回复,我需要做标签信号波形分析,想从FFT中发现单张和多张标签的幅值规律,发现特征,写个算法,可是信号太窄,只有1US,但是一个信号的周期是10ms,我的采样率是8.3M的,数据量太大,几万个点,不好处理啊,有什么好的办法吗?怎么减少采样点

使用特权

评论回复
15
steelen| | 2017-4-10 13:42 | 只看该作者
呵呵,有难度

使用特权

评论回复
16
i1mcu| | 2017-4-10 21:01 | 只看该作者
williamzjy 发表于 2017-4-10 09:07
谢谢大家的热情回复,我需要做标签信号波形分析,想从FFT中发现单张和多张标签的幅值规律,发现特征,写个 ...

DSP做1024就很慢了,周期太大了。

使用特权

评论回复
17
i1mcu| | 2017-4-10 21:03 | 只看该作者
williamzjy 发表于 2017-4-10 09:07
谢谢大家的热情回复,我需要做标签信号波形分析,想从FFT中发现单张和多张标签的幅值规律,发现特征,写个 ...

信号频率太低,采样计算也不容易,试试DFT。

使用特权

评论回复
18
vivilzb1985| | 2017-4-11 23:05 | 只看该作者
这个需要注意AD采样率的设计的

使用特权

评论回复
19
minzisc| | 2017-4-13 20:28 | 只看该作者
执行的效率怎么样?

使用特权

评论回复
20
minzisc| | 2017-4-13 20:36 | 只看该作者
8.3MHz这么高频率采样怎么样?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

72

帖子

8

粉丝