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.

[参考译文] CCS/TMS320F28377S:使用 TMS320f28377S LaunchPad 的256点 FFT

Guru**** 2200880 points
Other Parts Discussed in Thread: TMS320F28377S, C2000WARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/737864/ccs-tms320f28377s-256-point-fft-using-tms320f28377s-launchpad

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

工具/软件:Code Composer Studio

我正在尝试在 TMS320f28377S 上获取50Hz 的实时256点 FFT 信号。 采样频率为1.6KHz。 频率分辨率为6.25Hz。 因此、在 FFT 输出(RFFToutBuff)中、8号样本应提供50Hz 信号的脉冲性质、但我获得的 FFT 输出的所有256个样本值都在[2、-2]范围内。
我也不能检查天气,我的 epwm1给了我频率为1.6KHz 的时钟。

请指导我检查 epwm1以及更好的 FFT 输出所需的更改。

谢谢你
Bhavesh

FFT 代码:-

//文件:adc_soc_ePWM_cpu01.c
//文件:Voltmeto_FFT.c
//标题:针对 F2837xS 通过 ePWM 触发 ADC。
//
//! addtogroup cpu01_example_list
//!

ADC ePWM 触发(ADC_SoC_ePWM)


//!
//! 此示例设置 EPWM 以定期触发 ADC。
//!
//! 程序运行后,内存将包含:\n
//! -\b 结果:一系列的模数转换样本
//! 引脚 A0。 采样之间的时间根据周期确定
//! PWM 计时器的功能。

#include "F28x_Project.h"//器件头文件和示例 include 文件
#include
#include
#include
#include
#include
#include
#include
#include
#include "fpu_rfft.h"
#include "FPU_FFT_Hann.h"
#include "FPU_FFT_hamming.h"
#include "FPU_FFT_flattop.h"
#include "FPU_FFT_Blackman.h"
#include "FPU_FFT_blackmanharris.h"
#include "FPU_FFT_rect.h"


#define RFFT_STACages 8.
#define RFFT_SIZE (1 << RFFT_STOPENAINSages)
#define NPP 16.
#define UART0_BASE 0x7200

//RFFT_ADC_F32_struct rfft_ADC;
//RFFT_ADC_F32_struct_handle HND_rfft_ADC =&rfft_ADC;

RFFT_F32_struct rfft;
RFFT_F32_struct_Handle HND_rfft =&rfft;

#pragma DATA_SECTION (RFFTin1Buff、"RFFTdata1");
float32 RFFTin1Buff[RFFT_SIZE];

#pragma DATA_SECTION (RFFToutBuff、"RFFTdata2");
float32 RFFToutBuff[RFFT_SIZE];

#pragma DATA_SECTION (RFFTmagBuff、"RFFTdata3");
float32 RFFTmagBuff[RFFT_SIZE/2];

#pragma DATA_SECTION (RFFTF32Coef、"RFFTdata4");
float32 RFFTF32Coef[RFFT_SIZE];

#pragma DATA_SECTION (Power、"RFFTdata5");
float32 Power[RFFT_SIZE/2];

//#pragma DATA_SECTION (PeakValueFFT、"RFFTdata6");
//float32 PeakValueFFT[RFFT_SIZE/2];

//#pragma DATA_SECTION (ADCin1Buff、"RFFTdata7");
//float32 Buffer_Signal_Scaled[RFFT_SIZE];

#pragma DATA_SECTION (ADCin1Buff、"RFFTdata7");
uint16_t ADCin1Buff[RFFT_SIZE];

#pragma DATA_SECTION (Buffer_Signal_Scaled、"RFFTdata8");
float32 Buffer_Signal_Scaled[RFFT_SIZE];

//const float RFFTWindow[RFFT_SIZE/2]= RECT2048;

void ConfigureADC (void);//ADC、PWM
void ConfigureEPWM (void);
void SetupADCepwm (uint16通道);
//void RFFT_F32_win (float * pbuffer、float * pWindow、uint16_t size);//fdt
//void RFFT_F32_MAG (RFFT_F32_struct*);
//void PowerSpectrumCompute (void);
void FFT (void);

//void useuart (void);//uart
中断 void adca1_ISR (void);//ADC ISR

void Set_Sample_Frequency (float FS);//获取并详细说明
//静态浮点真有效值(浮点信号[]、常量 int dim、浮点频率、浮点 FS);
void PeakValueCompute (void);
//静态浮点 Frequency_Compute (const float Power_Spectrum[]、const float fs、const int FFT_size、const unsigned int Max_Index);
void AcquireSignal (void);
void scale_input_buffer (void);

uint16结果索引;
易失性 uint16 bufferFull;

float RMS_value = 0;
浮点频率;
浮点 FSample、FSample_default;
unsigned int Max_Index = 0;
volatile char state = 0;

//unsigned int msg1len;//= strlen (msg1);
//初始化 UART。 设置波特率、数据位数、关闭奇偶校验、停止位数和记忆棒模式。
//uint32_t param1 =(uint32_t)&SciaRegs;// 0x00007210;
//uint32_t 参数2 =(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_LEON);
//uint32_t PARAM3 = 50000000;
//UARTConfigSetExpClk (param1、paramM3、10000、param2);
//启用 UART。

void main (void)

//步骤1. 初始化系统控制:
// PLL、安全装置、启用外设时钟
//此示例函数位于 F2837xS_SYSCTRL.c 文件中。
InitSysCtrl();
//步骤2. 初始化 GPIO:
//此示例函数位于 F2837xS_GPIO.c 文件和中
//说明了如何将 GPIO 设置为其默认状态。
InitGpio();//针对此示例跳过
//步骤3. 清除所有中断并初始化 PIE 矢量表:
//禁用 CPU 中断
Dint;

//将 PIE 控制寄存器初始化为默认状态。
//默认状态为禁用所有 PIE 中断和标志
//被清除。
//此函数位于 F2837xS_PIECTRL.c 文件中。
InitPieCtrl();

//禁用 CPU 中断并清除所有 CPU 中断标志:
IER = 0x0000;
IFR = 0x0000;

//使用指向 shell 中断的指针初始化 PIE 矢量表
//服务例程(ISR)。
//这将填充整个表,即使是中断也是如此
//在本例中未使用。 这对于调试很有用。
//可以在 F2837xS_DefaultIsr.c 中找到 shell ISR 例程
//此函数可在 F2837xS_PieVect.c 中找到
InitPieVectTable();

//映射 ISR 函数
EALLOW;
PieVectTable.ADCA1_INT =&adca1_ISR;//针对 ADCA 中断1的函数
//PieVectTable.XINT3_INT =&xint3_ISR;
EDIS;

//配置 ADC 并为其加电
ConfigureADC();

//配置 ePWM
ConfigureEPWM();

//Setup the ADC for ePWM triggered Conversions on channel 0
SetupADCepwm (4);

//启用全局中断和更高优先级的实时调试事件:
IER |= M_INT1;//启用组1中断
EINT;//启用全局中断 INTM
ERTM;//启用全局实时中断 DBGM

resultsIndex = 0;
bufferFull = 0;

//hnd_rfft_adc->尾线=&(hnd_rfft->OutBuf);
hnd_rfft->FFTize = RFFT_SIZE;//FFT 大小
hnd_rfft->FFTStage = RFFT_STA期;//FFT 级

hnd_rfft->InBuf =&RFFTin1Buff[0];//输入缓冲器(12位 ADC)输入
hnd_rfft->OutBuf =&RFFToutBuff[0];//输出缓冲区
hnd_rfft->CosSinBuf =&RFFTF32Coef[0];//Twiddle 因子
hnd_rfft->MagBuf =&RFFTmagBuff[0];//幅度输出缓冲区


//在 PIE 中启用 Xint3:组12中断1
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;//启用 PIE 块
PieCtrlRegs.PIEIER12.bit.INTx1= 1;//启用 PIE 组12 INTx1
IER |= M_INT12;//启用 CPU INT12
EINT;//启用全局中断
XintRegs.XINT3CR.bit.polarity = 2;//下降边沿
XintRegs.XINT3CR.bit.enable = 1;//XINT3交叉点使能
PieCtrlRegs.PIEIER1.bit.INTx1 = 1;//启用 PIE 中断

//SYNC ePWM
EALLOW;
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=1;
//循环无限地进行转换
操作

DELAY_US (10000);//原始延迟10000
AcquireSignal();//获取信号
scale_input_buffer();
memcpy_fast (Buffer_Signal_Scaled、RFFTin1Buff、RFFT_SIZE* sizeof (float));
FFT();//FFT 计算
//PowerSpectrumCompute ();//Power spectrum
//Freq =频率计算(功率、FSample、RFFT_SIZE、Max_Index);
//RMS_value =真有效值(Buffer_Signal_Scaled、RFFT_Size、Freq、FSample);
//中断;
//asm (" ESTOP0");
} while (1);

//写入 ADC 配置并为 ADC A 和 ADC B 加电
空配置 ADC (空)

EALLOW;
//写入配置
AdcaRegs.ADCCTL2.bit.prescale = 6;//将 ADCCLK 分频器设置为/4
//AdcSetMode (ADC_ADCA、ADC_Resolution 12位、ADC_SIGNALMODE_SINGLE);
AdcaRegs.ADCCTL2.bit.resolution = 0;// 12位分辨率
AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0;//单端通道转换(仅12位模式)
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1;//将脉冲位置设置为晚期
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;//为 ADC 加电
DELAY_US (1000);//延迟1ms 以允许 ADC 加电时间
EDIS;

空配置 EPWM (空)

EALLOW;
//假设 ePWM 时钟已启用
EPwm1Regs.ETSEL.bit.SOCAEN = 0;//禁用组上的 SOC
EPwm1Regs.ETSEL.bit.SOCASEL = 4;//在递增计数时选择 SOC
EPwm1Regs.ETPS.bit.SOCAPRD = 1;//在发生第一个事件时生成脉冲
EPwm1Regs.CMPA.bit.CMPA = 781;
EPwm1Regs.TBPRD = 1562;
EPwm1Regs.TBCTL.bit.CTRMODE = 2;//加减计数器
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;
EPwm1Regs.TBCTL.bit.CLKDIV = 2;
EDIS;

void SetupADCepwm (uint16通道)

//选择要转换的通道和转换结束标志
EALLOW;
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 1;//SOC0将转换引脚 A0 //引脚29 adcA1
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14;//采样窗口为100个 SYSCLK 周期
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5;// ePWM1 SOCA/C 上的触发
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0;// SOC0结束将设置 INT1标志
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;//启用 INT1标志
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//确保 INT1标志被清除


中断 void adca1_ISR (void)

ADCin1Buff[resultsIndex++]=(AdcResultRegs.ADCRESULT0);
if (RFFT_SIZE<=结果索引)

resultsIndex = 0;
bufferFull = 1;

AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;//清除 INT1标志
PieCtrlRegs.PIEACX.ALL = PIEACK_Group1;

无效电爆信号(空)

//启动 ePWM
EPwm1Regs.ETSEL.bit.SOCAEN = 1;//启用 SOCA
EPwm1Regs.TBCTL.bit.CTRMODE = 2;//取消冻结,并进入向上计数模式//原始=0

//等待、而 ePWM 导致 ADC 转换、然后导致中断、
//填充结果缓冲区,最终设置 bufferFull
//flag
while (!bufferFull);
bufferFull = 0;//清除缓冲区已满标志

//停止 ePWM
EPwm1Regs.ETSEL.bit.SOCAEN = 0;//禁用 SOCA
EPwm1Regs.TBCTL.bit.CTRMODE = 2;//冻结计数器(3)//递增/递减计数器(2)

void FFT (void)

RFFT_f32u (HND_rfft);
RFFT_F32_MAG_TMU0 (HND_RFFT);

void Set_Sample_Frequency (float FS)

unsigned int TBPRD = 0;
unsigned int CMPA = 0;
//TBPRD =(unsigned int)((rnd_sp_RS (200000000.0/(4*FS)-1)));
// CMPA =(unsigned int)((rnd_sp_RS (((TBPRD/2.0)-1)));
EPwm1Regs.CMPA.bit.CMPA = 781;
EPwm1Regs.TBPRD = 1562;

EPwm1Regs.TBCTL.bit.CTRMODE = 2;//加减计数器
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;
EPwm1Regs.TBCTL.bit.CLKDIV = 2;

void scale_input_buffer (void)

size_t k;
对于(k = 0;k <(RFFT_SIZE);k = k+2)

RFFTin1Buff[k]= 0.000732421875*ADCin1Buff[k]-1.5;
RFFTin1Buff[k+1]= 0.000732421875*ADCin1Buff[k+1]-1.5;
}// 0.000732421875 = 3/4096 (3V ADC 基准)

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

    对延迟答复表示歉意。 我将查看您的问题、下周再见。

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

    1.您是否阅读了 C2000Ware 中 FPU_SW_LIB_UG.pdf 的第5.12和5.13节? 这些示例正是您尝试执行的操作(具有 ADC 输入的 RFFT (对齐或不对齐)。 如果您没有、请执行、然后构建并运行相应的 CCS 工程、这些工程位于:
    C:\ti\c2000Ware_1_00_05_00\libraries\dsp\FPU\c28\examples\FFT

    由于您使用的是28377S Launchpad、因此值得指出的是、C2000ware 示例是为 controlCARD 编写的、该 controlCARD 使用器件的20MHz 时钟输入。 对于200MHz SYSCLKOUT、它使用一个10倍乘因子(20/2)。 LaunchPad 使用10MHz 时钟输入。 因此、它需要使用20 (40/2)的乘法因子来实现相同的 SYSCLKOUT。 这一点很重要、因为这会影响外设时钟频率、因此它将确定您是获得所需的1.6kHz 采样时钟还是其他时钟。

    F2837xS_SYSCTRL.c 中的变量_LAUNCHXL_F28377S 控制调用哪个 PLL 函数。 必须在项目设置窗口(Build-C2000 Compiler - Advanced Options - Predefined Symbols)中手动添加此变量,此方案才能生效。
    如需参考、请参阅 F2837xS_SYSCTRL.c 中的第171行及其后的内容:

    #ifdef _LAUNCHXL_F28377S
    InitSysPll (XTAL_OSC、IMULT_40、FULT_0、PLLCLK_By_2);
    其他
    InitSysPll (XTAL_OSC、IMULT_20、FULT_0、PLLCLK_By_2);
    #endif

    此外、粘贴一段长代码的一个很好的替代方法是创建软件流的方框图说明。 如果代码是从其他位置获取的参考代码、请准确指出文件/示例的位置和位置。

    4.你的分析是对的。 纸槽8应包含一个峰值、所有其他值应为0。 如何生成50Hz 信号并将其馈送至28377的 ADC? 您应缓冲 ADC 样本并绘制其图形、并确保它们对应于50Hz 正弦波。

    请尝试这些并告诉我。
    谢谢、
    Sira