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/DK-TM4C129X:使用 CMSIS DSP 库的模拟信号 FFT

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/696830/ccs-dk-tm4c129x-fft-of-analog-signal-using-cmsis-dsp-library

器件型号:DK-TM4C129X

工具/软件:Code Composer Studio

您好、

我不熟悉此 CMSIS DSP 库函数。 我目前正在研究一个项目、该项目涉及通过函数发生器计算外部模拟信号的 FFT。 我已使用由计时器触发的 ADC 成功采样模拟信号、并使用 DMA 将值存储在1024长度的数组"g_ui8RxBufA"中。 现在、我想计算该信号的 FFT。 我成功构建了 CMSIS DSP 库并运行了此处给出的示例。 我运行了其中给出的 FFT 示例、该示例计算了测试数据信号的 FFT。 我只想这样做。 因此、输出"g_ui8RxBufA"数组、我在数组的每个奇数索引处添加了0值、方法是使用代码中所示的 for 循环(阵列索引从0开始)来形成数组" testInput_F32_10kHz"(长度为2048)、并遵循与示例相同的过程。 但是、当我运行代码时、"testInput_F32_10kHz" 数组的所有值都为0。 不知怎么说、这些值不是从"g_ui8RxBufA"数组传输的。 是否有人可以指出代码中的缺陷?

主函数:

uint32_t sysclock;

SysClock = SysCtlClockFreqSet ((SYSCTL_XTAL_25MHz |

SYSCTL_OSC_MAIN |

SYSCTL_USE_PLL |

SYSCTL_CFG_VCO_480)、120000000);


SysCtlPeripheralEnable (SYSCTL_Periph_UDMA);

while (!(SysCtlPeripheralReady (SYSCTL_Periph_UDMA)));

SysCtlPeripheralSlepEnable (SYSCTL_Periph_UDMA);

IntMasterEnable();

IntEnable (INT_UDMAERR);

uDMAEnable();

uDMAControlBaseSet (pui8ControlTable);

InitUART1传输(sysclock);

//FFT 开始
uint32_t i;

对于(I = 0;I < 1024;I++)
{
//if (I % 2 = 0)
testInput_F32_10kHz[2*i]= g_ui8RxBufA[i];
//else
testInput_F32_10kHz[2*I + 1]= 0;
}


/*----------------------------------------------
*最大幅度 FFT Bin 测试
************************************************************************************************** *

//int32_t main (空)
//{

ARM_STATUS 状态;
float32_t maxValue;

状态= ARM_MATH_SUCCESS;

/*通过 CFFT/CIFFT 模块处理数据*/
ARM_CFFT_F32 (&ARM_CFFT_SR_F32_len1024、testInput_F32_10kHz、ifftFlag、doBitReverse);

/*通过的复数幅度模块处理数据
计算每个区间的幅度*/
arm_cmplx_mag_F32 (testInput_F32_10kHz、TestOutput、fftSize);

/*计算 maxValue 并返回相应的 bin 值*/
arm_max_F32 (TestOutput、fftSize、&maxValue、&testIndex);

if (testIndex!= refIndex)
{
状态= ARM_MATH_TEST_FAILURE;
}

/*----------------------------------------------
**如果信号未通过通过通过检查,则在此环路。
**这表示测试失败
**-------------------------------------- *

if (status!= ARM_MATH_SUCCESS)
{
while (1);
}

//FFT 结束
// while (1); /*主函数不返回*/
while (1)
{

}

InitUART1 Transfer()函数:

uint32_t ui32Period;
//uint32_t div;

SysCtlPeripheralEnable (SYSCTL_Periph_ADC0);

while (!(SysCtlPeripheralReady (SYSCTL_Periph_ADC0)));

SysCtlPeripheralSlepEnable (SYSCTL_Periph_ADC0);

//ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL、1);
// ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL、 30);
ADCClockConfigSet (ADC0_BASE、ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL、24);

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE);

while (!(SysCtlPeripheralReady (SYSCTL_Periph_GPIOE)));

GPIOPinTypeADC (GPIO_Porte _BASE、GPIO_PIN_3);

//ADCSequenceConfigure (ADC0_BASE、0 /*SS0*/、ADC_TRIGGER_AYSHOW、3 /*Priority*/);// SS0-SS3优先级必须始终不同
ADCSequenceConfigure (ADC0_BASE、0、ADC_TRIGGER_TIMER、0);

ADCSequenceStepConfigure (ADC0_BASE、0、0、ADC_CTL_CH0 | ADC_CTL_IE |
ADC_CTL_END);

ADCSequenceEnable (ADC0_BASE、0);

ADCIntClear (ADC0_BASE、0);

//启用计时器外设
SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);

//计时器应定期运行
TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICASE);

//设置每次计时器完成时加载到计时器中的值
//这是计时器触发 ADC 之前所需的时钟周期数
//#define F_sample 1000
ui32Period = 1200000/1024000;
TimerLoadSet (TIMER0_BASE、TIMER_A、ui32Period-1);

//启用触发
TimerControlTrigger (TIMER0_BASE、TIMER_A、TRUE);

ADCIntEnable (ADC0_BASE、0);

//启用计时器
TimerEnable (TIMER0_BASE、TIMER_A);

ADCSequenceDMAEnable (ADC0_BASE、0);

uDMAChannelAttributeDisable (UDMA_CHANGE_ADC0、

UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |

UDMA_ATTR_HIGH_PRIOR|

UDMA_ATTR_REQMASK);

uDMAChannelControlSet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT、

UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEW_USEBURST |

UDMA_ARB_1024);

uDMAChannelControlSet (UDMA_CHANGE_ADC0 | UDMA_ALT_SELECT、

UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_NEW_USEBURST |

UDMA_ARB_1024);

uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_PRI_SELECT、

UDMA_MODE_PINGONG、

(void *)(ADC0_BASE + ADC_O_SSFIFO0)、

G_ui8RxBufA、MEM_buffer_size);


uDMAChannelTransferSet (UDMA_CHANGE_ADC0 | UDMA_ALT_SELECT、

UDMA_MODE_PINGONG、

(void *)(ADC0_BASE + ADC_O_SSFIFO0)、

G_ui8RxBufB、MEM_buffer_size);

uDMAChannelEnable (UDMA_CHANGE_ADC0);

ADCIntEnableEx (ADC0_BASE、ADC_INT_DMA_SS0);

IntEnable (INT_ADC0SS0);

 

 

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

    是"float"类型的数组"testInput_F32_10kHz"、并且正在执行从 unsigned char 到 float 分配的隐式转换:

    testInput_F32_10kHz[2*i]= g_ui8RxBufA[i]; 

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

    嗨、Bob、

    是的、你是对的。 这两个数组定义为:

    静态 uint32_t g_ui8RxBufA[MEM_buffer_size];
    静态 float32_t testInput_F32_10kHz[test_length_samples]; 

    我来自数组"g_ui8RxBufA"中 UDMA 的值位于 unsigned int 中。 我在 CMSIS DSP 库的 FFT 函数文档中看到、这些函数将 float32作为输入数据。 现在、为了将 uint32_t 转换为 float32_t 数组、我首先尝试使用类型转换:



    testInput_F32_10kHz[2*i]=(float32_t) g_ui8RxBufA[i];

    但这不起作用。 因此、我在 CMSIS 库中进行了搜索。 并使用 ARM_Q31_TO_FLOC()函数将32位整数转换为 float32。 这也不起作用。 我在下面附上了我的整个代码。 您能否建议如何将 UINT32转换为 float32、或者通过其他方式计算 FFT?

    此致、

    Harshul

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

    嘿、我尝试了互联网上关于这个转换的其他东西。 我首先将 uint32_t 更改为 Q31_t、然后通过将 Q31_t 转换为 float32_t 的 ARM 函数生成用于 FFT 计算的数组。 但是、当我运行代码时、缓冲区中的所有值仍然为0。这些值为0、当我在几秒钟后暂停时、代码会转到编码中定义的 ADCseq0handler、然后从那里进入 Udma.c 文件、然后来回移动。 切勿到达 main 中的 for 循环。 但我在这之后尝试了一种不同的方法。 我手动单步进入每个函数中的主文件、当进入 for loop 时、我单步进入该文件并保持1024次步进(耗时)、并对所有循环执行此操作、此后至少缓冲区具有一些值(我认为 testInput_F32_10kHz 具有正确的值)。 为什么在我运行代码时、代码会进入 ADC 中断处理程序而不是进入循环? 您能否指出代码中的任何错误并提出解决方案?

    下面是我的整条代码:

    e2e.ti.com/.../2021.single_5F00_ended.c

    此致、

    Harshul

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

    我已使用下面附加的代码正确地对外部信号进行采样。 我想通过 CMSIS DSP 库函数计算该缓冲区的 FFT、我尝试将采样数据导出到 dat 文件、然后将 dat 文件导入另一个计算该数据 FFT 的项目。 效果非常好。 但我想在 ADC 项目中整合 FFT 算法、该怎么做? 我的意思是缓冲区正在以快速的速率(1024khz 的采样率和1024个采样、因此填充缓冲区的时间为1ms)进行填充和清空、因此 、我必须在缓冲区完全填满时计算缓冲区的 FFT (2个缓冲区中的任何一个)。 有人可以帮助解决这些问题、并建议我必须在哪里更改 FFT 的代码?

    e2e.ti.com/.../8306.single_5F00_ended.c