基于LPC55S69双核ARM-M33FFT傅利叶频谱仪

 

一、项目名称

    基于LPC55S69双核ARM-M33的FFT傅利叶频谱仪

 

二、项目概述

    傅利叶运算FFT很适用于频谱的分析。基于LPC55S69双核ARM-M33的FFT傅利叶频谱仪,利用M33双核ARM主核浮点运算的特点,Core0进行ADC采样和FFT运算。Core1驱动OLED将运算结果以图形方式显示频谱。

三、项目的实施

双核任务的规划:

    项目主要功能为每秒512点的FFT运算,其中主要分为0#模块(ADC采样、FFT浮点小数运算)和1#模块(OLED图形显示)。0#模块分配给Core0,1#模块分配给Core1。申请了一个内存共享区,Core0将512个点FFT运算结果存放在该区,Core1读取该共享数据在OLED上显示。

    本项目使用了IAR自带的DSP库和LPC的PowerQuad两种DSP进行测试。

硬件资源:

    实现项目的功能利用《基于LPC55S69双核三相真有效值交流电压表》的硬件资源。Core0的资源需要ADC0通道的采样转换。Core1驱动OLED的5条GPIO口线硬件资源不变直接利用。这些都从板子上的ARDUINO插座上引出。

外扩资源:

 

    需要外扩ADC外部输入电路ADC0输入利用原《真有效值交流电压表》的硬件ADC0,见图1。

 

                               图1

DEMO板的三相交流电模拟信号发生器,输出的正弦波信号,连接到LPC55S69的ADC0输入端,在P3端接上9V层叠电池就能进行50HZ正弦波频谱的显示。由于这片OLED水平方向只有128DPI,扣除512点FFT的镜像部分256点,将前256点压缩每2点抽取1点共128点供水平显示。如果断开用50HZ发生器的9V供电,用户也可以将MP3信号从S1(GND)和S2(信号)接入来测试(见图2)。注意信号电平勿超过3.3V供电电压。

开发环境:

IAR8.32.1。工程模块使用双核Hello_world修改而成。

    为了对比使用IAR自带DSP函数库与LPC5500独特的PowerQuad处理浮点运算的能力,代码使用了方案A(IAR DSP)和方案B(LPC PowerQuad):

方案A;使用IAR自带DSP库,需要调用IAR的DSP库,见图2.

                       图2

FPU要使能(图3)

                                            图3

     FFT 运算直接调用IAR的DSP库,代码不复杂:

Void LPC_FFT(void)

{

arm_cfft_radix2_instance_f32 scfft;

  uint16_t i;

      arm_cfft_radix2_init_f32(&scfft,FFT_LENGTH,0,1);

       for(i=0;i<FFT_LENGTH;i++)                                                                                  

        { fft_inputbuf[2*i]=(uint16_t)Adc_Value[i];

        fft_inputbuf[2*i+1]=0;

       }

arm_cfft_radix2_f32(&scfft,fft_inputbuf);   

 arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);

}

双核调试:

调试过程与真有效交流电压表基本相同,不再重复。

演示代码测试了LPC55s69主核处理浮点运算处理512个点FFT的浮点运算速度,,测试结果大约耗时1156uS(图4)。

 

                       图4

方案B:使用LPC的POWERQUAD

   该测试使用Core0单核工程添加fsl_powerquad.c、fsl_widdlefactor.c和DSP原代码(图5)。

 

                            图5

 

使能FPU(图6)。

                               图6

 

void task_pq_fft_512(void)

{

    arm_cfft_instance_q31 instance;

    uint32_t i;

      for (i = 0; i < APP_PQ_FFT_SAMPLE_COUNT_512; i++)

    { gPQFftF32In[i*2] = (float32_t)(Adc_Value[i]-2047.99);

       gPQFftF32In[i*2] /= 3.0f;

        gPQFftF32In[i*2+1] = 0.0f;

    }//导入ADC数据

  arm_float_to_q31(gPQFftF32In,gPQFftQ31In, APP_PQ_FFT_SAMPLE_COUNT_512*2u);

    for (i = 0u; i < APP_PQ_FFT_SAMPLE_COUNT_512 * 2u; i++)

    { gPQFftQ31InOut[i] = gPQFftQ31In[i] >> 5u; }

 TimerCount_Start();

   instance.fftLen = APP_PQ_FFT_SAMPLE_COUNT_512;  

   arm_cfft_q31(&instance, gPQFftQ31InOut, 0, 1);

  TimerCount_Stop(calcTime);

    for (i = 0u; i < APP_PQ_FFT_SAMPLE_COUNT_512 * 2u; i++)

    { gPQFftQ31Out[i] = gPQFftQ31InOut[i] << 5u;

    }

    arm_q31_to_float(gPQFftQ31Out,gPQFftF32Out, APP_PQ_FFT_SAMPLE_COUNT_512*2u);

   arm_cmplx_mag_f32( gPQFftF32Out, gPQFftF32In, APP_PQ_FFT_SAMPLE_COUNT_512);  

     memset(gLcdFreqSpecDispBuf,0u, sizeof(gLcdFreqSpecDispBuf));

    for (i = 0u; i < APP_PQ_FFT_SAMPLE_COUNT_512; i++)

    { gLcdFreqSpecDispBuf[i] = (int)(gPQFftF32In[i] * 128.0);     }  

    gPQProcCycles[APP_USER_TASK_FFT_512_IDX] = calcTime;

}

使用POWERQUAD使得FFT浮点运算速度大大提高,处理512点FFT浮点运算耗时36uS(图7)。

                                     图7

    通过方案A(图4)与方案B(图7)运行结果对比可知,LPC5500特有的PowerQuad处理浮点运算的速度比IAR自带的DSP处理速度大大提高。