野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24707|回复: 18

关于使用ADC+DMA+FFT做 音乐频率显示 完整篇

[复制链接]
发表于 2016-1-5 14:22:32 | 显示全部楼层 |阅读模式
本帖最后由 kevin_D 于 2016-1-5 14:40 编辑

程序主要分 1:测试FFT处理数据显示部份 2:ADC+DMA数据处理部份 3:幅度计算部份  4:频率计算部份 5:频谱显示系统
1:测试FFT处理数据显示部份
  1. float testInput[BufferSize*2];    //BufferSize为采样点数,数据来自  ADC.H
  2. float testOutput[BufferSize];
复制代码

2:ADC+DMA数据处理部份
  1. #include "./adc/bsp_adc.h"

  2. uint16_t uhADC3Converted_buffer1[BufferSize]={0};
  3. uint16_t uhADC3Converted_buffer2[BufferSize]={0};

  4. DMA_InitTypeDef DMA_InitStructure;
  5. void ADC3_DMA_RX_Config(uint16_t *Bufferdst)
  6. {
  7.     ADC_Cmd(RHEOSTAT_ADC, DISABLE);//ADC_Cmd(ADC3, DISABLE);//必顺先把ADC关掉然后再把DMA传输关掉        
  8.     DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, DISABLE);//DMA_Cmd(DMA2_Stream0, DISABLE);//        
  9.     DMA_ClearFlag(RHEOSTAT_ADC_DMA_STREAM,DMA_FLAG_TCIF0|DMA_FLAG_HTIF0|DMA_FLAG_TEIF0|DMA_FLAG_DMEIF0|DMA_FLAG_FEIF0);
  10.     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Bufferdst;        
  11.     DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);
复制代码
ADC函数部份
  1. #ifndef __ADC_H
  2. #define        __ADC_H

  3. #include "stm32f4xx.h"

  4. #define BufferSize    1024  //2048//4096   //下面就直接引用   野火 STM32F429 例程文件中的“ADC—单通道(DMA)”
复制代码
TIM2采样频率  40K或44.1K配置

  1. void TIM_GPIO_Config_2(void)
  2. {
  3.        GPIO_InitTypeDef GPIO_InitStructure;        
  4.        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);        
  5.        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        
  6.        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;        
  7.        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;        
  8.        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        
  9.        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        
  10.        GPIO_Init(GPIOA,&GPIO_InitStructure);  
  11.        GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM2);               
  12. }
  13.         
  14. static         void TIM2_NVIC_Configuration(void)
  15. {
  16.        NVIC_InitTypeDef NVIC_InitStructure;
  17.        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  18.        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  19.        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  20.        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        
  21.        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        
  22.        NVIC_Init(&NVIC_InitStructure);
  23. }
  24. static void TIM2_Mode_Config(void)
  25. {        
  26.        TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStructure;               
  27.        u16 TimerPeriod =  (SystemCoreClock / TimerPeriodDIV ) - 1;         
  28.        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);        
  29.        //RCC_TIMCLKPresConfig(RCC_TIMPrescActivated);         
  30.        TIM_Cmd(TIM3, DISABLE);               
  31.        TIM_TimeBaseInitStructure.TIM_Period = TimerPeriod-1;        
  32.        TIM_TimeBaseInitStructure.TIM_Prescaler = 0;        
  33.        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  34.        TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  35.        TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  36.        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);        
  37.        if(GPIO_PWM_OUT)  //如果 GPIO_PWM_OUT 为直,说明大家有示波器,就让TIM2_CH1/CH2/CH3/CH4输出波形,测试一下方波周期是否是正确,
  38. <blockquote><span class="Apple-tab-span" style="line-height: 1.5; white-space: pre;">        </span><span style="line-height: 1.5;">{</span>
复制代码
最后就是主程序部份
  1. while(1)
  2.         {        
  3.                 if(it_flag==1)
  4.                 {                                       
  5.             if(buffer_flag==0)
  6.                         {        
  7.                                 buffer_flag=1;        
  8.                                 
  9.                                 FFTDisp_MainLoop(uhADC3Converted_buffer1);
  10.                                 
  11.                                 if(TEST_FFT_V)TEST_FFT_VIEW();   //这里是显示 频谱部份就没有写,因为有些人使用的是LED灯显示,有些使用的是  液晶屏
  12.                                 
  13.                                 else TEST_FFT_MAXT(); //这是求最大频率
  14.                                                                
  15.                           ADC3_DMA_RX_Config(uhADC3Converted_buffer2);
  16.                   }
  17.                         else
  18.                         {
  19.                                 buffer_flag=0;        
  20.                                 
  21.                                 FFTDisp_MainLoop(uhADC3Converted_buffer2);
  22.                                 
  23.                                 if(TEST_FFT_V)TEST_FFT_VIEW();
  24.                                 
  25.                                 else TEST_FFT_MAXT();
  26.                                                                
  27.                                 ADC3_DMA_RX_Config(uhADC3Converted_buffer1);        
  28.                         }                        
  29.                         it_flag=0;
  30.                 }        
  31.         }
  32. }
复制代码





主程序框图

主程序框图
回复

使用道具 举报

 楼主| 发表于 2016-1-5 14:41:08 | 显示全部楼层
  1. if(GPIO_PWM_OUT)
  2.         {
  3.                 TIM_OCInitTypeDef TIM_OCInitStructure;        
  4.                
  5.                 u16 ccr4 = TimerPeriod / 2;  //&#213;&#188;&#191;&#213;±è1/3 = 33%       
  6.                 /* -----------------------------------------------------------------------
  7.     TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR+1)* 100% = 50%
  8.     TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR+1)* 100% = 37.5%
  9.     TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR+1)* 100% = 25%
  10.     TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR+1)* 100% = 12.5%
  11.   ----------------------------------------------------------------------- */
  12.                
  13.                 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  14.                
  15.                 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  16.                
  17.                 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  18.                
  19.                 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  20.                
  21.                 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
  22.                
  23.                 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  24.                
  25.                 TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
  26.                                
  27.                 TIM_OCInitStructure.TIM_Pulse = ccr4;                       
  28.                 TIM_OC4Init(TIM2,&TIM_OCInitStructure);       

  29.                 TIM_CtrlPWMOutputs(TIM2,ENABLE);        //&#197;D&#182;&#207;è&#231;1&#251;ê1&#196;üGPIO_PWMê&#228;3&#246;
  30.         }       
  31.         else
  32.         {                               
  33.                 TIM_ClearFlag(TIM2, TIM_FLAG_Update);// &#199;&#229;3y&#188;&#198;êy&#198;÷&#214;D&#182;&#207;±ê&#214;&#190;&#206;&#187;
  34.                
  35.                 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);  //·&#241;&#212;ò&#190;í&#191;a&#214;D&#182;&#207;
  36.         }
  37.        
  38.         TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update);//&#209;&#161;&#212;&#241;TIM3ê&#228;3&#246;′¥·¢&#212;′
  39.        
  40.         TIM_Cmd(TIM2, ENABLE);       
  41. }
复制代码
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2016-1-5 14:41:39 | 显示全部楼层
  1. void ADC3_DMA_RX_Config(uint16_t *Bufferdst)
  2. {
  3.         ADC_Cmd(RHEOSTAT_ADC, DISABLE);//ADC_Cmd(ADC3, DISABLE);//±&#216;D&#235;&#207;è°&#209;ADC1&#216;μ&#244;è&#187;oó&#212;ù°&#209;DMA′&#171;ê&#228;1&#216;μ&#244;       
  4.        
  5.   DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, DISABLE);//DMA_Cmd(DMA2_Stream0, DISABLE);//ê§&#196;üDMA  
  6.        
  7.         DMA_ClearFlag(RHEOSTAT_ADC_DMA_STREAM,DMA_FLAG_TCIF0|DMA_FLAG_HTIF0|DMA_FLAG_TEIF0|DMA_FLAG_DMEIF0|DMA_FLAG_FEIF0);

  8.   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Bufferdst;
  9.        
  10.   DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);        
  11.   DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);
  12.         ADC_Cmd(RHEOSTAT_ADC, ENABLE);//&#207;èê1&#196;üDMA′&#171;ê&#228;£&#172;&#212;ù&#191;aADC
  13. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2016-1-5 15:18:44 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 2016-1-19 11:26:20 | 显示全部楼层
楼主,你好,可以分享一下整个工程吗
回复 支持 反对

使用道具 举报

发表于 2016-2-1 19:55:58 | 显示全部楼层
赞!!!!!!!
回复

使用道具 举报

发表于 2016-12-25 17:49:26 | 显示全部楼层
大神加个好友先
回复 支持 反对

使用道具 举报

发表于 2017-1-21 10:59:55 | 显示全部楼层
很好的资料,不错,支持
回复 支持 反对

使用道具 举报

发表于 2017-2-4 13:24:50 | 显示全部楼层
感谢大神
正好需要
回复 支持 反对

使用道具 举报

发表于 2017-2-6 09:59:10 | 显示全部楼层
厉害,加个好友吧!
回复 支持 反对

使用道具 举报

发表于 2017-9-24 21:25:20 | 显示全部楼层

大神,能分享一下整个工程吗?谢啦
回复 支持 反对

使用道具 举报

发表于 2018-6-9 23:02:05 | 显示全部楼层
您好,请问可以直接用耳机的左右声道线直接接AD采集口吗
回复 支持 反对

使用道具 举报

发表于 2019-3-21 22:17:10 | 显示全部楼层
1111111111111
回复 支持 反对

使用道具 举报

发表于 2019-3-21 22:18:19 | 显示全部楼层
大神能分享下工程吗?谢谢了,急需!1061091328@qq.com 跪谢
回复 支持 反对

使用道具 举报

发表于 2020-2-9 17:30:47 | 显示全部楼层
大神  能把音乐频率显示的工程发我研究一下吗?我最近在做这方面的毕设 拜托了    邮箱:[email]2947214720@qq.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 23:17:39 | 显示全部楼层
这么早就做出这了,不错!我来搬砖
回复 支持 反对

使用道具 举报

发表于 2021-9-28 10:06:18 | 显示全部楼层
老铁  代不代码不重要  主要是原理思路  我现在还搞不清楚 我要怎么把音频数据呈现在音乐柱的样子
回复 支持 反对

使用道具 举报

发表于 2021-9-28 10:48:52 | 显示全部楼层
顶顶顶
回复

使用道具 举报

发表于 2021-9-28 18:00:45 | 显示全部楼层
6666666666666666666
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-24 11:06 , Processed in 0.040993 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表