本帖最后由 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] != ' ')
- {
- scia_xmit(msg[i]);
- i++;
- }
- }
- //===========================================================================
- // No more.
- //===========================================================================
- </P>
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>