F4硬件FFT频谱显示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27508477/article/details/83241683
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "timer.h"
#include "math.h"
#include "arm_math.h"
#include "adc.h"

#define FFT_LENGTH		1024 		//FFT长度,默认是1024点FFT

float fft_inputbuf[FFT_LENGTH*2];	//FFT输入数组
float fft_outputbuf[FFT_LENGTH];	//FFT输出数组
float outmax;
float frq;
u8 timeout;//定时器溢出次数
u16 height;

int main(void)
{
    arm_cfft_radix4_instance_f32 scfft;
    float time;
    u16 i;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    delay_init(168);  //初始化延时函数
    uart_init(115200);		//初始化串口波特率为115200
    Adc_Init();         //初始化ADC
    LCD_Init();					//初始化LCD
    TIM3_Int_Init(65535,84-1);	//1Mhz计数频率,最大计时65ms左右超出
    arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);//初始化scfft结构体,设定FFT相关参数
    while(1)
    {
				//生成信号序列
        for(i=0; i<FFT_LENGTH; i++) 
        {
            TIM_SetCounter(TIM3,0);//重设TIM3定时器的计数器值
            fft_inputbuf[2*i]=Get_Adc(ADC_Channel_10)-1930;
            fft_inputbuf[2*i+1]=0;//虚部全部为0
						//以下4句和 delay_us(50); 等效
            time=0;
            timeout=0;
            while(time<50)	//50us 20kHz
                time=TIM_GetCounter(TIM3)+(u32)timeout*65536; 			//计算所用时间
        }
        arm_cfft_radix4_f32(&scfft,fft_inputbuf);	//FFT计算(基4)
        arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH);	//把运算结果复数求模得幅值
				//输出最大分量
        outmax=0;
        frq=0;
        for(i=1; i<FFT_LENGTH/2; i++)
        {

            if(outmax<fft_outputbuf[i])
            {
                outmax=fft_outputbuf[i];
                frq=i;
            }
        }
		//20k/1024=19.5	每两个点的间隔是19.5Hz
		printf("%f\t\t%f\r\n",frq*19.5,outmax);
		//清屏
        LCD_Clear(0xFFFF);
//				//绘制水平刻度,因为所使用的示波器的分度是1.25kHz/分度
//				//为了方便对比,这里也取1.25kHz,即1.25k/19.5=64格
//        POINT_COLOR=RED;
//        for(i=0; i<5; i++)
//            LCD_DrawLine(0,64*i,239,64*i);	//1.25k
//        //绘制频谱图,因显示屏分辨率是320*240,这里只取前0--319*19.5Hz范围的频域进行显示
//				POINT_COLOR=BLUE;
//        for(i=1; i<319; i++)
//        {
//						//比例缩小及限幅
//            height=fft_outputbuf[i]/100;
//            if(height>239)	height=239;
//            LCD_DrawLine(0,i,height,i);
//        }
								//绘制水平刻度,因为所使用的示波器的分度是1.25kHz/分度
				
				//绘制0--10kHz范围的频域进行显示
				//因为20kHz的采样速率决定了最大显示的频率是10kHz,快速傅里叶变换后,后半截与前半截对称,舍弃
        POINT_COLOR=RED;
        for(i=0; i<11; i=i+2)
            LCD_DrawLine(0,32*i,239,32*i);	//1.25k	32div	
		POINT_COLOR=BLUE;
        for(i=1; i<256; i++)
        {
						//比例缩小及限幅
            height=(fft_outputbuf[i*2]+fft_outputbuf[i*2+1])/100;	//取两者的平均
            if(height>239)	height=239;
            LCD_DrawLine(0,i,height,i);
        }
    }
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
	{
		//LED1=!LED1;
			timeout++;
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}

以正点原子F407开发板 实验47 DSP测试实验 例程为蓝本,添加adc.c、adc.h到项目中,实现模拟信号采集并做硬件快速傅立叶变换。

猜你喜欢

转载自blog.csdn.net/qq_27508477/article/details/83241683
F4