AnsweredAssumed Answered

FFT Problem on STM32F4

Question asked by gellekum.felix on Apr 15, 2013
Latest reply on Jul 22, 2013 by schneider.will
Hi there, 

I am writing my Bachelorthesis and have to calculate the FFT on the STM32F4. The Input Signal comes from a Radarsensor and is added with quite a lot of noise. My Radarsensor is powered with a triangular Voltage fom 0,5 to 5,0V. At the Output of the Radarsensor I get the difference of the input and output signal. Now I want to measure during the up chirp and during the down chirp.
After this is done I want to calculate the FFT of both signals, so I can compare them.

My ADC and my DAC are triggered with the same Timer:

void TIM2Init() //42 MHz
{
    TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure);
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;        
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;    
    TIM_TimeBaseInitStructure.TIM_Period = (20)-1;                     
    TIM_TimeBaseInitStructure.TIM_Prescaler = (1)-1;                 
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
 
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);            
 
    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
}

void ADCInit()
{
    ADC_CommonStructInit(&ADC_CommonInitStructure);
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler =ADC_Prescaler_Div4;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_15Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);
 
    ADC_StructInit(&ADC_InitStructure);                                            
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                            
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                         
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;  
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;         
    ADC_InitStructure.ADC_NbrOfConversion = 1;                                     
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;                                  
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;                         
 
    ADC_Init(ADC_I_SIGNAL, &ADC_InitStructure);                                    
 
}
void DACInit(uint32_t DAC_Channel)
{
    DAC_DeInit();
 
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;                           
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;                
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;                  
 
    DAC_Init(DAC_Channel, &DAC_InitStructure);                                     
}

ADC and DAC are connected with a DMA the config follows next:
void DMA1Init()
{
    DMA_StructInit(&DMA_InitStructure);                                                
    DMA_InitStructure.DMA_Channel = DMA_Channel_7;                                     
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) DAC_DHR12R1_Address;         
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &DAC_Signal;                    
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                            
    DMA_InitStructure.DMA_BufferSize = 1360;                                            
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                   
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                            
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;        
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;                
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                    
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 
    DMA_Init(DMA1_Stream5, &DMA_InitStructure);                                        
}
 
void DMA2Init() //for ADC
{
    DMA_StructInit(&DMA_InitStructure);                                                
    DMA_InitStructure.DMA_Channel = DMA_Channel_0;                                     
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address;              
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ConvertedValue;                 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;                            
    DMA_InitStructure.DMA_BufferSize = NR_OF_CONVERTED_VALUES;                  //2500, 2048 needed
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                   
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                            
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;    
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;            
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;                                    
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;                                
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 
    DMA_ITConfig(DMA2_Stream4, DMA_IT_TC | DMA_IT_HT, ENABLE);
 
    DMA_Init(DMA2_Stream4, &DMA_InitStructure);                                        
}

Now I want the DMA2 to tell me when it is finished with the first half, so I now know that the up chirp is sampled. Then he should tell me when it is finished with all the conversion so that I know I can now take the samples of the down chirp. All this takes place in the interrupt routine:
void DMA2_Stream4_IRQHandler()
{
    GPIO_ToggleBits(LED_PORT, LED_GREEN);
    uint16_t i = 0;
    float32_t *pData;
    uint16_t  *pConvertedValues;
 
    if(DMA_GetFlagStatus(DMA2_Stream4, DMA_FLAG_HTIF4) == SET)
    {
    //UP Chirp
        if(busyflag == 0)
        {
            busyflag = 1;
 
            pData=&(fdata_up[0]);
            pConvertedValues=&(ConvertedValue[CUT_OFF_VALUES-1]);
            for(i=0; i<LENGTH_SAMPLES; i++)
            {
                *pData=(float) *pConvertedValues;
                pData++;
                *pData=0;
                pData++;
                pConvertedValues++;
            }
        }
    }
 
    if(DMA_GetFlagStatus(DMA2_Stream4, DMA_FLAG_TCIF4) == SET)
    {
    //DOWN Chirp
        if(busyflag == 1)
        {
            pData = &(fdata_down[0]);
            pConvertedValues = &(ConvertedValue[(CUT_OFF_VALUES-1)+(NR_OF_CONVERTED_VALUES/2)]);
            for(i=0; i<LENGTH_SAMPLES; i++)
            {
                *pData=(float) *pConvertedValues;
                pData++;
                *pData=0;
                pData++;
                pConvertedValues++;
            }
            busyflag = 2;
        }
    }
 
    DMA_ClearFlag(DMA2_Stream4, DMA_IT_HT | DMA_IT_TC);
    DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_HTIF4 | DMA_IT_TCIF4);
}

This seems to work ok, at least I get two arrays (fdata_up and fdata_down) filled with data and 0's. Now in the main loop I check the busyflag and the I calculate the FFT of them. Right now I am just looking at standing objects, so that I should get two identical or almost identical FFT. But the reality looks different as you will see:
int main(void)
{
    INIT_ALL();
    Start();
    arm_cfft_radix4_instance_f32 S;
    arm_status status;
 
    while (1)
    {
        if(busyflag == 2)      
        {
            status = arm_cfft_radix4_init_f32(&S, FFTSIZE, ifftFlag, doBitReverse);
 
            arm_cfft_radix4_f32(&S, fdata_up);                                     
 
            arm_cmplx_mag_f32(fdata_up, fdataOutput_down, FFTSIZE);
 
            send_scope_f(4096, (uint8_t*)fdataOutput_down, 0x92, 2);               
 
 
 
            arm_cfft_radix4_f32(&S, fdata_up);                                     
 
            arm_cmplx_mag_f32(fdata_up, fdataOutput_up, FFTSIZE);
 
            fdataOutput_up[0] = 0;
 
            send_scope_f(4096, (uint8_t*)fdataOutput_up, 0x92, 3);                 
 
            busyflag = 0;
        }
    }
}

As you can see I am then sending my solution via UART to the PC. And here you can see the strange solution.
  http://img707.imageshack.us/img707/5247/fftf.png

Can you maybe tell me what went wrong here? I have seen some videos of the calculation of the FFT on a STM32f4 and they looked really good. I have no idea why it is doing this strange calculation here. Also if I use the 10kHz test array from the FFT example he is calculating it right first, but the second time it calculates strange stuff. The next time it is right again, after 4 or  times though it stops showing me anything. 

Thank you for your help. If you need further information pls let me know

Greets Felix

Outcomes