单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 100|回复: 1
收起左侧

stc12C5a单片机FFT 音乐频谱 不间断ADC程序

[复制链接]
zpmzqr 发表于 2019-9-11 09:51 | 显示全部楼层 |阅读模式
本帖最后由 zpmzqr 于 2019-9-12 19:25 编辑
  1. #define uchar unsigned char
  2. #define uint unsigned int
  3. #define OUT_Port          P0                     //输出
  4. #define ADC_CHO          0x00                   //AD通道为(111) P1.0
  5. #define ADC_POWER          0x80                   //AD电源
  6. #define ADC_START   0x08                   //AD启动
  7. #define ADC_FLAG    0x10                   //AD标志
  8. //#define ADC_SPEED  0x00                //420 clocks
  9. //#define ADC_SPEED  0x20               //280 clocks
  10. //#define ADC_SPEED  0x40               //140 clocks
  11. #define ADC_SPEED 0x60                 //70 clocks        31kHZ

  12. uchar code EF_Tab[]={0x01,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff,0xff};//显示效果
  13. uchar data ADCTmp_Tab[FFT_PCS]; // ADC输入缓存
  14. uchar idata Gap_Tab[FFT_X];            //下落间隔计数
  15. uchar idata Out_Tab[FFT_X];                //实际输出缓存
  16. uchar data  ADC_Count=0;                  //采集计数

  17. sbit Rout=OUT_Port^4;                //高中低音输出端口
  18. sbit Gout=OUT_Port^5;
  19. sbit Bout=OUT_Port^6;
  20. sbit Yout=OUT_Port^7;

  21. bit ADCOK_BT;//采集完成标志

  22. void Display_OUT()//显示数据输出
  23. {
  24.         if(Out_Tab[0]>7)Rout=1; else Rout=0;  //高中低音指示灯输出
  25.         if(Out_Tab[1]>7)Gout=1; else Gout=0;
  26.         if(Out_Tab[2]>6)Bout=1; else Bout=0;
  27.         if(Out_Tab[3]>6)Yout=1; else Yout=0;
  28.         
  29.         TM1640_GRID[15]=EF_Tab[Out_Tab[0]];                                          //R0  1640点阵输出
  30.         TM1640_GRID[14]=0;          //G0
  31.         TM1640_GRID[13]=0;
  32.         TM1640_GRID[12]=EF_Tab[Out_Tab[1]];
  33.         TM1640_GRID[11]=EF_Tab[Out_Tab[2]];
  34.         TM1640_GRID[10]=EF_Tab[Out_Tab[2]];
  35.         TM1640_GRID[9]=EF_Tab[Out_Tab[3]];
  36.         TM1640_GRID[8]=0;
  37.         TM1640_GRID[7]=0;
  38.         TM1640_GRID[6]=EF_Tab[Out_Tab[4]];
  39.         TM1640_GRID[5]=EF_Tab[Out_Tab[5]];
  40.         TM1640_GRID[4]=EF_Tab[Out_Tab[5]];
  41.         TM1640_GRID[3]=EF_Tab[Out_Tab[6]];
  42.         TM1640_GRID[2]=0;
  43.         TM1640_GRID[1]=0;
  44.         TM1640_GRID[0]=EF_Tab[Out_Tab[7]];
  45.         
  46.         TM1640B_GRID[15]=EF_Tab[Out_Tab[8]];
  47.         TM1640B_GRID[14]=EF_Tab[Out_Tab[8]];
  48.         TM1640B_GRID[13]=0;
  49.         TM1640B_GRID[12]=EF_Tab[Out_Tab[9]];
  50.         TM1640B_GRID[11]=0;
  51.         TM1640B_GRID[10]=EF_Tab[Out_Tab[10]];
  52.         TM1640B_GRID[9]=0;
  53.         TM1640B_GRID[8]=EF_Tab[Out_Tab[11]];
  54.         TM1640B_GRID[7]=EF_Tab[Out_Tab[12]];
  55.         TM1640B_GRID[6]=0;
  56.         TM1640B_GRID[5]=EF_Tab[Out_Tab[13]];
  57.         TM1640B_GRID[4]=0;
  58.         TM1640B_GRID[3]=EF_Tab[Out_Tab[14]];
  59.         TM1640B_GRID[2]=0;
  60.         TM1640B_GRID[1]=0;
  61.         TM1640B_GRID[0]=EF_Tab[Out_Tab[15]];        
  62.         TM1640_WriteDisp(0x8b);        //1640显示
  63. }

  64. /*-----T1中断-----------------------------刷新显示----------------------*/
  65. void RefreshDisplay() interrupt 3
  66. {
  67.          uchar i;
  68.         TL1 = 0x33;                //设置定时初值4MS
  69.         TH1 = 0xE3;                //设置定时初值
  70.         if(Fft_DispBT)        //显示标志
  71.         {
  72.                 for(i=0;i<FFT_X;i++)//输出效果上升直接显示,下落间断
  73.                 {
  74.                         if(FftOut_Tab[i]>Out_Tab[i])
  75.                         {Out_Tab[i]=FftOut_Tab[i];Gap_Tab[i]=0;}
  76.                         else if(FftOut_Tab[i]<Out_Tab[i])
  77.                         {
  78.                                 Gap_Tab[i]++;
  79.                                 if(Gap_Tab[i]>4)
  80.                                 {
  81.                                         Out_Tab[i]--;Gap_Tab[i]=0;
  82.                                 }
  83.                         }
  84.                 }
  85.                 Display_OUT(); //显示输出
  86.         }
  87. }                                                                                                                        
  88. /*-----ADC中断----------44100/128=345HZ频率点------32000/64=500HZ频率点----------------*/
  89. void ADC_Finish() interrupt 5        //ADC中断
  90. {   
  91.         ADC_CONTR &= !ADC_FLAG;         //清除标志
  92.         ADCTmp_Tab[LIST_TAB[ADC_Count]]=ADC_RESL<<2;//按LIST_TAB表里的顺序,进行存储采样值        低8位
  93.         ADC_Count++;if(ADC_Count>=FFT_PCS){ADCOK_BT=1;ADC_Count=0;}//置位 EADC=0;TR0=0;
  94. }
  95. /*---T0中断-启动ADC控制采样率,------------1000000US/32000HZ=31.25US-------------------------*/
  96. void Ad_Control() interrupt 1
  97. {
  98.         ADC_CONTR = ADC_POWER | ADC_SPEED | ADC_START | ADC_CHO;//1110 1000   1打开 ADC_POWER转换电源;11速度为70周期一次;0中断标志清零;1启动adc(ADC_START);000AD通道打开(这里为P1.0);
  99. }
  100. /*----------------------系统初始化----------22.1184-----------12T----------------------------*/
  101. void STC_INIT()
  102. {
  103. /*----------------------AD------------------------------------------------------------*/
  104.         P1ASF = 0x01;   //0000,0000, 将 P1.0 置成模拟口
  105.         AUXR1|= 0x04;   //1111,1011, ADRJ=1 高2位放ADC_RES 低8位放ADC_RESL
  106.         EADC=1;                //AD中断打开
  107.         ADC_CONTR = ADC_POWER | ADC_SPEED | ADC_CHO; //打开ADC电源
  108. /*----------------------Uint---------------------------------------------------------*/
  109.         TMOD= 0X12;                //T1 16位, T0 8位自动重载
  110.         TL0 = 0xC6;                //设置定时初值                频率≈44KHZ,1000000/44100=22.67US;         值D6
  111.         TH0 = 0xC6;                //设置定时重载值         频率≈32KHZ,1000000/32000=31.25US;  值C6
  112.         
  113.         TL1 = 0x33;                //设置定时初值设4MS        采集64次时间 31.25*64=2000US+FFT时间≈3US
  114.         TH1 = 0xE3;                //设置定时初值
  115.         ET0=1;          //定时器0中断打开
  116.         TR0=0;          //关闭定时器0
  117.         ET1=1;                        //定时器1中断打开
  118.         TR1=1;                        //启动定时器0
  119.         PT1=0;                        //T1中断优先级         0
  120.         PT0=1;                        //T0中断优先级        1
  121.         IPH=0X20;                //ADC中断优先级        2
  122.         PADC=1;               //ADC中断优先级        3
  123.         EA=1;                 //总中断打开
  124.         OUT_Port=0X00;                //输出
  125. }
  126. void main()//主程序
  127. {
  128.         unsigned char i;
  129.         STC_INIT();
  130.         TR0=1;EADC=1; //开启定时器中断0,开启ADC
  131.         while(1)
  132.         {
  133.         //        ADC_Count=0;
  134.         //        TR0=1;EADC=1; //开启定时器中断0,开启ADC
  135.         //        while(!ADCOK_BT);
  136.                 if(ADCOK_BT)
  137.                 {
  138.                         for(i=0;i<FFT_PCS;i++)
  139.                         {FftReal_Tab[i]=ADCTmp_Tab[i];FftImage_Tab[i]=0;}//
  140.                         FFT_OUT();//FFT运算并转换为各频段幅值
  141.                         ADCOK_BT=0;
  142.                 }     
  143.         }
  144. }
复制代码
51hei图片_20190912192218.jpg
51hei图片_20190912192222.jpg
51hei图片_20190912192246.jpg
51hei图片_20190912192212.jpg
回复

使用道具 举报

admin 发表于 2019-9-11 16:40 | 显示全部楼层
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

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

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51Hei单片机16群 联系QQ:125739409;技术交流QQ群7344883

Powered by 单片机教程网

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