找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5979|回复: 3
收起左侧

音乐频谱(stc12系列)

  [复制链接]
ID:139654 发表于 2017-3-23 14:15 | 显示全部楼层 |阅读模式
原理图是用proteus画的,所以没有Vcc和Gnd标识
信号输入端的电阻、电容是抗干扰用的,大小请根据电路的实际情况做改动
0.png 0.png



程序如下:
  1. #include<stc12c5a.h>
  2. #include<intrins.h>
  3. //#include"basic.h"
  4. typedef unsigned char uint8;
  5. typedef unsigned int uint16;
  6. #define ADC_FLAG    (1<<4)    /*ADC_中断标志*/
  7. /*放大128倍后的sin整数表(128)*/        
  8. code char SIN_TAB[128]={0,6,12,18,24,30,36,42,48,54,59,65,70,75,80,85,89,94,98,102,
  9.                         105,108,112,114,117,119,121,123,124,125,126,126,126,126,126,
  10.                                                 125,124,123,121,119,117,114,112,108,105,102,98,94,89,85,80,75,
  11.                                                 70,65,59,54,48,42,36,30,24,18,12,6,0,-6,-12,-18,-24,-30,-36,-42,
  12.                                                 -48,-54,-59,-65,-70,-75,-80,-85,-89,-94,-98,-102,-105,-108,-112,
  13.                                                 -114,-117,-119,-121,-123,-124,-125,-126,-126,-126,-126,-126,-125,
  14.                                                 -124,-123,-121,-119,-117,-114,-112,-108,-105,-102,-98,-94,-89,-85,
  15.                                                 -80,-75,-70,-65,-59,-54,-48,-42,-36,-30,-24,-18,-12,-6
  16.                                            };

  17. /*放大128倍后的cos整数表(128)*/
  18. code char COS_TAB[128]={127,126,126,125,124,123,121,119,117,114,112,108,105,102,98,94,
  19.                         89,85,80,75,70,65,59,54,48,42,36,30,24,18,12,6,0,-6,-12,-18,-24,
  20.                                                 -30,-36,-42,-48,-54,-59,-65,-70,-75,-80,-85,-89,-94,-98,-102,
  21.                                                 -105,-108,-112,-114,-117,-119,-121,-123,-124,-125,-126,-126,-126,
  22.                                                 -126,-126,-125,-124,-123,-121,-119,-117,-114,-112,-108,-105,-102,
  23.                                                 -98,-94,-89,-85,-80,-75,-70,-65,-59,-54,-48,-42,-36,-30,-24,-18,
  24.                                                 -12,-6,0,6,12,18,24,30,36,42,48,54,59,65,70,75,80,85,89,94,98,102,
  25.                                                 105,108,112,114,117,119,121,123,124,125,126,126
  26.                                            };

  27. /*采样存储序列表*/
  28. code char LIST_TAB[128] = {0,64,32,96,16,80,48,112,8,72,40,104,24,88,56,120,4,68,36,100,20,84,52,116,
  29.                            12,76,44,108,28,92,60,124,2,66,34,98,18,82,50,114,10,74,42,106,26,90,58,
  30.                                                    122,6,70,38,102,22,86,54,118,14,78,46,110,30,94,62,126,1,65,33,97,17,81,49,
  31.                                                    113,9,73,41,105,25,89,57,121,5,69,37,101,21,85,53,117,13,77,45,109,29,93,61,
  32.                                                    125,3,67,35,99,19,83,51,115,11,75,43,107,27,91,59,123,7,71,39,103,23,87,55,
  33.                                                    119,15,79,47,111,31,95,63,127
  34.                                                   };

  35. /*分级量化表*/
  36. uint8 QTY_TAB[] = {0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
  37. uint8 ADC_Count=0;
  38. uint8 i,j,k,b,p,anum;        
  39. uint16 xdata Fft_Real[128];
  40. uint16 xdata Fft_Image[128];               // fft的虚部
  41. uint8 xdata LED_TAB[16];                                //记录红色柱状

  42. /********************************************************************
  43. * 名称 : FFT
  44. * 功能 : 碟型运算转换
  45. * 输入 : 无
  46. * 输出 : 读出的值
  47. ***********************************************************************/
  48. void FFT()//基2fft
  49. {                 
  50.         uint16 Temp_Real,Temp_Imag,temp;                // 中间临时变量
  51.         uint16 TEMP1 = 0,max=0;
  52.         for( i=1; i<=7; i++)                            /* for(1) */
  53.         {
  54.                 b=1;
  55.                 b <<=(i-1);                                 //碟式运算,用于计算隔多少行计算例如 第一极 1和2行计算
  56.                 for( j=0; j<=b-1; j++)                      /* for (2) */
  57.                 {
  58.                         p=1;
  59.                         p <<= (7-i);            
  60.                         p = p*j;
  61.                         for( k=j; k<128; k=k+2*b)               /* for (3)  */
  62.                         {
  63.                                 Temp_Real=Fft_Real[k];
  64.                                 Temp_Imag=Fft_Image[k];
  65.                                 temp=Fft_Real[k+b];
  66.                                 Fft_Real[k]=Fft_Real[k]+((Fft_Real[k+b]*COS_TAB[p])>>7)+((Fft_Image[k+b]*SIN_TAB[p])>>7);
  67.                                 Fft_Image[k]=Fft_Image[k]-((Fft_Real[k+b]*SIN_TAB[p])>>7)+((Fft_Image[k+b]*COS_TAB[p])>>7);
  68.                                 Fft_Real[k+b]=Temp_Real-((Fft_Real[k+b]*COS_TAB[p])>>7)-((Fft_Image[k+b]*SIN_TAB[p])>>7);
  69.                                 Fft_Image[k+b]=Temp_Imag+((temp*SIN_TAB[p])>>7)-((Fft_Image[k+b]*COS_TAB[p])>>7);          // 移位.防止溢出. 结果已经是本值的 1/64               
  70.                                 Fft_Real[k] >>= 1;            
  71.                                 Fft_Image[k] >>= 1;
  72.                                 Fft_Real[k+b] >>= 1;                 
  73.                                 Fft_Image[k+b] >>= 1;                                                      
  74.                         }     
  75.                 }
  76.         }
  77.         
  78.         for(j=0;j<16;j++)//16分频                                                                                         
  79.         {                                                                                                                                                         
  80.                 TEMP1=((((Fft_Real[j+1]* Fft_Real[j+1]))+((Fft_Image[j+1]*Fft_Image[j+1])))>>1);//求各频段幅值
  81.                 if(TEMP1<1)TEMP1=0;
  82.                 LED_TAB[j]=TEMP1;        
  83.                 if(LED_TAB[j]>max)max=LED_TAB[j];
  84.         }
  85.         if(max > 16)//分级量化
  86.         {
  87.                 max/=16;
  88.                 for(j=0;j<16;j++)LED_TAB[j]/=max;
  89.         }      
  90. }

  91. /********************************************************************
  92. * 名称 : GPIO_init
  93. * 功能 : GPIO初始化
  94. * 输入 : 无
  95. * 输出 : 读出的值
  96. ***********************************************************************/
  97. void GPIO_init()
  98. {
  99.         P0M0 = 1; P0M1 = 0; P0 = 0XFF;    /*列*/
  100.         P2M0 = 1; P2M1 = 0; P2 = 0XFF;
  101.         P3M0 = 1; P3M1 = 0; P3 = 0XFF;          /*行*/
  102. }
  103. /********************************************************************
  104. * 名称 : timer_Init
  105. * 功能 : 内部寄存器初始化
  106. * 输入 : 无
  107. * 输出 : 无
  108. ***********************************************************************/
  109. void timer_Init()
  110. {
  111.         TMOD = 0X12;
  112.         TH0 = 0xb0;                                                                  
  113.         TL0 = 0xb0;
  114.         ET0 = 1;                                               //定时器0 打开
  115.         TR0 = 0;                                                      //关闭定时器
  116.         TH1 = 0xfd;                                                                                                
  117.         TL1 = 0Xa8;
  118.         ET1  = 1;
  119.         TR1  = 1;        
  120.         EA   = 1;        
  121. }
  122. /********************************************************************
  123. * 名称 : adc_Init
  124. * 功能 : 内部寄存器初始化
  125. * 输入 : 无
  126. * 输出 : 无
  127. ***********************************************************************/
  128. void adc_Init()
  129. {         
  130.         ADC_CONTR = 0x80;             //ADC电源打开
  131.         _nop_();_nop_();_nop_();_nop_();
  132.         P1ASF = 0x01;                 //0000,0001, 将 P1.0 置成模拟口
  133.         AUXR1 &=0xFB;                 //1111,1011, 令 ADRJ=0
  134.         ADC_RES = 0x00;               //清零寄存器
  135.         ADC_RESL = 0x00;
  136.         EADC  = 1;                                          //AD中断打开
  137.         EA = 1;                                                  //总中断打开
  138. }

  139. /********************************************************************
  140. * 名称 : main
  141. * 功能 : 主程序
  142. * 输入 : 无
  143. * 输出 : 无
  144. ***********************************************************************/
  145. void main()
  146. {
  147.         uint8 i = 0;
  148.         GPIO_init();
  149.         timer_Init();
  150.         adc_Init();
  151.         while(1)
  152.         {
  153.                 ADC_Count = 0;
  154.                 EADC = 1;
  155.                 TR0  = 1;
  156.                 while(ADC_Count < 128);       //满足128点
  157.                 for(i=0; i<128; i++)                  //清除虚部
  158.                 {
  159.                         Fft_Image[i] = 0;
  160.                 }
  161.                 FFT();                        //FFT运算并转换为各频段幅值

  162.         }
  163. }
  164. /********************************************************************
  165. * 名称 : ADC_Finish
  166. * 功能 : ADC转换完成中断服务
  167. * 输入 : 无
  168. * 输出 : 无
  169. ***********************************************************************/
  170. void ADC_Finish() interrupt 5
  171. {
  172.         Fft_Real[LIST_TAB[ADC_Count]] = (int)(((ADC_RES)<<1)+(ADC_RESL>>1)*2)>>3;    /*按LIST_TAB表顺序,进行存储采样值*/
  173.         if(ADC_Count <= 127)
  174.         {
  175.                 ADC_Count++;           /*自动增量控制*/
  176.                 ADC_CONTR &= !ADC_FLAG;
  177.         }
  178.         else
  179.         {
  180.                 EADC = 0;
  181.                 TR0  = 0;        
  182.         }                        
  183. }
  184. /********************************************************************
  185. * 名称 : interrupt_timer1
  186. * 功能 : 显示屏幕刷新中断服务
  187. * 输入 : 无
  188. * 输出 : 无
  189. ***********************************************************************/
  190. void interrupt_timer1() interrupt 3
  191. {        
  192.         static uint8 rec = 0;
  193.         TH1 = 0xfd;                                                                                                
  194.         TL1 = 0Xa8;

  195.         switch(rec)                                                                     //往点阵屏填充一列的数据
  196.         {
  197.                 case 0: P0 = QTY_TAB[LED_TAB[0]]; P2 = 0;break;
  198.                 case 1: P0 = QTY_TAB[LED_TAB[1]]; P2 = 1;break;                 
  199.                 case 2: P0 = QTY_TAB[LED_TAB[2]]; P2 = 2;break;        
  200.                 case 3: P0 = QTY_TAB[LED_TAB[3]]; P2 = 3;break;        
  201.                 case 4: P0 = QTY_TAB[LED_TAB[4]]; P2 = 4;break;        
  202.                 case 5: P0 = QTY_TAB[LED_TAB[5]]; P2 = 5;break;               
  203.                 case 6: P0 = QTY_TAB[LED_TAB[6]]; P2 = 6;break;        
  204.                 case 7: P0 = QTY_TAB[LED_TAB[7]]; P2 = 7;break;
  205.                 case 8: P0 = QTY_TAB[LED_TAB[8]]; P2 = 8;break;
  206.                 case 9: P0 = QTY_TAB[LED_TAB[9]]; P2 = 9;break;                 
  207.                 case 10: P0 = QTY_TAB[LED_TAB[10]]; P2 = 10;break;        
  208.                 case 11: P0 = QTY_TAB[LED_TAB[11]]; P2 = 11;break;        
  209.                 case 12: P0 = QTY_TAB[LED_TAB[12]]; P2 = 12;break;        
  210.                 case 13: P0 = QTY_TAB[LED_TAB[13]]; P2 = 13;break;               
  211.                 case 14: P0 = QTY_TAB[LED_TAB[14]]; P2 = 14;break;        
  212.                 case 15: P0 = QTY_TAB[LED_TAB[15]]; P2 = 15;break;               
  213.                 default:break;
  214.         }
  215.         rec++;
  216.         if(rec > 15)
  217.         {
  218.                 rec = 0;
  219.         }
  220. }
  221. /********************************************************************
  222. * 名称 : Ad_Control
  223. * 功能 : 控制采样率
  224. * 输入 : 无
  225. * 输出 : 无
  226. ***********************************************************************/
  227. void Ad_Control() interrupt 1
  228. {
  229.         ADC_CONTR = 0xe8;                     //开始AD采集
  230.         _nop_();_nop_();_nop_();_nop_();         
  231. }


复制代码


0.png

音频显示(STC12系列老版).zip

733.11 KB, 下载次数: 154, 下载积分: 黑币 -5

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:328758 发表于 2018-5-26 16:16 | 显示全部楼层
下载学习一哈
回复

使用道具 举报

ID:467739 发表于 2019-5-15 10:48 | 显示全部楼层
谢谢分享,学习一下!!
回复

使用道具 举报

ID:64283 发表于 2022-4-19 00:31 | 显示全部楼层
下载学习了,谢谢楼主分享,代码可以通过测试,只是显示时,有断点和满格。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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