找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 30407|回复: 50
打印 上一主题 下一主题
收起左侧

DIY单片机迷你音乐频谱显示器 点阵显示 带FFT

  [复制链接]
跳转到指定楼层
楼主

所有制作资料打包下载:
迷你音乐频谱显示器.rar (1.81 MB, 下载次数: 504)

实现功能:
# 电路制作简单,无需PCB板,只需元器件,采用USB 接口供电
# 采用LED点阵16*8显示,随音频变化而起伏显示
# 自动增益校正功能,音量调大调小都不会过满显示或显示过少(当然,音量也不能太小了。输入音量过小、电平比较低时,可以把音响的音量调小一点,音源的音量调大一些)

电路原理图:
管脚连接说明
单片机的1为音频信号输入端,2~9/32~39LED1点阵引脚,10~17/24~31LED2点阵引脚,18/19为晶振、电容引脚,21/22为指示灯引脚(21极,22极)
40VCC电源5V正极,20GND电源负极(也是音频信号输入负极)23为空脚悬空
制作说明
1、用热熔胶或502胶水将USB公头反向粘到芯片底座的左侧(底座缺口一侧)
2、将USB公头上的正极连至40负极连至20,将2PIN排针粘到芯片底座的右侧(频谱接口)上端接1脚,下端接20
3、2个30PF电容连接至芯片底座的181920(一个接1820脚,另一个接1920脚)
4、32.768MHZ晶振连接至芯片底座的1819
5、将芯片安放置底座上,缺口对缺口
6、8*8点阵管脚识别方法:点阵旁边的字朝下,下边那行的左边开始数是第一脚,然后逆时针走一圈1~16脚,和集成块的数法一样,然后对照点阵原理图看!
点阵的识别与测试视频:http://v.youku.com/v_show/id_XMjMwODU4OTQ0.html
7、将2个8*8点阵安放于另一个芯片底座上,如图所示,左侧空出1列,右侧空出3,右侧底下两只脚接发光二极管(左正右负
8、将两块芯片底座合并,40个管脚依次焊接到一起,USB公头接上USB延长线到电脑音频接口接上杜邦线到音频线,到音频分离器
9、制作音频线:
10、一分二音频分线器可以让音乐频谱显示器与音响并联
11、音乐频谱显示器通过USB接口取电从音频接口采集音乐信号
注意事项:
1、电脑音量不能太小,因为检测电压幅值,音量太小了对单片机ADC采集会有影响,建议音量调到中等以上为最佳显示效果。同时,可以通过调节音响的音量来控制声音的大小(把音响的音量调小一点,电脑的音量调大一些)。

2、拔掉音频接口信号输入端(悬空),显示会满屏,拔掉音频接口信号接地端,只显示最下面一行!

3、在静音的状态下,显示屏若时有波动,这是空中的电磁波的影响,是属于正常情况。


12、成品展示


元器件清单:
1、单片机STC12C5A60S2 PDIP40 (1片)
2、0788形红色8*8LED点阵屏(2块)
3、普通芯片座PIN40(2个)
4、USB公头(1个)
5、32.768MHz石英晶体(1个)
6、30pF电容(2个)
7、2PIN排针(1个)
8、1PIN杜邦线(2根)
9、USB延长线公对母(1根)
10、音频头(1个)
11、音频线(1根)
12、音频分离器(1个)
13、发光二极管(1个)
14、导线 若干


主程序:
  1. /********************************************************************************************
  2. 程序名:    迷你音乐频谱显示器
  3. 编写人:   
  4. 编写时间:  
  5. 硬件支持:  2个8*8点阵  STC12C5A60S2 外部32.768MHz晶振
  6. 接口说明:  见说明文档 
  7. *********************************************************************************************/
  8. #include "src\STC12C5A.h"                 
  9. #include <intrins.h>    //51基本运算(包括_nop_空函数)
  10. #include <math.h>
  11. #include "src\Define.h"
  12. ///////全局变量///////
  13. uchar data DelayTime=10;
  14. uchar data INTTime=0x45;
  15. uchar data gain=1;
  16. uchar data Menu=0;
  17. uchar idata  refreshflag[40];
  18. //////////////////////
  19. void Delays(uint t)
  20. {  
  21.         uint j;
  22.         while(--t)
  23.                 for(j=0;j<5;j++);   
  24. }
  25. uchar data LEDBuf[35];                         //15列;从左到右;亮的位为真(1);
  26. #include "src\ADC.c"
  27. #include "src\fft.h"
  28. #include "src\LED168D.h"

  29. void LIOINIT( )
  30. {
  31.         P4SW = 0xff;                                  //启动I/O:P4;

  32.         P0M1 = 0x00;            P0M0 = 0xff;          //I/O强上拉模式;
  33.         P1M1 = B(00000001);        P1M0 = B(11111110);   //P10(光敏电阻:AD:高阻或开漏)
  34.         P4M1 = 0x00;             P4M0 = 0xff;        
  35.         P2M1 = B(00000000); P2M0 = B(11111001);   //P21,P20(强上拉);P22(传统IO);
  36.         P3M1 = 0x00;               P3M0 = 0xff;          //!!!

  37.         P0 = 0xff;                                          //初始化;
  38.         P1 = B(11111110);
  39.         P4 = 0xff;
  40.         P2 = B(11111100);
  41.         P3 = 0xff;        
  42.         ////////////////////////////////
  43.         P04=0;P26=0;  //LY;
  44.         P01=0;P45=0;
  45.         P06=0;P24=0;
  46.         P00=0;P46=0;
  47.         P15=0;P34=0;
  48.         P07=0;P23=0;
  49.         P13=0;P32=0;
  50.         P47=0;P37=0;
  51.         ////////////////////////////////
  52.         P14=1; P33=1;  //LX0; //LX1;
  53.         P02=1; P44=1;         
  54.         P03=1; P27=1;         
  55.         P17=1; P36=1;         
  56.         P05=1; P25=1;         
  57.         P16=1; P35=1;         
  58.         P12=1; P31=1;         
  59.         P11=1; P30=1;                        
  60. }

  61. //////////////////////////////////////////////////////
  62. void LEDRefresh() interrupt 3 //using 3   
  63. {
  64.     TL1 = 0x00;      
  65.     TH1 = INTTime;   //0x50~0x80 //0x6A
  66.         BuftoLED168_Refresh();
  67. }  
  68. /////////////////////////////////////////////////////

  69. /*SFR中与定时/计数器工作方式有关的设计]
  70. -----------------------------------------------------------------------------
  71. M1        M0        方式        说明
  72. 0        0        0        13位T/C,由TL低5位和TH的8位组成13位计数器
  73. 0        1        1        16位T/C,TL和TH共16位计数器
  74. 1        0        2        8位T/C,TL用于计数,当TL溢出时将TH中的值自动写入TL
  75. 1        1        3        两组8位T/C
  76. -----------------------------------------------------------------------------
  77. */
  78. void Timer_INT()
  79. {
  80.          TMOD = 0x11; //高4位控制T/C1 [ GATE,C/T,M1,M0,GATE,C/T,M1,M0 ]
  81.         EA = 1;        //中断总开关

  82.         TH1 = 0x00; //16位计数寄存器T1高8位(写入初值)
  83.         TL1 = 0x00; //16位计数寄存器T1低8位
  84.         ET1 = 1; //T/C1中断开关
  85.     TR1 = 1; //T/C1启动开关
  86. }

  87. void Main()
  88. {  
  89.         uint data Count=700;
  90.         uchar data i,Cgain,LED=0,num=0;
  91.         LIOINIT();          //I/O强上拉模式
  92.         InitADC();    //Init ADC sfr         
  93.         for(i=0;i<40;i++) refreshflag[i]=0x09;
  94.         P20=0;                  //LED负极
  95.         Timer_INT();  //定时器初始化
  96.         while(1)
  97.         {
  98.                 for(i=0;i<65;i++)
  99.                 {  
  100.                         dd[i].real=(GetADCResult(0))<<gain;
  101.                         dd[i].imag=0; //清零虚部
  102.                 }
  103.                  processfft();//傅立叶变化及处理
  104.                  LED=!LED;
  105.                  if(dd[2].real<32)
  106.                  {
  107.                          LED=1;
  108.                  }
  109.                  else
  110.                  {
  111.                          Count=1;
  112.                          if(++num==0xAF)                                 //播放时,Auto gain;
  113.                          {
  114.                                 num=0;

  115.                                 P2M0 = B(11111011);
  116.                                 P21=1;                          //LED正极
  117.                                 Delays(2000);
  118.                                 P21=0;                         //LED正极
  119.                                 P2M0 = B(11111001);

  120.                                 //自动增益;Automatic gain;
  121.                                 Cgain=dd[2].real/32;
  122.                                 if(7<Cgain<=8)
  123.                                 {
  124.                                         gain=2;
  125.                                        
  126.                                 }
  127.                                 else if(4<Cgain<=6)
  128.                                 {
  129.                                         gain=3;               
  130.                                 }
  131.                                 else if(2<Cgain<=4)
  132.                                 {
  133.                                         gain=4;
  134.                                 }
  135.                                 else
  136.                                 {
  137.                                         gain=5;
  138.                                 }
  139.                          }
  140.                   }

  141.                   P21=LED;         //LED正极         
  142.         }
  143. }
  144. /*****************************************************************************/
  145. //
  146. /*****************************************************************************/
复制代码

fft程序:
  1. #ifndef _FFT_INCLUDED_
  2. #define _FFT_INCLUDED_

  3. struct compx
  4. {
  5.         float real;
  6.         float imag;
  7. };//定义数据存放机构体

  8. struct compx dd[65]; //FFT数据段   
  9. code float iw[64]=
  10. {
  11.         1.000,0,0.9952,-0.0980,0.9808,-0.1951,0.9569,-0.2903,0.9239,-0.3827,0.8819,-0.4714,0.8315,-0.5556,
  12.         0.7730,-0.6344,0.7071,-0.7071,0.6344,-0.7730,0.5556,-0.8315,0.4714,-0.8819,0.3827,-0.9239,0.2903,-0.9569,
  13.         0.1951,-0.9808,0.0980,-0.9952,0.0,-1.0000,-0.0980,-0.9952,-0.1951,-0.9808,-0.2903,0.9569,-0.3827,-0.9239,
  14.         -0.4714,-0.8819,-0.5556,-0.8315,-0.6344,-0.7730,-0.7071,-0.7071,-0.7730,-0.6344,-0.8315,-0.5556,-0.8819,-0.4714,
  15.         -0.9239,-0.3827,-0.9569,-0.2903,-0.9808,-0.1951,-0.9952,-0.0980
  16. };//w值缓存区

  17. data struct compx temp;  
  18. //复数乘法
  19. void ee(struct compx b1,uchar data b2)
  20. {
  21.         temp.real=b1.real*iw[2*b2]-b1.imag*iw[2*b2+1];
  22.         temp.imag=b1.real*iw[2*b2+1]+b1.imag*iw[2*b2];
  23. }
  24. //乘方函数,计算 nbottom^ntop   
  25. uint mypow(uchar data nbottom,uchar data ntop)
  26. {
  27.     uint data result=1;
  28.     uchar data t;   
  29.     for(t=0;t<ntop;t++)result*=nbottom;//nbottom^ntop
  30.     return result;
  31. }
  32. //快速傅立叶变换  
  33. void fft(struct compx *xin,uchar data N)
  34. {
  35.         uchar data  fftnum,i,j,k,l,m,n,disbuff,dispos,dissec;
  36.         data struct compx t;
  37.         fftnum=N;//傅立叶变换的点数
  38.         for(m=1;(fftnum=fftnum/2)!=1;m++);//求得M的值
  39.         for(k=0;k<=N-1;k++)//码位倒置
  40.         {
  41.                 n=k;
  42.                 j=0;
  43.                 for(i=m;i>0;i--)//倒置
  44.                 {
  45.                         j=j+((n%2)<<(i-1));
  46.                         n=n/2;
  47.                 }
  48.                 if(k<j){t=xin[1+j];xin[1+j]=xin[1+k];xin[1+k]=t;}//交换数据
  49.         }  
  50.         for(l=1;l<=m;l++)//fft运算
  51.         {
  52.                 disbuff=mypow(2,l);//求得碟间距离
  53.                 dispos=disbuff/2;//求得碟形两点之间的距离
  54.                 for(j=1;j<=dispos;j++)
  55.                         for(i=j;i<N;i=i+disbuff)//遍历M级所有的碟形
  56.                         {
  57.                                 dissec=i+dispos;//求得第二点的位置
  58.                                 ee(xin[dissec],(uint)(j-1)*(uint)N/disbuff);//复数乘法
  59.                                 t=temp;
  60.                                 xin[dissec].real=xin[i].real-t.real;
  61.                                 xin[dissec].imag=xin[i].imag-t.imag;
  62.                                 xin[i].real=xin[i].real+t.real;
  63.                                 xin[i].imag=xin[i].imag+t.imag;
  64.                         }
  65.         }
  66. }

  67. //对fft数据进行处理,得到各个频率段的电压幅值
  68. void processfft( )
  69. {
  70.     uchar data pt=0,tmp;
  71.     for(pt=1;pt<65;pt++)
  72.     {
  73.         dd[pt].imag=0; //清零虚部
  74.     }
  75.     fft(dd,64);//对当前数据进行傅立叶变换
  76.         dd[0].imag=0;  dd[0].real=0;
  77.     for(pt=1;pt<65;pt++)
  78.     {                                      
  79.         dd[pt].real=sqrt(dd[pt].real*dd[pt].real+dd[pt].imag*dd[pt].imag);//取均方根
  80.     }

  81.         if(Menu==1)
  82.         {
  83.                 for(pt=2;pt<34;pt+=2)        
  84.             {      
  85.                         for(tmp=(dd[pt].real/32)+1,LEDBuf[pt]=0xFF;tmp>=1;tmp--)                  //tmp>1;不保留  最低位那一行常亮;{}一次也不执行;
  86.                         {
  87.                                  LEDBuf[pt]<<=1;        
  88.                                 
  89.                         }
  90.                         LEDBuf[pt]=~(LEDBuf[pt]);
  91.                 }
  92.         }
  93.         else if(Menu==2)
  94.         {

  95.                 //下落感频谱
  96.                 for(pt=2;pt<34;pt+=2)        
  97.             {      
  98.                         tmp=(dd[pt].real/32)+1;
  99.                         if(refreshflag[pt]<tmp)                  //刷新数据,取较大高度值 存储显示  
  100.                         {
  101.                                 for(LEDBuf[pt]=0xFF;tmp>1;tmp--)                  //tmp>1;不保留  最低位那一行常亮;{}一次也不执行;
  102.                                 {
  103.                                          LEDBuf[pt]<<=1;        
  104.                                        
  105.                                 }
  106.                                 refreshflag[pt]=(dd[pt].real/32)+1;
  107.                         }
  108.                         else
  109.                         {
  110.                                  if(refreshflag[pt]>1)refreshflag[pt]--;                            //顶端下落速度控制  改变值可以改变下降速度
  111.                                  for(LEDBuf[pt]=0xFF,tmp=refreshflag[pt];tmp>1;tmp--)                  //tmp>1;不保留  最低位那一行常亮;{}一次也不执行;
  112.                                 {
  113.                                          LEDBuf[pt]<<=1;        
  114.                                        
  115.                                 }

  116.                         }
  117.          
  118.                 }

  119.         }
  120.         else if(Menu==0)
  121.         {
  122.                 //下落感频谱
  123.                 for(pt=2;pt<34;pt+=2)        
  124.             {      
  125.                         tmp=(dd[pt].real/32)+1;
  126.                         if(refreshflag[pt]<tmp)                  //刷新数据,取较大高度值 存储显示  
  127.                         {
  128.                                 for(LEDBuf[pt]=0xFF;tmp>=1;tmp--)                  //tmp>1;不保留  最低位那一行常亮;{}一次也不执行;
  129.                                 {
  130.                                          LEDBuf[pt]<<=1;        
  131.                                        
  132.                                 }
  133.                                 refreshflag[pt]=(dd[pt].real/32)+1;
  134.                         }
  135.                         else
  136.                         {
  137.                                  if(refreshflag[pt]>1)refreshflag[pt]--;                            //顶端下落速度控制  改变值可以改变下降速度
  138.                                  for(LEDBuf[pt]=0xFF,tmp=refreshflag[pt];tmp>=1;tmp--)                  //tmp>1;不保留  最低位那一行常亮;{}一次也不执行;
  139.                                 {
  140.                                          LEDBuf[pt]<<=1;        
  141.                                        
  142.                                 }

  143.                         }
  144.                         LEDBuf[pt]=~(LEDBuf[pt]);
  145.          
  146.                 }

  147.         }


  148.         
  149. }  
  150. #endif
复制代码

评分

参与人数 5黑币 +23 收起 理由
cyjun99 + 5
dpj1185090651 + 5 共享资料的黑币奖励!
942811442 + 3 最近刚好做音乐节奏灯,很有用。
958842929qq + 5 很给力!点阵屏是主流趋势吧,觉得。
fay860601 + 5 赞一个!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏36 分享淘帖 顶7 踩
回复

使用道具 举报

沙发
ID:145560 发表于 2016-11-20 18:19 | 只看该作者
你好问一下,那个音频头上三根线,为什么到单片机上就两根了(p1.0和GND),还有我用32M晶振可以吗?最近做了一个但是不亮,可以恢复一下吗,万分感谢
回复

使用道具 举报

板凳
ID:145560 发表于 2016-11-20 18:28 | 只看该作者

 你好问一下,那个音频头上三根线,为什么到单片机上就两根了(p1.0和GND),还有我用32M晶振可以吗?最近做了一个但是不亮,可以恢复一下吗,万分感谢
回复

使用道具 举报

地板
ID:157950 发表于 2016-12-27 09:51 | 只看该作者
拿走了啊
回复

使用道具 举报

5#
ID:158248 发表于 2016-12-28 08:52 | 只看该作者
好东西,自己也做一个
回复

使用道具 举报

6#
ID:180268 发表于 2017-3-22 15:09 | 只看该作者
不错,不错
回复

使用道具 举报

7#
ID:180805 发表于 2017-3-22 23:18 | 只看该作者
hahahahah
回复

使用道具 举报

8#
ID:130231 发表于 2017-3-22 23:56 | 只看该作者
给力!
回复

使用道具 举报

9#
ID:187468 发表于 2017-4-8 16:26 | 只看该作者
哇 还不错 想自己diy一个大一点的  40*40的,不知道还要改哪里
回复

使用道具 举报

10#
ID:187468 发表于 2017-4-30 20:45 | 只看该作者
好东西,感谢楼主的分享
回复

使用道具 举报

11#
ID:139761 发表于 2017-5-16 10:40 | 只看该作者
学习
回复

使用道具 举报

12#
ID:116893 发表于 2017-7-31 14:00 | 只看该作者
不错不错,多谢分享。想搞一个简单的
回复

使用道具 举报

13#
ID:232387 发表于 2017-9-11 13:30 | 只看该作者
厉害厉害
回复

使用道具 举报

14#
ID:237377 发表于 2017-10-5 17:53 | 只看该作者
点阵屏是主流。很不错。
回复

使用道具 举报

15#
ID:238810 发表于 2017-10-23 11:00 来自手机 | 只看该作者
这个挺好的
回复

使用道具 举报

16#
ID:237377 发表于 2017-11-19 14:06 | 只看该作者
你好,可以问一下8*8的LED点阵屏在protel里原理图的器件和pcb里的封装有吗。
回复

使用道具 举报

17#
ID:250010 发表于 2017-11-22 12:05 | 只看该作者
这个需要matlab仿真吗,如果不需要为什么函数标识用FFTMTL呢??
回复

使用道具 举报

18#
ID:264565 发表于 2017-12-20 23:12 | 只看该作者
马上可以来试试!!
回复

使用道具 举报

19#
ID:264387 发表于 2018-1-4 17:58 | 只看该作者
有没有办法收集成语音信号?
回复

使用道具 举报

20#
ID:198286 发表于 2018-1-27 21:10 | 只看该作者
想玩,可是程序不懂,看不明白
回复

使用道具 举报

21#
ID:312212 发表于 2018-4-20 09:54 | 只看该作者
很给力!
回复

使用道具 举报

22#
ID:124995 发表于 2018-4-21 23:22 | 只看该作者
灰常不错,赞一个
回复

使用道具 举报

23#
ID:283159 发表于 2018-4-29 23:38 | 只看该作者
不错,学习一下,自己也做一个
回复

使用道具 举报

24#
ID:319464 发表于 2018-5-1 15:18 | 只看该作者
为什么附件下载到一半多就下载不动了
回复

使用道具 举报

25#
ID:328609 发表于 2018-5-14 20:57 | 只看该作者
有电路图就好了
回复

使用道具 举报

26#
ID:60026 发表于 2018-7-26 08:03 | 只看该作者
感谢楼主的分享!下载了看看!
回复

使用道具 举报

27#
ID:292119 发表于 2018-7-26 09:04 | 只看该作者
写的非常不错,顶一个
回复

使用道具 举报

28#
ID:276663 发表于 2018-7-26 10:06 | 只看该作者
简直是666啊!
回复

使用道具 举报

29#
ID:294665 发表于 2018-7-26 11:10 | 只看该作者
谢谢楼主,自己也尝试做一个
回复

使用道具 举报

30#
ID:147329 发表于 2018-11-26 17:52 | 只看该作者
太帅了,好崇拜楼主!
最近突发奇想也要做个类似的东东,没想到咱们论坛都有现成的啦~~~



回复

使用道具 举报

31#
ID:433756 发表于 2018-11-26 21:11 来自手机 | 只看该作者
不错啊,厉害
回复

使用道具 举报

32#
ID:401936 发表于 2018-12-19 20:22 | 只看该作者
课设就做它了
回复

使用道具 举报

33#
ID:308712 发表于 2019-1-2 15:31 来自手机 | 只看该作者
为啥使用32.768M的晶振啊,12M不行吗
回复

使用道具 举报

34#
ID:337484 发表于 2019-1-24 12:00 | 只看该作者
谢谢楼主,做一个试一下
回复

使用道具 举报

35#
ID:505143 发表于 2019-4-5 00:05 | 只看该作者
非常好的帖子,顶起来
回复

使用道具 举报

36#
ID:432687 发表于 2019-4-22 23:12 来自手机 | 只看该作者
灵感和学习效果的完美页面..我对这项创新感到非常惊讶好主意,和我们在一起!不幸的是,我不懂你的语言,我严重依赖翻译。谢谢分享。
回复

使用道具 举报

37#
ID:582867 发表于 2019-7-23 18:39 来自手机 | 只看该作者
好久不见 发表于 2016-11-20 18:28
 你好问一下,那个音频头上三根线,为什么到单片机上就两根了(p1.0和GND),还有我用32M晶振可以吗?最 ...

我觉得这就是音量采集直接出来应该就可以了,接头和端口连就可以。三根线不是接都接头上,然后p1.0相连接可以起到控制p1.0电压的作用。不知对不没试过
回复

使用道具 举报

38#
ID:281113 发表于 2020-2-10 15:38 | 只看该作者
学习一下
回复

使用道具 举报

39#
ID:283883 发表于 2020-2-11 11:37 | 只看该作者
很好,点阵是共阴的还是共阳的?
回复

使用道具 举报

40#
ID:413157 发表于 2020-2-13 17:43 | 只看该作者
好东西哎,赶紧自己做一个
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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