This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F280025C:RFFT 代码计算可提供全部零和大量警告

Guru**** 2460850 points
Other Parts Discussed in Thread: TMS320F280025C, C2000WARE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1029202/tms320f280025c-rfft-code-calculations-giving-all-zeros-and-lots-of-warnings

器件型号:TMS320F280025C
主题中讨论的其他器件: C2000WARE

我已经修改了用于计算 TMS320F280025C 中64点 RFFT 的 RFFT 示例代码。  实现 RFFT 的完整主代码文件如下所示:

//#############################################################################
//
// FILE:   main.c
//
//
//
//#############################################################################
// $TI Release: F28002x Support Library v3.04.00.00 $
// $Release Date: Fri Feb 12 18:58:34 IST 2021 $
// $Copyright:
// Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################

//
// Included Files
//
// Select the global Q value to use:
#define GLOBAL_Q    17
#define FFT_SIZE    64
//long GlobalQ = GLOBAL_Q;      // Used for legacy GEL & Graph Debug.

#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "IQmathLib.h"
#include <stdio.h>
#include <file.h>
#include "sci_io_driverlib.h"
#include "fft.h"
#include "fft_hamming_Q31.h"
#include "math.h"

//
// Globals
//
uint16_t sData[32];                // Send data buffer for DMA transmission
uint16_t rData[32];                // Receive data buffer for DMA reception

//Defining FFT sections
#pragma DATA_SECTION(ipcb, "FFTipcb");
int32_t ipcb[FFT_SIZE+2];         //Calculations buffer
#pragma DATA_SECTION(ipcbsrc, "FFTipcbsrc");
int32_t ipcbsrc[FFT_SIZE];        //Sampled input signal
//Defining real fft object for 64 point calculations
RFFT32  rfft = RFFT32_64P_DEFAULTS;

// Place buffers in GSRAM so that DMA can access these
#pragma DATA_SECTION(sData, "ramgs0");
#pragma DATA_SECTION(rData, "ramgs0");
//
// Function Prototypes
void init_SPI_FIFO(void);
//
// Function Prototypes for Interrupt
//
extern __interrupt void controlISR(void);
extern __interrupt void jemADCISR(void);
extern __interrupt void cpuTimer0ISR(void);
extern __interrupt void dmaCh5ISR(void);
extern __interrupt void dmaCh6ISR(void);
void initCPUTimers(void);
void configCPUTimer(uint32_t, float, float);

const long win[FFT_SIZE/2]=HAMMING64;
void main(void)
{
    volatile int status = 0;
    volatile FILE *fid;
    int i = 0;
    //
    float RadStep = 0.1963495408494f;
    float Rad = 0.0f;
    float temp1;
    int temp2;

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pull-ups.
    //
    Device_initGPIO();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Interrupts that are used in this example are re-mapped to ISR functions
    // found within this file.
    //
    Interrupt_register(INT_TIMER0, &cpuTimer0ISR);
    Interrupt_register(INT_ADCA1, &controlISR);
    Interrupt_register(INT_ADCA2, &jemADCISR);
    //
    // Configuring interrupts for DMA transmit and receive channels
    Interrupt_register(INT_DMA_CH5, &dmaCh5ISR);
    Interrupt_register(INT_DMA_CH6, &dmaCh6ISR);

    //
    // Configure all peripherals and analog/digital GPIOs
    //
    Board_init();

    //Initialize ADCs. Not generated by the sysconfig tool.
    ADC_init();

    //
    //EPWM initialization code.Needs to be configured separately as current
    // tool version does not support this module
    //
    EPWM_init();

    // Set up DMA for SPI use, initialize the SPI for FIFO mode
    initDMA();
    //initSPI();

    // Enable interrupts required for DMA send and receive
    //
    Interrupt_enable(INT_DMA_CH5);
    Interrupt_enable(INT_DMA_CH6);

    //Initialize Timer
    initCPUTimers();

    // Configure CPU-Timer 0 to interrupt every 100000 u seconds:
    //
    configCPUTimer(CPUTIMER0_BASE, DEVICE_SYSCLK_FREQ, 100000);
    CPUTimer_enableInterrupt(CPUTIMER0_BASE);
    Interrupt_enable(INT_TIMER0);
    Interrupt_enable(INT_ADCA1);
    Interrupt_enable(INT_ADCA2);

    //
    // Enable Global Interrupt (INTM) and real time interrupt (DBGM)
    //
    EINT;
    ERTM;

    // Redirect STDOUT to SCI
    status = add_device("scia", _SSA, SCI_open, SCI_close, SCI_read, SCI_write,
                        SCI_lseek, SCI_unlink, SCI_rename);
    fid = fopen("scia", "w");
    freopen("scia:", "w", stdout);
    setvbuf(stdout, NULL, _IONBF, 0);

    //Prints welcome message on debug SCI
    printf("Skyelectric");
    DEVICE_DELAY_US(10000);

    init_SPI_FIFO();

    // Start the DMA channels
    //
    DMA_startChannel(DMA_CH6_BASE);
    DMA_startChannel(DMA_CH5_BASE);

    //------------------------------------
    CPUTimer_startTimer(CPUTIMER0_BASE);

    //Temporary code for implementing FFT
    for (i=0;i<FFT_SIZE;i++)
    {
        ipcbsrc[i]=(long)(2147483648*sinf(Rad));//Q31 format
        Rad=Rad+0.09817;
    }
    printf("\r\nSample Input:\r\n");
    for (i = 0; i < FFT_SIZE; i++)


        printf("%ld\r\n", ipcbsrc[i]);
    }

    RFFT32_brev(ipcbsrc, ipcb, FFT_SIZE); // real FFT bit reversing

    rfft.ipcbptr = ipcb;                  // FFT computation buffer
    rfft.magptr  = ipcbsrc;               // Magnitude output buffer
    rfft.winptr  = (long *)win;           // Window coefficient array
    rfft.init(&rfft);                     // Twiddle factor pointer initialization

    rfft.calc(&rfft);                     // Compute the FFT
    rfft.split(&rfft);                    // Post processing to get the correct spectrum
    rfft.mag(&rfft);                      // Q31 format (abs(ipcbsrc)/2^16).^2


    printf("\r\nFFT Result:\r\n");
    for (i = 0; i < FFT_SIZE; i++)
    {
         printf("%ld\r\n", ipcbsrc[i]);
    }
    for (;;)
    {

        DEVICE_DELAY_US(1000000);    //one second delay

    }
}

void init_SPI_FIFO(void)
{
    int i;
    for (i = 0; i < 32; i++)
        sData[i] = i;
}

编译过程会引发以下大量错误:

项目的链接器设置如下所示:

下面显示了链接器命令文件、以检查 FFT 段是否已正确分配。

MEMORY
{
   BEGIN           	: origin = 0x080000, length = 0x000002
   BOOT_RSVD		: origin = 0x00000002, length = 0x00000126
   RAMM0           	: origin = 0x00000128, length = 0x000002D8
   RAMM1            : origin = 0x00000400, length = 0x000003F8     /* on-chip RAM block M1 */
// RAMM1_RSVD       : origin = 0x000007F8, length = 0x00000008 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */

/* RAMLS4           : origin = 0x0000A000, length = 0x00000800
   RAMLS5           : origin = 0x0000A800, length = 0x00000800
   RAMLS6           : origin = 0x0000B000, length = 0x00000800
   RAMLS7           : origin = 0x0000B800, length = 0x00000800*/

   /* Combining all the LS RAMs */
   RAMLS4567        : origin = 0x0000A000, length = 0x00002000
   RAMGS0           : origin = 0x0000C000, length = 0x000007F8
// RAMGS0_RSVD      : origin = 0x0000C7F8, length = 0x00000008 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */


//  FLASHBANK1       : origin = 0x00080000, length = 0x0000FFF0
//  FLASH_BANK1_RSVD : origin = 0x0008FFF0, length = 0x00000010 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
   BOOTROM          : origin = 0x003F0000, length = 0x00008000
   BOOTROM_EXT      : origin = 0x003F8000, length = 0x00007FC0
   RESET            : origin = 0x003FFFC0, length = 0x00000002
   /*IQMath table already exists in the BOOTROM section*/
   //IQTABLES 		: origin = 0x3F1402, length = 0x0166D
   /* Flash sectors */
   /* BANK 0 */
   FLASH_BANK0_SEC0  : origin = 0x080002, length = 0x000FFE	/* on-chip Flash */
   FLASH_BANK0_SEC1  : origin = 0x081000, length = 0x001000	/* on-chip Flash */
   FLASH_BANK0_SEC2  : origin = 0x082000, length = 0x001000	/* on-chip Flash */
   FLASH_BANK0_SEC3_9  : origin = 0x083000, length = 0x007000	/* on-chip Flash */
   FLASH_BANK0_SEC10_11 : origin = 0x08A000, length = 0x002000	/* on-chip Flash */
   FLASH_BANK0_SEC12_15 : origin = 0x08C000, length = 0x003FF0	/* on-chip Flash */
   // FLASH_BANK0_SEC15_RSVD     : origin = 0x08FFF0, length = 0x000010  /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */

}


SECTIONS
{
   codestart        : > BEGIN, ALIGN(8)
   .text            : >> FLASH_BANK0_SEC2 | FLASH_BANK0_SEC3_9 ,   ALIGN(8)//executable code >> operator splits code
   .cinit           : > FLASH_BANK0_SEC1,  ALIGN(8)//table that initializes global variables
   .switch          : > FLASH_BANK0_SEC1,  ALIGN(8)
   .reset           : > RESET,                  TYPE = DSECT /* not used, Dummy Section*/

   .stack           : > RAMM1

   .init_array      : > FLASH_BANK0_SEC1,  ALIGN(8)
   .bss             : > RAMLS4567 //uninitialized global variables
   .bss:output      : > RAMLS4567
   .bss:cio         : > RAMGS0
   .const           : > FLASH_BANK0_SEC10_11,  ALIGN(8)
   .data            : > RAMLS4567 //initialized data
   .sysmem          : > RAMLS4567

    ramgs0 : > RAMGS0


   /* Allocate IQ math areas: */
   IQmath : > FLASH_BANK0_SEC1, PAGE = 0, ALIGN(4) /* Math Code */
   //IQmathTables : > FLASH_BANK0_SEC2, PAGE = 0, ALIGN(4)/*This was working*/
   IQmathTables : > FLASH_BANK0_SEC1, PAGE = 0, ALIGN(4)/*Moved to sector 1 to run from RAM.Need verification*/

   /* Allocating FFT areas: */
   FFTipcb 		: >> RAMGS0, ALIGN(256) //64 points FFT
   FFTipcbsrc	: >> RAMLS4567
   FFTtf        : > FLASH_BANK0_SEC12_15

  .TI.ramfunc      : LOAD = FLASH_BANK0_SEC1, //Flash bank0 sector 1 contaings time critical functions required to run from RAM
                  RUN = RAMGS0,
                  LOAD_START(RamfuncsLoadStart),
                  LOAD_SIZE(RamfuncsLoadSize),
                  LOAD_END(RamfuncsLoadEnd),
                  RUN_START(RamfuncsRunStart),
                  RUN_SIZE(RamfuncsRunSize),
                  RUN_END(RamfuncsRunEnd),
                  ALIGN(8)

}
/*
//===========================================================================
// End of file.
//===========================================================================
*/

请注意、我仅在一个月前就开始使用 TI 控制器、我不熟悉链接的命令文件、因此请验证是否正确分配了所有段。 如果能够修改这些分配 以获得更好的处理时间和更高效的内存使用、我将不胜感激。 同时、我将查看 C2000Ware 目录中的"定点 DSP 软件库"文档、以便在我结束时进行故障排除 我参考了为 f2838x 控制器编写的"FixedPoint_RFFT"项目。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    阿萨德

    [引用 userid="488051" URL"~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1029202/tms320f280025c-rfft-code-calculations-giving-all-zeros-and-lots-of-warnings "]编译过程会引发以下大量错误:

    经过大量调试后、我注意到第207行缺少"{"。 您能否添加它并查看它是否仍然存在?

    [引用 userid="488051" url="~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1029202/tms320f280025c-rfft-code-calculations-giving-all-zeros-and-lots-of-warnings "]链接器命令文件如下所示,用于检查 FFT 段是否已正确分配。

    您的 cmd 文件看起来正确。   通过执行 memcpy ((uint32_t *)&FFTfRunStart、(uint32_t *)&FFTfLoadStart、(uint32_t *)、确保将 FFTtf 和闪存中的任何表 memcpy 复制到代码中的 RAM 中、
    (uint32_t)&FFTtfLoadSize);此外、在 cmd 文件中、您应该指定以下内容:

    FFTtf:load = FLASHC,page = 0
    运行= RAML7、PAGE = 1
    load_start (_FFTtfLoadStart)、
    load_size (_FFTtfLoadSize)、
    run_start (_FFTtfRunStart)

    希望这对您有所帮助

    -Shantanu

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shanty:

      非常感谢您提供宝贵的反馈。 只是一个有关您的回复的小问题:编译器如何识别 FLASHC 和 RAML7?。 这些段未在我的链接器命令文件中定义。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    编译问题实际上是由于您指出缺少了小括号。 但是、对于 cmd 文件添加文本:编译器不识别"FLASHC"和"RAML7"。 我已根据链接器命令文件中的段和存储器定义修改了您建议的 cmd 文件加法器件、如下所示。  
    FFTtf:load = flash_BANK0_SEC12_15,
    运行= RAMLS4567、
    load_start (_FFTtfLoadStart)、
    load_size (_FFTtfLoadSize)、
    run_start (_FFTtfRunStart)

    请检查 上述 修改 是否可以包含在链接器命令文件中:

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    阿萨德

    是的、需要在 cmd 文件的"存储器"部分定义像'FLASHC"这样的存储器范围。 您可以根据需要更改范围和名称、但"段"部分需要遵循相同的命名规则。

    您的 FFTtf 看起来正常。 尽量匹配示例。 如果您遇到任何问题、请告诉我。

    -Shantanu

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shanty:
      我已经对正弦波上的 FFT 计算进行了一些基本测试、如下定义:

    对于(i=0 <FFT_SIZE;i++)

    ipcbsrc[i]=(long)(2147483648*(((sinf(2*3.14167*50*TS*I))+sinf(2*3.14167*150*TS*I))))/2);//50Hz 和150Hz 组件。

    其中 TS=1/3200、即采样频率为3200Hz。 采样长度为64点、因此频率 bin 为50Hz。 FFT 表目前是在闪存中定义的、不会加载到 RAM 中、因为我有一些问题、但我认为从 RAM 运行应该只具有性能增益。 如果我错了、请纠正我的问题。

    生成的正弦波如下所示:

    FFT 计算后、获得以下结果:
    0
    67109714
    0
    67104820
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    因此、我在第一个频率库(50Hz)和第三个频率库(150Hz)中正确地获得了两个谐波。 Q31格式的每个组件的大小应为2147483648/2=1073741824。 请告诉我如何将 RFFT32 (67109714)的 FFT 结果与预期结果(1073741824)相关联?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    阿萨德

    您的结果似乎按1/16进行缩放。 这可能是定点实现的函数。 我现在还没有机会深入了解这个问题。 让我在本周结束之前回到您的身边。  

    您可以尝试确保计算的幅度采用相同的 Q 格式。 文档指出、幅度结果在 Q30中。  

    对拖延表示歉意。  

    -Shantanu

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shanty:

      我将在周末等待您的回复。 还有一个小查询:我需要对 ADC 读数执行 RFFT。 ADC 分辨率为12位。 那么、是否有必要将 ADC 读数乘以2^19以转换为 Q31格式、然后复制到 ipcbsrc 数组中以进行后续 FFT 计算?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Asad、

    感谢您的理解。
    对于 ADC、 是的、您应该通过乘以  2^19将其转换为 Q31。  

    -Shantanu

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Asad、

    我能够再现比例问题。 我们正在研究这种情况的发生原因。 一旦我们确定它、我将会通知您。

    你还有其他问题吗?

    -Shantanu

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shanty:

      非常感谢您的更新。 我目前没有更多关于 RFFT 的问题。 我将等待您对比例问题的回复。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    根据 FPU_CFFT.h 中的文档、定点 FFT 会进行幅度缩放以避免溢出。 该系数为:

    1/[2^{FFT\_stages-1}]

    -Shantanu

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    请解释分母中的术语:"FFT\_STACENS-1"。  它是否为您上一帖子中提到的1/16?