找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2|回复: 0
收起左侧

请教LED3264双色频谱显示问题

[复制链接]
ID:86421 发表于 2025-5-9 16:39 | 显示全部楼层 |阅读模式
做了一个STC15单片机驱动的LED3264频谱,24MHZ,代码移植于本论坛中STC12C5A60S驱动程序。现在的问题是:只显示幅值,与频率无关了,就是16个光柱都一般高,随着音量大小一起跳动。烦请哪位老师帮忙看一下代码,问题出在哪?
  1. #include<math.h>
  2. #include"stc15.h"
  3. #include <intrins.h>

  4. #define uint unsigned int
  5. #define uchar unsigned char

  6. #define ADC_POWER   0x80     //ADC 电源控制位。
  7. #define ADC_FLAG    0x10     //ADC 完成标志
  8. #define ADC_START   0x08     //ADC 起始控制位
  9. #define ADC_SPEEDLL 0x00     //540 个时钟
  10. #define ADC_SPEEDL  0x20     //360 个时钟
  11. #define ADC_SPEEDH  0x40     //180 个时钟
  12. #define ADC_SPEEDHH 0x60     //90  个时钟

  13. sbit  R1=P3^6;           //上红数据
  14. sbit  R2=P3^7;     //下红数据
  15. sbit  G1=P2^4;           //上绿数据       
  16. sbit  G2=P2^5;     //下绿数据

  17. sbit  STR=P2^6;    //锁存
  18. sbit  CLK=P2^7;    //时钟
  19. sbit  OE=P3^5;     //

  20. sbit  IA=P2^0;     //行控制线A
  21. sbit  IB=P2^1;     //行控制线B
  22. sbit  IC=P2^2;     //行控制线C
  23. sbit  ID=P2^3;     //行控制线D
  24. /*--------------------------------------------
  25.     行输出控制
  26. --------------------------------------------*/
  27. void hang(unsigned char Value)
  28. {
  29.         switch(Value)
  30.         {
  31.                                         case  0: {IA=0;IB=0;IC=0;ID=0;}break;
  32.                       case  1: {IA=1;IB=0;IC=0;ID=0;}break;
  33.                       case  2: {IA=0;IB=1;IC=0;ID=0;}break;
  34.                       case  3: {IA=1;IB=1;IC=0;ID=0;}break;
  35.           case  4: {IA=0;IB=0;IC=1;ID=0;}break;
  36.                       case  5: {IA=1;IB=0;IC=1;ID=0;}break;
  37.                       case  6: {IA=0;IB=1;IC=1;ID=0;}break;
  38.                       case  7: {IA=1;IB=1;IC=1;ID=0;}break;
  39.           case  8: {IA=0;IB=0;IC=0;ID=1;}break;
  40.                       case  9: {IA=1;IB=0;IC=0;ID=1;}break;
  41.                       case 10: {IA=0;IB=1;IC=0;ID=1;}break;
  42.                       case 11: {IA=1;IB=1;IC=0;ID=1;}break;
  43.           case 12: {IA=0;IB=0;IC=1;ID=1;}break;
  44.                       case 13: {IA=1;IB=0;IC=1;ID=1;}break;
  45.                        case 14: {IA=0;IB=1;IC=1;ID=1;}break;
  46.                 case 15: {IA=1;IB=1;IC=1;ID=1;}break;
  47.         }
  48.                                        
  49. }

  50. uchar COUNT=15,COUNT1=0,LINE=15;
  51. uint TEMP1;       
  52. uchar xdata LED_TAB2[16];                                //记录 漂浮物 是否需要 停顿一下
  53. uchar xdata LED_TAB[16];                                //记录红色柱状
  54. uchar xdata LED_TAB1[16];                                //记录 漂浮点


  55. struct compx                                                                           //定义复数结构体
  56. {
  57.         float real;
  58.         float imag;
  59. };

  60. xdata struct compx s[ 64 ];                                                       //FFT数据缓存放在XDATA空间
  61. struct compx EE(struct compx,struct compx);   //复数乘法函数的声明
  62. void FFT(struct compx xin[],int N);                                    //FFT函数的声明

  63. /*---------------------------------------------
  64.    ADC初始化,P1^0口音频输入
  65. --------------------------------------------*/
  66. void InitADC()
  67. {
  68.           P1ASF =0x01;              //P10口做AD 使用
  69.           P1M0 = 0x01;                    //0000,0001用于A/D转换的P1.x口,先设为开漏
  70.           P1M1 = 0x01;              //0000,0001 P1.0先设为开漏。断开内部上拉电阻
  71.     ADC_RES = 0;               //清除结果寄存器
  72.           ADC_RESL = 0;                  
  73.     ADC_CONTR = ADC_POWER | ADC_SPEEDHH;         //40.96K采样率  0xC8
  74. }

  75. /*---------------------------------------------
  76.     读 ADC 数据
  77. --------------------------------------------*/
  78. unsigned int  GetADCResult(unsigned char  ch)
  79. {
  80.     ADC_CONTR = ADC_POWER | ADC_SPEEDHH | ch | ADC_START;
  81.     _nop_();                        
  82.     _nop_();
  83.     _nop_();
  84.     _nop_();
  85.     while (!(ADC_CONTR & ADC_FLAG));
  86.     ADC_CONTR &= ~ADC_FLAG;         
  87.     return (ADC_RES<<2+ADC_RESL);               
  88. }

  89. /*--------------------------------------------------------
  90.    复数乘法
  91. ---------------------------------------------------------*/
  92. struct compx EE(struct compx a1,struct compx b2)        
  93. {
  94.         struct compx b3;
  95.         b3.real=a1.real*b2.real-a1.imag*b2.imag;
  96.         b3.imag=a1.real*b2.imag+a1.imag*b2.real;
  97.         return(b3);
  98. }
  99. /*--------------------------------------------------------
  100.   FFT函数
  101. ---------------------------------------------------------*/
  102. void FFT(struct compx xin[],int N)                                  
  103. {
  104.         int f,m,nv2,nm1,i,k,j=1,l;
  105.         struct compx v,w,t;
  106.         nv2=N/2;
  107.         f=N;
  108.         for(m=1;(f=f/2)!=1;m++){;}
  109.         nm1=N-1;
  110.         for(i=0;i<nm1;i++)                                           //倒序操作
  111.         {
  112.                 if(i<j)
  113.                 {
  114.                         t=xin[j];
  115.                         xin[j]=xin[i];
  116.                         xin[i]=t;
  117.                 }
  118.                 k=nv2;                                                       //k为倒序中相应位置的权值
  119.                 while(k<j)
  120.                 {
  121.                         j=j-k;
  122.                         k=k/2;
  123.                 }
  124.                 j=j+k;
  125.         }
  126.         {
  127.                 int le,lei,ip;
  128.                   float pi;
  129.                   for(l=1;l<=m;l++)
  130.                    {
  131.                 le=pow(2,l);                                                 //乘方
  132.                     lei=le/2;
  133.                     pi=3.14159265;
  134.                     v.real=1.0;
  135.                 v.imag=0.0;  
  136.                    w.real=cos(pi/lei);                                           //旋转因子
  137.                     w.imag=-sin(pi/lei);
  138.                    
  139.                 for(j=1;j<=lei;j++)                                           //控制蝶形运算的级数
  140.                      {
  141.                         for(i=j-1;i<N;i=i+le)                                         //控制每级蝶形运算的次数
  142.                               {
  143.                                     ip=i+lei;
  144.                                        t=EE(xin[ ip ],v);
  145.                                        xin[ ip ].real=xin[ i ].real-t.real;   //蝶形计算
  146.                                        xin[ ip ].imag=xin[ i ].imag-t.imag;
  147.                                        xin[ i ].real=xin[ i ].real+t.real;
  148.                                        xin[ i ].imag=xin[ i ].imag+t.imag;
  149.                               }
  150.                               v=EE(v,w);   
  151.                       }     
  152.                    }
  153.           }
  154. }

  155. /*--------------------------------------------------------
  156.   显示模式
  157. ---------------------------------------------------------*/
  158. void showbar()
  159. {                               
  160.   unsigned char i,j;
  161.        
  162.         for(j=0;j<16;j++)          //读取FFT转换数据
  163.         {
  164.                 TEMP1=sqrt(pow((s[i  ].real+s[i+1].real),2)+pow((s[i  ].imag+s[i+1].imag),2))/2;

  165.                 if(TEMP1>1)TEMP1--;
  166.                         else TEMP1=0;
  167.                         if(TEMP1>31)TEMP1=31;
  168.                         if(TEMP1>(LED_TAB[j]))LED_TAB[j]=TEMP1;       
  169.                         if(TEMP1>(LED_TAB1[j]))
  170.                         {
  171.                                 LED_TAB1[j]=TEMP1;
  172.                                 LED_TAB2[j]=14;                                                //提顿速度=12
  173.                         }
  174.         }
  175. }

  176. /*------------------------------------------------
  177.                     定时器0初始化子程序
  178. ------------------------------------------------*/
  179. void Init_Timer0(void)
  180. {
  181. TMOD |= 0x01;          //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响                     
  182. ET0=1;           //定时器中断打开
  183. TR0=1;           //定时器开关打开
  184. EA=1;            //总中断打开
  185. }
  186. /*------------------------------------------------
  187.                  定时器0中断子程序
  188. ------------------------------------------------*/
  189. void LED_Display() interrupt 1
  190. {
  191.         uchar G;
  192.   TH0=(65536-2000)/256;                  //重新赋值
  193.   TL0=(65536-2000)%256;
  194.        
  195.           for        (G=0;G<16;G++)                                                  //往点阵屏填充 一行的 数据
  196.                 {       
  197.                         if(LED_TAB[G]<=LINE+16)R1=0;
  198.                         else R1=1;
  199.                   if(LED_TAB[G]<=LINE)R2=0;
  200.                         else R2=1;

  201.                         if(LED_TAB1[G]==LINE){G1=0;G2=1;}
  202.                         else if(LED_TAB1[G]==(LINE+16)){G1=1;G2=0;}
  203.                         else G2=G1=0;
  204.                         CLK=1;CLK=0;
  205.                         CLK=1;CLK=0;
  206.                         CLK=1;CLK=0;
  207.                         G1=0;G2=0;R1=0;R2=0;
  208.                         CLK=1;CLK=0;
  209.                 }
  210.                 STR=1;STR=0;

  211.     if(LED_TAB[COUNT]>0)LED_TAB[COUNT]--;                   //柱状递减,
  212.           if(COUNT>0)COUNT--;
  213.     else COUNT=15;

  214.                 if(LED_TAB2[COUNT1]==0)
  215.                          {
  216.                                         if(LED_TAB1[COUNT1]>LED_TAB[COUNT1])LED_TAB1[COUNT1]--;
  217.                          }
  218.                 else LED_TAB2[COUNT1]--;
  219.                          COUNT1++;
  220.                 if(COUNT1>=16)COUNT1=0;
  221.    
  222.                 OE=1;
  223.                 hang(15-LINE);                        //行选
  224.                 OE=0;
  225.     if(LINE>0)LINE--;
  226.                 else LINE=15;               
  227. }

  228. /*-------------------------------------------------------------------
  229. 主函数
  230. -------------------------------------------------------------------*/
  231. void main()                                                                    
  232. {
  233.        
  234.         int N=64,i;                                                             //变量初始化,64点FFT运算
  235.         float offset;
  236.        
  237.         P0M1=0x00;
  238.         P0M0=0x00;
  239.         P1M1=0x00;
  240.         P1M0=0x00;
  241.         P2M1=0x00;
  242.         P2M0=0x00;
  243.         P3M1=0x00;
  244.         P3M0=0x00;
  245.         P5M1=0x00;
  246.         P5M0=0x00;

  247.   Init_Timer0();
  248.         InitADC();          //ADC初始化
  249.        
  250.         offset=GetADCResult(0);
  251.        
  252.         while(1)
  253.         {       
  254.                         for(i=0;i<N;i++)                                      //采集音频信号
  255.                   {
  256.                                 ADC_CONTR=0xC8;                                         //40.96K采样率

  257.                                 while(!(ADC_CONTR&0x10));
  258.                                    s[i].real=((float)ADC_RES*4+(float)(ADC_RESL%0x04)-offset)/4;  //((((int)ADC_DATA-128)/2))*4;
  259.                                    s[i].imag=0;
  260.                   }
  261.                        
  262.                   FFT(s,N);        //调用FFT函数进行变换
  263.       showbar();
  264.         }
  265. }
复制代码



回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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