找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机音乐闪灯(类似于音乐频谱)制作问题

[复制链接]
跳转到指定楼层
楼主
ID:239055 发表于 2017-11-9 08:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我想用51单片机做一个类似于音乐频谱,
音乐频谱有些是8*8,12*12规格的,达到要求点亮每一级上面的LED,但点亮后的LED就只是点亮,而不是随音乐闪动,
我是想达到要求点亮每一级上面的LED,并且LED随音乐闪动,效果应该和舞厅效果差不多吧,
下面是论坛上面的源代码,哪位可以帮我改改不?谢谢

  1. #include<reg52.h>                    //stc15系列1T单片机
  2. #define ADC_CHANNEL 0x01                    //AD转换通道P1.0
  3. #define ADC_POWER 0x80                                                //ADC电源控制位
  4. #define ADC_SPEED 0x60                                                //90个时钟周期
  5. #define ADC_START 0x08                                                //ADC启动控制位
  6. #define ADC_FLAG 0x10                                                //ADC完成标志位
  7. #define SAMPLE_NUM 64                       //取64点FFT算法
  8. #define NUM_2_LOG 6                                                        //2的6次方
  9. #define FFT_OUT_MIN 1                       //FFT运算最小值
  10. #define LED_C1_8 P2                         //LED1~8列
  11. #define LED_C9_16 P3                        //LED9~16列
  12. #define LED_R1_8 P0                         //LED1~8行
  13. /***************************引脚定义*****************************/
  14. sbit LED_R1 = P0^0;                                                        //LED1~8行
  15. sbit LED_R2 = P0^1;
  16. sbit LED_R3 = P0^2;
  17. sbit LED_R4 = P0^3;
  18. sbit LED_R5 = P0^4;
  19. sbit LED_R6 = P0^5;
  20. sbit LED_R7 = P0^6;
  21. sbit LED_R8 = P0^7;
  22. sbit LED_R9 = P1^6;                        //LED第9行
  23. sbit LED_R10 = P1^7;                        //LED第10行                                 
  24. sbit SWITCH = P2^5;

  25. /*----------------------------变量表----------------------------*/
  26. unsigned char code BIT_RESORT[SAMPLE_NUM] = { 0, 32, 16, 48, 8, 40, 24, 56,4, 36, 20, 52, 12, 44, 28, 60,          //比特逆序重排
  27.                                                                             2, 34, 18, 50, 10, 42, 26, 58, 6, 38, 22, 54, 14, 46, 30, 62,
  28.                                                                             1, 33, 17, 49, 9, 41, 25, 57,5, 37, 21, 53, 13, 45, 29, 61,
  29.                                                                              3, 35, 19, 51, 11, 43, 27, 59,7, 39, 23, 55, 15, 47, 31, 63};

  30. char code SIN_TAB[SAMPLE_NUM] = { 0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 ,              //正弦表
  31.                                                                    127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 ,
  32.                                                                    0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,
  33.                                                                    -127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12  };

  34. char code COS_TAB[SAMPLE_NUM] = {127 ,126 ,125 ,122 ,117 ,112 ,106 ,98 ,90 ,81 ,71 ,60 ,49 ,37 ,25 ,12 ,            //余弦表
  35.                                                                   0 ,-12 ,-25 ,-37 ,-49 ,-60 ,-71 ,-81 ,-90 ,-98 ,-106 ,-112 ,-117 ,-122 ,-125 ,-126 ,
  36.                                                                   -127 ,-126 ,-125 ,-122 ,-117 ,-112 ,-106 ,-98 ,-90 ,-81 ,-71 ,-60 ,-49 ,-37 ,-25 ,-12 ,
  37.                                                                   0 ,12 ,25 ,37 ,49 ,60 ,71 ,81 ,90 ,98 ,106 ,112 ,117 ,122 ,125 ,126 };

  38. unsigned char LED_NUM[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};          //led显示数目
  39. unsigned char AMP, AMP_TAB[16];                      //频谱幅值,幅值表
  40. unsigned char DISP_NUM;                              //显示次数
  41. unsigned char KEEP, KEEP_NUM;                                                 //自动增益选择
  42. int xdata FFT_REAL[SAMPLE_NUM];                      //FFT运算结果实部
  43. int xdata FFT_IMAGE[SAMPLE_NUM];                     //FFT运算结果虚部
  44. bit SWITCH_ON;
  45. /**************************************************************
  46. *名                称:delay
  47. *功                能:微秒级延时
  48. **************************************************************/
  49. void Delay(unsigned int i)
  50. {
  51.         while(i--);
  52. }
  53. /**************************************************************
  54. *名                称:Delay_ms
  55. *功                能:毫秒级延时
  56. **************************************************************/
  57. void Delay_ms(unsigned int x)
  58. {
  59.         unsigned int i, j;
  60.         for(i = 0; i < x; i++)
  61.                 for(j = 0; j < 500; j++);
  62. }
  63. /**************************************************************
  64. *名                称:IOInit
  65. *功                能:IO端口初始化
  66. **************************************************************/
  67. void IOInit(void)
  68. {
  69.         P1M0 = 0x00;                        //高阻输入
  70.         P1M1 = 0x01;
  71.         P1ASF = 0x01;                        //设为AD转换
  72. }
  73. /**************************************************************
  74. *名                称:Timer0Init
  75. *功                能:定时器0初始化100us定时
  76. **************************************************************/
  77. void TimerInit(void)                //100微秒@33.000MHz
  78. {
  79.         AUXR = 0XC0;                        //定时器0-1T,定时器1-12T
  80.         TMOD = 0X00;                        //定时器0/1-方式0-16位自动重装
  81.         TL0 = 0X16;                                //定时器0-定时170us-显示幅值
  82.         TH0 = 0Xea;                                
  83.         TL1 = 0X1C;                                //定时器1-定时1ms-检测开关状态
  84.         TH1 = 0XF3;
  85.         TR0=1;
  86.         TR1 = 1;
  87. }

  88. /**********************************************************
  89. *名                称:Display
  90. *功                能:显示幅值
  91. **********************************************************/
  92. void Display(void)
  93. {
  94.         DISP_NUM++;
  95.         if(DISP_NUM == 17)
  96.                 DISP_NUM = 1;
  97.         LED_R1_8 = 0X00; LED_R9 = 0; LED_R10 = 0; LED_R11 = 0; LED_R12 = 0;                        //显示前先关闭
  98.         switch(DISP_NUM)                                                                                           //逐列显示
  99.         {
  100.                 case 1: AMP = AMP_TAB[0]; LED_C1_8 = 0X01; LED_C9_16 = 0x00; break;
  101.                 case 2: AMP = AMP_TAB[1]; LED_C1_8 = 0X02; LED_C9_16 = 0x00; break;
  102.                 case 3: AMP = AMP_TAB[2]; LED_C1_8 = 0X04; LED_C9_16 = 0x00; break;
  103.                 case 4: AMP = AMP_TAB[3]; LED_C1_8 = 0X08; LED_C9_16 = 0x00; break;
  104.                 case 5: AMP = AMP_TAB[4]; LED_C1_8 = 0X10; LED_C9_16 = 0x00; break;
  105.                 case 6: AMP = AMP_TAB[5]; LED_C1_8 = 0X20; LED_C9_16 = 0x00; break;
  106.                 case 7: AMP = AMP_TAB[6]; LED_C1_8 = 0X40; LED_C9_16 = 0x00; break;
  107.                 case 8: AMP = AMP_TAB[7]; LED_C1_8 = 0X80; LED_C9_16 = 0x00; break;
  108.                 case 9: AMP = AMP_TAB[8]; LED_C1_8 = 0X00; LED_C9_16 = 0x01; break;
  109.                 case 10: AMP = AMP_TAB[9]; LED_C1_8 = 0X00; LED_C9_16 = 0x02; break;
  110.                 case 11: AMP = AMP_TAB[10]; LED_C1_8 = 0X00; LED_C9_16 = 0x04; break;
  111.                 case 12: AMP = AMP_TAB[11]; LED_C1_8 = 0X00; LED_C9_16 = 0x08; break;
  112.                 case 13: AMP = AMP_TAB[12]; LED_C1_8 = 0X00; LED_C9_16 = 0x10; break;
  113.                 case 14: AMP = AMP_TAB[13]; LED_C1_8 = 0X00; LED_C9_16 = 0x20; break;
  114.                 case 15: AMP = AMP_TAB[14]; LED_C1_8 = 0X00; LED_C9_16 = 0x40; break;
  115.                 case 16: AMP = AMP_TAB[15]; LED_C1_8 = 0X00; LED_C9_16 = 0x80; break;
  116.         }
  117.         if(AMP <= 8)
  118.         {
  119.                 LED_R1_8 = LED_NUM[AMP];
  120.                 LED_R9 = 0;
  121.                 LED_R10 = 0;
  122.                 LED_R11 = 0;
  123.                 LED_R12 = 0;
  124.         }
  125.         if(AMP == 9)
  126.         {
  127.                 LED_R1_8 = 0XFF;
  128.                 LED_R9 = 1;
  129.                 LED_R10 = 0;
  130.                 LED_R11 = 0;
  131.                 LED_R12 = 0;
  132.         }
  133.         if(AMP == 10)
  134.         {
  135.                 LED_R1_8 = 0XFF;
  136.                 LED_R9 = 1;
  137.                 LED_R10 = 1;
  138.                 LED_R11 = 0;
  139.                 LED_R12 = 0;
  140.         }
  141.         if(AMP == 11)
  142.         {
  143.                 LED_R1_8 = 0XFF;
  144.                 LED_R9 = 1;
  145.                 LED_R10 = 1;
  146.                 LED_R11 = 1;
  147.                 LED_R12 = 0;
  148.         }
  149.         if(AMP == 12)
  150.         {
  151.                 LED_R1_8 = 0XFF;
  152.                 LED_R9 = 1;
  153.                 LED_R10 = 1;
  154.                 LED_R11 = 1;
  155.                 LED_R12 = 1;
  156.         }
  157. }

  158. /************************************************
  159. *名                称:ReadADC
  160. *功                能:读取AD转换结果
  161. ************************************************/
  162. unsigned char ReadADC(void)
  163. {
  164.         ADC_CONTR = ADC_POWER + ADC_START;           //启动转换
  165.         Delay(50);                                   
  166.         while(!(ADC_CONTR & ADC_FLAG));              //等待转换结束
  167.         ADC_CONTR = ADC_POWER;
  168.         return (ADC_RES << 2 + ADC_RESL);
  169. }
  170. /************************************************
  171. *名                称:sqrt
  172. *功                能:算平方根
  173. ************************************************/
  174. short sqrt( unsigned long M)                                            //不懂啊
  175. {
  176.     unsigned int N, i;
  177.     unsigned long tmp, ttp;
  178.     if( M == 0 )            
  179.         return 0;

  180.     N = 0;

  181.     tmp = ( M >> 30 );        
  182.     M <<= 2;
  183.     if( tmp > 1 )            
  184.     {
  185.         N ++;               
  186.         tmp -= N;
  187.     }

  188.     for( i=15; i>0; i-- )   
  189.     {
  190.         N <<= 1;           

  191.         tmp <<= 2;
  192.         tmp += (M >> 30);  

  193.         ttp = N;
  194.         ttp = (ttp<<1)+1;

  195.         M <<= 2;
  196.         if( tmp >= ttp )   
  197.         {
  198.             tmp -= ttp;
  199.             N ++;
  200.         }      
  201.     }

  202.     return N;
  203. }

  204. /************************************************
  205. *名                称:FFT
  206. *功                能:快速傅里叶变换求取频谱
  207. ************************************************/
  208. void FFT(void)                             //基2时分蝶式算法
  209. {
  210. //         unsigned char i, j, r, m1, m2, m3, m4, k1, k2;       //分别为:级号,蝶群号,运算蝶号,蝶群总数,蝶群长度,运算蝶数,蝶群址,蝶址
  211. //         unsigned char p;
  212. //         unsigned char MAX = 0;
  213. //         short u, v;
  214. //         unsigned long ulReal, ulImage;
  215.         register unsigned char i,bb,j,k,p,MAX;
  216.         register short TR,TI,temp;
  217.     unsigned long ulReal;                             
  218.     unsigned long ulImage;

  219.         for(i = 0; i < SAMPLE_NUM; i++)                                         //采样
  220.         {
  221.                 FFT_REAL[BIT_RESORT[i]] = ReadADC() << KEEP;
  222.                 FFT_IMAGE[i] = 0;
  223.         }
  224.         KEEP_NUM = FFT_REAL[2] >> 4;
  225.         if((7 < KEEP_NUM) && (KEEP_NUM <= 8))
  226.                 KEEP = 1;
  227.         else if((4 < KEEP_NUM) && (KEEP_NUM <= 6))
  228.                 KEEP = 2;
  229.         else if((2 < KEEP_NUM) && (KEEP_NUM <= 4))
  230.                 KEEP = 3;
  231.         else
  232.                 KEEP = 5;
  233.     for( i=1; i<=NUM_2_LOG; i++)                          
  234.     {
  235.         bb=1;
  236.         bb <<= (i-1);                                      
  237.         for( j=0; j<=bb-1; j++)                           
  238.         {
  239.             p=1;
  240.             p <<= (NUM_2_LOG-i);            
  241.             p = p*j;
  242.             for( k=j; k<SAMPLE_NUM; k=k+2*bb)               
  243.             {
  244.                 TR = FFT_REAL[k]; TI = FFT_IMAGE[k]; temp = FFT_REAL[k+bb];
  245.                 FFT_REAL[k] = FFT_REAL[k] + ((FFT_REAL[k+bb]*COS_TAB[p])>>7) + ((FFT_IMAGE[k+bb]*SIN_TAB[p])>>7);
  246.                 FFT_IMAGE[k] = FFT_IMAGE[k] - ((FFT_REAL[k+bb]*SIN_TAB[p])>>7) + ((FFT_IMAGE[k+bb]*COS_TAB[p])>>7);
  247.                 FFT_REAL[k+bb] = TR - ((FFT_REAL[k+bb]*COS_TAB[p])>>7) - ((FFT_IMAGE[k+bb]*SIN_TAB[p])>>7);
  248.                 FFT_IMAGE[k+bb] = TI + ((temp*SIN_TAB[p])>>7) - ((FFT_IMAGE[k+bb]*COS_TAB[p])>>7);

  249.                 FFT_REAL[k]  >>= 1;            
  250.                 FFT_IMAGE[k]  >>= 1;
  251.                 FFT_REAL[k+bb]  >>= 1;                 
  252.                 FFT_IMAGE[k+bb]  >>= 1;

  253.             }  
  254.         }
  255.     }
  256.         for(i = 0; i < 16; i++)
  257.         {
  258.                 ulReal = FFT_REAL[i + 1];
  259.                 ulReal *= ulReal;
  260.                 ulImage = FFT_IMAGE[i + 1];
  261.                 ulImage *= ulImage;
  262.                 AMP_TAB[i] = sqrt(ulImage + ulReal);
  263.                 if(AMP_TAB[i] < FFT_OUT_MIN)
  264.                         AMP_TAB[i] = 0;
  265.                 else
  266.                         AMP_TAB[i] -= FFT_OUT_MIN;
  267.                 if(AMP_TAB[i] > MAX)
  268.                         MAX = AMP_TAB[i];
  269.         }
  270.         if(MAX > 12)
  271.         {
  272.                 MAX /= 12;
  273.                 for(i = 0; i < 16; i++)
  274.                         AMP_TAB[i] /= MAX;
  275.         }
  276. }

  277. /************************************************
  278. *名                称:main
  279. *功                能:主函数
  280. ************************************************/
  281. void main()
  282. {
  283.         IOInit();                                                            //初始化
  284.         TimerInit();
  285.         DISP_NUM = 0;
  286.         KEEP = 0;
  287.         KEEP_NUM = 0;
  288.         EA = 1;                                                                        //开中断
  289.         ET1 = 1;
  290.         while(1)
  291.         {
  292.                 if(SWITCH_ON == 0)
  293.                 {
  294.                         ET0 = 0;
  295.                 }
  296.                 if(SWITCH_ON == 1)
  297.                 {
  298.                         ET0 = 1;
  299.                         FFT();
  300.                 }
  301.         }
  302. }

  303. /************************************************
  304. *名                称:Timer0Interrupt
  305. *功                能:定时器0中断服务程序-显示
  306. ************************************************/
  307. void Timer0Interrupt() interrupt 1
  308. {
  309.         Display();
  310.         Delay(300);
  311. }
  312. /************************************************
  313. *名                称:Timer1Interrupt
  314. *功                能:定时器1中断服务程序-检测开关状态
  315. ************************************************/
  316. void Timer1Interrupt() interrupt 3
  317. {
  318.         if(SWITCH == 1)
  319.                 SWITCH_ON = 1;
  320.         if(SWITCH == 0)
  321.                 SWITCH_ON = 0;

  322.    }
复制代码

评分

参与人数 1黑币 +5 收起 理由
51heiikejilunta + 5 很给力!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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