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.
器件型号: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 的代码?