版权声明:本文为博主原创文章,未经博主允许不得转载。 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到项目中,实现模拟信号采集并做硬件快速傅立叶变换。