本帖最后由 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>
|