AnsweredAssumed Answered

FFT problem on stm32f4 discovery.

Question asked by hamza.ameer.001 on Aug 29, 2015
Latest reply on Feb 9, 2016 by pochamreddy
Hi. I am facing strange problem implementing FFT on stm32f4 kit. i am using Virtual Com Port to transmit serial data which is plotted on QT (C++) platform.
The problem i am facing is that some time output is correct but most of the times wrong data is being plotted. Even when correct data is plotted still some wrong samples are
there to ruin theplot. Here is my code. Any help would be appreciated. Thanks in advance.


===== CODE =====
#define FFT_SAMPLES 2048
#define FFT_SIZE FFT_SAMPLES/2
#define FFT_TIM_PRESCALE 420-1// 100 KH-z Clock
#define FFT_TIM_PERIOD 10-1//100 KHz down to 10 Khz
#define FFT_SAMPLE_FRQ ADC_SampleTime_15Cycles               
#define FFT_SAMPLE_DELAY ADC_TwoSamplingDelay_5Cycles

uint16_t fftAdc[FFT_SAMPLES/2];
float32_t fftInput[FFT_SAMPLES];
float32_t fftOutput[FFT_SIZE];
uint16_t fftInc=0;
uint16_t fftI=0;
double fftAdcValue;//after conversion -1 to +1
uint32_t fftMaxIndex;
float32_t fftMaxValue;
uint8_t fftFlag=0;

int main(void){     
     arm_cfft_radix4_instance_f32     FFT_InitStruc;
     FFT_NVIC_ADC();
     FFT_GPIO();
     FFT_TIM2();
     FFT_ADC();
     status = arm_cfft_radix4_init_f32(&FFT_InitStruc,FFT_SIZE,0,1);
     while(1){               
          if(fftFlag == 1){
               fftFlag = 0;               
               arm_cfft_radix4_f32(&FFT_InitStruc,fftInput);
               arm_cmplx_mag_f32(fftInput,fftOutput,FFT_SIZE);
               arm_max_f32(fftOutput,FFT_SIZE,&fftMaxValue,&fftMaxIndex);          
               if(fftMaxIndex >= FFT_SIZE/2){
                    fftMaxIndex = FFT_SIZE - fftMaxIndex;
               }
                    for(frInc=0;frInc<FFT_SIZE/2;frInc+=16){
                    sprintf(strPut,"#%d+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%.0f+%d+%.0f+~",frInc,fftOutput[frInc],fftOutput[frInc+1],
                    fftOutput[frInc+2],fftOutput[frInc+3],fftOutput[frInc+4],fftOutput[frInc+5],fftOutput[frInc+6],fftOutput[frInc+7],fftOutput[frInc+8],fftOutput[frInc+9],fftOutput[frInc+10],fftOutput[frInc+11],
                    fftOutput[frInc+12],fftOutput[frInc+13],fftOutput[frInc+14],fftOutput[frInc+15],fftMaxIndex,fftMaxValue);
                    TM_USB_VCP_Puts(strPut);
                    Delay(7000);
               }          
          }
     }               
}
void FFT_GPIO(void){
     GPIO_InitStruc.GPIO_Pin = GPIO_Pin_0;
     GPIO_InitStruc.GPIO_Mode = GPIO_Mode_AN;
     GPIO_InitStruc.GPIO_Speed = GPIO_Speed_100MHz;
     GPIO_InitStruc.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_Init(GPIOA,&GPIO_InitStruc);     
}
void FFT_NVIC_ADC(void){
     NVIC_InitStruc.NVIC_IRQChannel = ADC_IRQn;
     NVIC_InitStruc.NVIC_IRQChannelCmd = ENABLE;
     NVIC_InitStruc.NVIC_IRQChannelPreemptionPriority = 0;
     NVIC_InitStruc.NVIC_IRQChannelSubPriority = 0;
     NVIC_Init(&NVIC_InitStruc);     
}


void FFT_TIM2(void){
     TIM_DeInit(TIM2);     
     TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruc);     
     TIM_TimeBaseInitStruc.TIM_Period = FFT_TIM_PERIOD;
     TIM_TimeBaseInitStruc.TIM_Prescaler = FFT_TIM_PRESCALE;
     TIM_TimeBaseInitStruc.TIM_ClockDivision = 0;
     TIM_TimeBaseInitStruc.TIM_CounterMode = TIM_CounterMode_Up;
     TIM_TimeBaseInitStruc.TIM_RepetitionCounter = 0;     
     TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruc);     
     TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update);
     TIM_Cmd(TIM2,ENABLE);     
}

void FFT_ADC(void){
     DMA_DeInit(DMA2_Stream0);     
     DMA_InitStruc.DMA_Channel = DMA_Channel_0;
     DMA_InitStruc.DMA_PeripheralBaseAddr = (uint32_t) &ADC1->DR;
     DMA_InitStruc.DMA_Memory0BaseAddr = (uint32_t) &fftAdc[0];
     DMA_InitStruc.DMA_DIR = DMA_DIR_PeripheralToMemory;
     DMA_InitStruc.DMA_BufferSize = FFT_SIZE;
     DMA_InitStruc.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
     DMA_InitStruc.DMA_MemoryInc = DMA_MemoryInc_Enable;
     DMA_InitStruc.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
     DMA_InitStruc.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
     DMA_InitStruc.DMA_Mode = DMA_Mode_Circular;
     DMA_InitStruc.DMA_Priority = DMA_Priority_High;
     DMA_InitStruc.DMA_FIFOMode = DMA_FIFOMode_Disable;
     DMA_InitStruc.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;     
     DMA_InitStruc.DMA_MemoryBurst = DMA_MemoryBurst_Single;
     DMA_InitStruc.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     
     DMA_Init(DMA2_Stream0,&DMA_InitStruc);     
     DMA_Cmd(DMA2_Stream0,ENABLE);     
     ADC_DeInit();
     ADC_CommonInitStruc.ADC_Mode = ADC_Mode_Independent;
     ADC_CommonInitStruc.ADC_Prescaler = ADC_Prescaler_Div2;
     ADC_CommonInitStruc.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
     ADC_CommonInitStruc.ADC_TwoSamplingDelay = FFT_SAMPLE_DELAY;
     ADC_CommonInit(&ADC_CommonInitStruc);          
     ADC_InitStruc.ADC_Resolution = ADC_Resolution_12b;
     ADC_InitStruc.ADC_ScanConvMode = DISABLE;
     ADC_InitStruc.ADC_ContinuousConvMode = DISABLE;
     ADC_InitStruc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
     ADC_InitStruc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
     ADC_InitStruc.ADC_DataAlign = ADC_DataAlign_Right;
     ADC_InitStruc.ADC_NbrOfConversion = 1;
     ADC_Init(ADC1,&ADC_InitStruc);
     ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,FFT_SAMPLE_FRQ);
     ADC_DMARequestAfterLastTransferCmd(ADC1,ENABLE);          
     ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);     
     ADC_DMACmd(ADC1,ENABLE);
     ADC_Cmd(ADC1,ENABLE);
     ADC_SoftwareStartConv(ADC1);               
}


void ADC_IRQHandler(void){
     float32_t *pData;
     uint16_t *pConvertedValues;
          ADC_ClearITPendingBit(ADC1,ADC_IT_EOC);{
          if(fftFlag ==0){
               fftFlag = 1;
               pData = &(fftInput[0]);
               pConvertedValues = & (fftAdc[0]);
               for(fftI =0;fftI<FFT_SIZE;fftI++){
                    *pData = (float32_t) ((float32_t)*pConvertedValues -     (float32_t) 2048) / (float32_t) 2048;
                    pData ++;
                    *pData = 0;
                    pData ++;
                    pConvertedValues ++;
               }
          }
     }
}


Outcomes