8.傅立叶运算(终结篇)
本次申请STM32F746 DISCOVERY的最终目的是运行STM32-DSP库的傅立叶浮点运算,以评估STM32F746的性能。
经过一段时间的摸索试用,终于能够在STM32F746 DISCOVERY开发板上顺利运行1024点基4 FFT的浮点运算,并将运算结果以图形方式实时在LTDC屏幕上显示。运行结果令人满意,STM32F476用来执行DSP浮点运算确实是一款性能极佳的处理器。
首先在项目工程中要添加ST的DSP库文件和FFT-C文件arm_cfft_radix4_f32.c:
图1 添加DSP库
接着要在Options->C/C++选项中添加STM32F746xx,__FPU_PRESENT=1,ARM_MATH_CM7,启用FPU.
在main.c中添加头文件#include "arm_math.h"
ADC的配置:启用ADC3的通道0(GPIOA.0)
void MX_ADC3_Init(void)
{
ADC_ChannelConfTypeDef sConfig;
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;
hadc3.Init.Resolution = ADC_RESOLUTION12b;
hadc3.Init.ScanConvMode = DISABLE;
hadc3.Init.ContinuousConvMode = ENABLE;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.NbrOfConversion = 1;
hadc3.Init.DMAContinuousRequests = ENABLE;
hadc3.Init.EOCSelection = EOC_SINGLE_CONV;
HAL_ADC_Init(&hadc3);
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
HAL_ADC_ConfigChannel(&hadc3, &sConfig);
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hadc->Instance==ADC3)
{
__ADC3_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
hdma_adc3.Instance = DMA2_Stream0;
hdma_adc3.Init.Channel = DMA_CHANNEL_2;
hdma_adc3.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc3.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc3.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc3.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc3.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc3.Init.Mode = DMA_CIRCULAR;
hdma_adc3.Init.Priority = DMA_PRIORITY_LOW;
hdma_adc3.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_adc3.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_adc3.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_adc3.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&hdma_adc3);
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance==ADC3)
{
__ADC3_CLK_DISABLE();
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
HAL_DMA_DeInit(hadc->DMA_Handle);
HAL_NVIC_DisableIRQ(ADC_IRQn);
}
}
ADC-DMA传输
void MX_DMA_Init(void)
{
__HAL_RCC_DMA2_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
设定ADC采样1024个数据后停止ADC,进行FFT运算后重新启动ADC。
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
dmaflage=1;
HAL_ADC_Stop_DMA(&hadc3);
}
基4浮点FFT
static void FFT_read(void)
{ uint16_t i;
arm_cfft_radix4_instance_f32 scfft;
arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);
for(i=0;i {
inputbuf[2*i]=(float)Samples_In[i]; //导入ADC数据
inputbuf[2*i+1]=0;
}
arm_cfft_radix4_f32(&scfft,inputbuf);
arm_cmplx_mag_f32(inputbuf,outputbuf,FFT_LENGTH);
}
在屏幕上显示
if(dmaflage==1) //1024个ADC采样结束
{
dmaflage=0;
FFT_read();
for(i=0;i<479;i++) //屏幕水平最大宽度坐标
{
BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
BSP_LCD_DrawVLine(i,0,269);
BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
BSP_LCD_DrawLine(i,269,i,269-(outputbuf[i]/80));
}
HAL_ADC_Start_DMA(&hadc3,(uint32_t*)&Samples_In[0],FFT_LENGTH );
}
视频地址:http://player.youku.com/player.php/sid/XMTM1NzUwNDc1Ng==/v.swf
实测STM32F746进行1次基4的1024点FFT浮点运算耗时仅500uS,确实是一款性能极佳的处理器。