STM32F4 FFT 音乐频谱 不要太easy!_音乐频谱灯stm32 fft

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新

需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)

如果你需要这些资料,可以戳这里获取


  

      上段代码就是模拟生成一个序列。原始信号由三个正弦信号和一个直流信号叠加而成,频率分别是10Hz、40Hz和80Hz,峰值分别为1、3、5,直流分量为1。 通过测试,可以发现,系统计算4096点的傅里叶变换需要的时间仅仅只要2.71ms,可见其速度是非常快。在傅里叶变换的输出中,我们可以发现只有在Outputbuf[0]、Outputbuf[1]、Outputbuf[4]、Outputbuf[8]处傅里叶变换的结果分别为4096、2048、6144、10240;Outputbuf[4088]、Outputbuf[4092]、Outputbuf[4095]处的值分别为10240、6144、2048。下面来分析这些结果。


     模拟的采样频率为40960Hz,采样的点数为4096,由数字信号处理知识可知,分辨率为10Hz,也即傅里叶变换计算后的频谱之间的间隔是10Hz。而Inputdata[2\*i]=1+1\*arm\_sin\_f32(2\*PI\*10\*i/Fs)+3\*arm\_sin\_f32(2\*PI\*\*40\*i/Fs)+5\*arm\_sin\_f32(2\*PI\*80\*i/Fs)。可知待测信号由三个正弦信号和一个直流信号叠加而成,频率分别是10Hz、40Hz和80Hz,峰值分别为1、3、5,直流分量为1。


     因为A/D采样后的时序信号为实信号,根据DFT的对称性可知,其傅里叶变换的结果具有共轭反对称性。Outputbuf[1]和Outputbuf[4095],Outputbuf[4]和Outputbuf[4092],Outputbuf[8]和Outputbuf[4088]幅值应该相同,实际情况再次和理论值完全相同。


     根据DFT变换后的性质可知:Outputbuf[0]=4096,其傅里叶变换变换后的模值刚好是原始信号的4096倍,所以值为4096.0;而在其它频率点处,模值应该是幅值的4096/2=2048倍,输出的结果刚好为Outputbuf[1]=4096、Outputbuf[4]=2048、Outputbuf[8]=6144与理论值完全相同,可见傅里叶变换运算的精度极高,运算速度极快。


**下面我们用Matlab验证算法的正确性:**  
 



Matlab 程序:




close all; %Turn off all the pictures
clc;
DC=1; %The magnitude of the dc signal
Amp1=1; %The amplitude of the first signal
Amp2=3; %The amplitude of the second signal
Amp3=5; %The frequency of the third signal
Fre1=10;%The frequency of the first signal )
Fre2=40;%The frequency of the Second signal
Fre3=80;%The frequency of the third signal
Fs=40960; %The sampling frequency
N=4096; %The sampling points
t=[0:1/Fs:1]; %Sampling time
S=DC+Amp1sin(2piFre1t)+Amp2sin(2piFre2t)+Amp3sin(2piFre3t); %信号
%Display the original signal
subplot(3,1,1);
plot(S,‘b’);
grid on;
xlabel(’ Frequency/HZ’);
ylabel(‘Voltage’);
title(‘The original signal’);
Y = fft(S,N); %Do FFT transform
Module = (abs(Y)); %:Acquire modulus
subplot(3,1,2);
F=([1:N]-1)*Fs/N;
h = stem(F(1:N/320)/10,Module(1:N/320),‘fill’,‘–’);
set(get(h,‘BaseLine’),‘LineStyle’,‘:’)
set(h,‘MarkerFaceColor’,‘red’)
grid on;
xlabel(’ FFTout[i]‘);
ylabel(‘FFT module’);
title(‘the module value of FFT’);
Module=Module/(N/2);
Module(1)=Module(1)/2;
F=([1:N]-1)*Fs/N;
subplot(3,1,3);
h = stem(F(1:N/320),Module(1:N/320),‘fill’,’–‘);
set(get(h,‘BaseLine’),‘LineStyle’,’:‘)
set(h,‘MarkerFaceColor’,‘red’)
grid on;
xlabel(’ Frequency /HZ’);
ylabel(‘Voltage’);
title(‘Amplitude - frequency curves’);


Matlab运行的结果如下所示:  
 
![](https://img-blog.csdn.net/20150607144753530?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGR1eGllanVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)


图1 FFT仿真结果  
 


    从Matlab仿真出来的结果和理论的结果完全一样。图一为原始的信号,原始信号由三个正弦信号和一个直流信号叠加而成,频率分别是10Hz、40Hz和80Hz,峰值分别为1、3、5,直流分量为1。图二为输入信号进行FFT运算后的输出结果,可以看出在FFTout[1]、FFTout[4]、FFTout[8]处有值,且值得大小和输入信号的幅度有关。图三为将模值化为实际电压值后的结果,可以看出其分别在频率0Hz、10Hz、40Hz、80Hz处的幅值分别为1、1、3、5。


  
 


注意事项:  
 


* 输入音乐信号可以是电脑、iPad、手机等音频信号,但是不可接直接将音频信号送入STM32的IO口,负的电平可能直接烧坏STM32的内部AD,因此需要做适当的信号调理电路,对输入的音乐信号进行放大、电平抬升等。


  

  

  

  


![img](https://img-blog.csdnimg.cn/img_convert/5844c279321032d8b2dfe1eaf4febe4f.png)
![img](https://img-blog.csdnimg.cn/img_convert/8778ec5254ff887529b9c51589d20f55.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上物联网嵌入式知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、电子书籍、讲解视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

视频,并且后续会持续更新**

**需要这些体系化资料的朋友,可以加我V获取:vip1024c (备注嵌入式)**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618679757)**

Main: #include "led.h" #include "delay.h" #include "key.h" #include "sys.h" #include "lcd.h" #include "usart.h" #include "adc.h" #include "stm32_dsp.h" #include /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define DOUBLE_COLOR 1 //ÊÇ·ñΪ˫ɫÆÁ£¬ÈôΪ˫ɫÆÁÔò¸ÄΪ1 #define NPT 64 //FFT²ÉÑùµãÊý #define GREEN_STOP_TIME 15 //ÂÌÉ«µã¶¥¶ËÍ£¶Ùʱ¼ä£¬ÖµÔ½´óʱ¼äÔ½³¤ #define GREEN_SUB_SPEED 100 //ÂÌÉ«µãÏÂÒÆËٶȣ¬ÖµÔ½´óËÙ¶ÈÔ½Âý #define RED_SUB_SPEED 50 //ºìɫƵÖùÏòÏÂËõ¶ÌËٶȣ¬ÖµÔ½´óËÙ¶ÈÔ½Âý uint32_t ADC_DataNum=0; //ADC²ÉÑùµãÊý uint32_t RedTime=0; //ºìÉ«µãÏÂÒÆʱ¼ä±äÁ¿ #if DOUBLE_COLOR uint32_t GreenTime=0; //ÂÌÉ«µãÏÂÒÆʱ¼ä±äÁ¿ uint32_t GreenStopTime[32]={0}; //ÂÌÉ«µã¶¥¶ËÍ£¶Ùʱ¼äÊý¾Ý #endif volatile uint8_t ADC_TimeOutFlag=1; //ADC¶¨Ê±²ÉÑùʱ¼äµ½±êÖ¾ extern __IO uint16_t ADCConvertedValue; //ADC²ÉÑùÖµ extern int LCD_COLOR; long lBUFMAG[NPT+NPT/2]; //´æ´¢ÇóÄ£ºóµÄÊý¾Ý long lBUFOUT[NPT];//FFTÊä³öÐòÁÐ long lBUFIN[NPT];//FFTÊäÈëϵÁÐ uint8_t fftHightRedBuf[NPT/2]={0}; //ºìɫƵÖù¸ß¶ÈÊý×é uint8_t DisplayRedDataBuf[32*8]={0}; //ºìÉ«ÏÔʾ»º³åÇø #if DOUBLE_COLOR uint8_t fftHightGreenBuf[NPT/2]={0}; //ÂÌɫƵµã¸ß¶ÈÊý×é uint8_t DisplayGreenDataBuf[32*8]={0}; //ÂÌÉ«ÏÔʾ»º³åÇø #endif u16 color_tab[16]={DARKBLUE,BLUE,LIGHTBLUE,GREEN,LIGHTGREEN,RED,BRED,BRRED,BLACK,YELLOW,CYAN,MAGENTA,GRAYBLUE,LGRAYBLUE,BROWN,LGRAY}; void music_fft_main(uint8_t *RedNewHeight,uint8_t *GreenNewHeight) { int BarWidth = 8; int i=0; int j=0; static uint8_t RedOldHeight[32] = {0}; static uint8_t GreenOldHeight[32] = {0}; for(i=0;iRedOldHeight[i]){//Èç¹ûµ±Ç°µÄÂÌÉ«Öù×Ӹ߶ȱÈ֮ǰµÄ´óÔò²¹ÆëÂÌÉ«Öù×Ó LCD_Fill(RedOldHeight[i],(BarWidth+2)*i,RedNewHeight[i],(BarWidth+2)*i+BarWidth,color_tab[j]); }else{//Èç¹ûµ±Ç°ÏÔʾµÄÂÌÉ«Öù×Ӹ߶ÈСÓÚ֮ǰµÄÖù×ÓÔòÐèÒª½«¶àÓàµÄÂÌÉ«Öù×ÓÓñ³¾°É«Ìî³ä LCD_Fill(RedNewHeight[i],(BarWidth+2)*i,RedOldHeight[i],(BarWidth+2)*i+BarWidth,WHITE); } //½«ÐÂÊý¾Ý±£´æ RedOldHeight[i] = RedNewHeight[i]; GreenOldHeight[i] = GreenNewHeight[i]; if(j>=15) j=0; j++; } } void powerMag(long nfill) { int32_t lX,lY; uint32_t i; for (i=0; i < nfill; i++) { lX= (lBUFOUT[i]<>16; /* sine_cosine --> cos */ lY= (lBUFOUT[i] >> 16); /* sine_cosine --> sin */ { float X= 64*((float)lX)/32768; float Y = 64*((float)lY)/32768; float Mag = sqrt(X*X+ Y*Y)/nfill; // ÏÈƽ·½ºÍ,ÔÙ¿ª·½ lBUFMAG[i] = (long)(Mag*65536); } } } int main(void) {uint32_t i=0; delay_init(); //ÑÓʱº¯Êý³õʼ»¯ NVIC_Configuration(); //ÉèÖÃNVICÖжϷÖ×é2:2λÇÀÕ¼ÓÅÏȼ¶£¬2λÏìÓ¦ÓÅÏȼ¶ uart_init(9600); //´®¿Ú³õʼ»¯Îª9600 LED_Init(); //LED¶Ë¿Ú³õʼ»¯ TIM2_Configuration(); TIM2_NVIC_Configuration(); FFT_RCC_Configuration(); FFT_GPIO_Configuration(); FFT_DMA_Init(); FFT_ADC_Init(); LCD_Init(); // BACK_COLOR=BLACK; TIM_Cmd(TIM2, ENABLE); ADC_SoftwareStartConvCmd(ADC1, DISABLE); while(1) { if(ADC_TimeOutFlag){ #if DOUBLE_COLOR GreenTime++; #endif RedTime++; ADC_TimeOutFlag=0; if(ADC_DataNumCR2 |= 0x00500000;// ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!DMA_GetFlagStatus(DMA1_FLAG_TC1)); /* Clear channel1 transfer complete flag */ DMA_ClearFlag(DMA1_FLAG_TC1); // ADC1->CR2 &= 0xFFAFFFFF;// ADC_SoftwareStartConvCmd(ADC1, DISABLE); lBUFIN[ADC_DataNum]=ADCConvertedValue<<16; ADC_DataNum++; }else{ TIM_Cmd(TIM2, DISABLE); ADC_DataNum=0; cr4_fft_64_stm32(lBUFOUT,lBUFIN,NPT);//µ÷ÓÃSTM32µÄDSP¿â×÷FFT±ä»» powerMag(NPT);//¼ÆËãƵµã·ùÖµ //¸üкìÉ«µãµÄ¸ß¶È for(i=0;ifftHightRedBuf[i]){ fftHightRedBuf[i]=(lBUFMAG[i]); } #if DOUBLE_COLOR //Ë¢ÐÂÂÌÉ«µã¸ß¶È if(fftHightRedBuf[i]>=fftHightGreenBuf[i]){ fftHightGreenBuf[i]=fftHightRedBuf[i]; GreenStopTime[i]=GREEN_STOP_TIME;//Â̵ãÍ£¶Ùʱ¼ä if(fftHightRedBuf[i]>=235){ fftHightGreenBuf[i]=235; fftHightRedBuf[i]=235; } } #else if(fftHightRedBuf[i]>=239){ fftHightRedBuf[i]=239; } #endif } //ÏÔʾºìÉ«Öù×Ó music_fft_main(fftHightRedBuf,fftHightGreenBuf); //ÏÔʾÂÌÉ«µã #if DOUBLE_COLOR //ÂÌÉ«µãÏÂÒÆ if((GreenTime>GREEN_SUB_SPEED)){ //ÂÌÉ«µãϽµ¼ä¸ôʱ¼ä GreenTime=0; for(i=0;iRED_SUB_SPEED){ RedTime=0; for(i=0;i<NPT/2;i++){ if((fftHightRedBuf[i]!=0)){ fftHightRedBuf[i]--; } } } //ÂÌÉ«µãÍ£¶Ùʱ¼ä¼õÒ» #if DOUBLE_COLOR for(i=0;iSR = (uint16_t)~TIM_FLAG_Update; TIM_ClearITPendingBit(TIM2,TIM_FLAG_Update); //ÇåÖÐ¶Ï ADC_TimeOutFlag=1; } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值