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

2019-07-17 15:54发布

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

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

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

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

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

  15. RFFT_ADC_F32_STRUCT rfft_adc;
  16. RFFT_F32_STRUCT rfft;

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

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

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



  23. // ADC start parameters
  24. #if (CPU_FRQ_150MHZ) // Default - 150 MHz SYSCLKOUT
  25. #define ADC_MODCLK 0x3 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*3) = 25.0 MHz
  26. #endif
  27. #if (CPU_FRQ_100MHZ)
  28. #define ADC_MODCLK 0x2 // HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 100/(2*2) = 25.0 MHz
  29. #endif

  30. #define CPU_FREQ 150E6
  31. #define LSPCLK_FREQ CPU_FREQ/4
  32. #define SCI_FREQ 115200
  33. #define SCI_PRD (LSPCLK_FREQ/(SCI_FREQ*8))-1

  34. interrupt void sciaRxFifoIsr(void);
  35. void scia_fifo_init(void);
  36. void scia_xmit(int a);
  37. void scia_msg(Uint16 *msg);

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


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

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

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

  47. #pragma DATA_SECTION(AdcBuf,"DMARAML6L7");
  48. //volatile Uint16 AdcBuf[ADC_BUF_LEN];
  49. uint16_t AdcBuf[ADC_BUF_LEN];
  50. float AdcBuf2[ADC_BUF_LEN];

  51. volatile Uint16 *DMADest;
  52. volatile Uint16 *DMASource;
  53. interrupt void local_DINTCH1_ISR(void);



  54. main()
  55. {
  56. uint16_t i,j;
  57. float freq; // Frequency of single-frequency-component signal

  58. InitSysCtrl();
  59. InitSciaGpio();

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


  63. DINT;

  64. InitPieCtrl();

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

  68. InitPieVectTable();

  69. // #ifdef FLASH
  70. // MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
  71. // InitFlash();
  72. // #endif

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

  78. EDIS; // Disable access to EALLOW protected registers

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

  89. RFFT_f32_sincostable(&rfft); //Calculate twiddle factor

  90. //Clean up output buffer
  91. for (i=0; i < RFFT_SIZE; i++)
  92. {
  93. RFFToutBuff[i] = 0;
  94. }

  95. //Clean up magnitude buffer
  96. for (i=0; i < RFFT_SIZE/2+1; i++)
  97. {
  98. RFFTmagBuff[i] = 0;
  99. }


  100. scia_fifo_init(); // Init SCI-A

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


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

  107. EINT; // Enable Global interrupt INTM
  108. ERTM; // Enable Global realtime interrupt DBGM

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

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

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

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

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

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



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



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

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

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

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

  150. // EDIS;



  151. // Initialize DMA
  152. DMAInitialize();

  153. // Clear Table
  154. for (i=0; i<ADC_BUF_LEN; i++)
  155. {
  156. AdcBuf[i] = 0x0000;
  157. }


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



  167. StartDMACH1();


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

  169. while(1)
  170. {
  171. // Waiting ADC finish





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


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

  180. j = 1;
  181. freq = RFFTmagBuff[1];
  182. for(i=2;i<RFFT_SIZE/2+1;i++)
  183. {
  184. //Looking for the maximum valude of spectrum magnitude
  185. if(RFFTmagBuff[i] > freq)
  186. {
  187. j = i;
  188. freq = RFFTmagBuff[i];
  189. }
  190. }

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

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


  196. }




  197. }

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

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





  210. }

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

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

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

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

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

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


  246. }


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

  252. }


  253. void scia_msg(Uint16 * msg)
  254. {
  255. int i;
  256. i = 0;
  257. while(msg[i] != '')
  258. {
  259. scia_xmit(msg[i]);
  260. i++;
  261. }
  262. }

  263. //===========================================================================
  264. // No more.
  265. //===========================================================================

  266. </P>
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
19条回答
uiint
1楼-- · 2019-07-17 19:02
你的变量定义的对不对
uiint
2楼-- · 2019-07-17 19:28
这个149/采样频率才是最后数值
williamzjy
3楼-- · 2019-07-18 00:36
谢谢回复,仔细想了下,考虑到采样的不完整,频谱泄漏的情况,得到的模值大体符合傅立叶公式
youtome
4楼-- · 2019-07-18 01:19
直流分量在0位置上。
youtome
5楼-- · 2019-07-18 02:28
幅值和采样频率、采样点数有计算关系。
jstgotodo
6楼-- · 2019-07-18 08:24
 精彩回答 2  元偷偷看……

一周热门 更多>