zoukankan      html  css  js  c++  java
  • LED音乐频谱之输出数据处理

    转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/38023539

    一.PWM调节

         1.初始化

    void  DACInit()
    {
    	CCON=0;	            //PAC初始化
    	CL=0;				// PAC16位计数器低8位
    	CH=0;				// PAC16位计数器高8位
    	CMOD=0x00;			 //选择  系统时钟/12为计数脉冲,则PWM的频率f=sysclk/256/12
    	CCAP0H=0X80;		 //占空比控制,0x80为百分之50	10000000所以在与PAC低八位比較时有CL>CCAPnL 一半的情况所以占空比为百分之50
            PCA_PWM0=0x00;         //使EPC0H   EPC0L为0。详细定义可看头文件
    	CCAPM0=0X42;		 //同意P13作为PWM输出
    	CR=1;				  //启动PCA计数器
    }


         2.按键调光

    		if(key1==0)				//独立按键	 ,PWM调节
    			{
    					delayms(35);
    			        if(key1==0)
    					  {		
    					  		a++;
    							CCAP0H=pwm[a];		//占空比调节
    			                CCAP0L=pwm[a];
    							while(!key1);
    							if(a==4)
    							{
    								a=0;
    							} 
    		
    					  }
    			 }


               各个模块的输出占空比是独立变化的。与使用的捕获寄存器[EPCnL,CCAPnL]有关。当寄存器CL的值小于[EPCnL,CCAPnL]时,输出为低;当寄存器CL的值等于或大于[EPCnL,CCAPnL]时,输出为高。当CL的值由FF变为00溢出时,[EPCnH,CCAPnH]的内容装载到[EPCnL,CCAPnL]中。这样就可实现无干扰地更新PWM。

    要使能PWM模式,模块CCAPMn寄存器的PWMn和ECOMn位必须置位。

    sfr  CCAPM0          //PCA模块0模式寄存器    Bit7    Bit6          Bit5        Bit4       Bit3          Bit2           Bit1    Bit0
                                    //位描写叙述                                -       ECOM0   CAPP0   CAPN0   MAT0    TOG0    PWM0    ECCF0
                                    //初始值=x000,0000      x       0       0       0       0       0       0       0


    二.位运算


    if(ACT_Key == 0)												// 动作检測,切换效果
    	{
    		num++;
    		if(num>4)
    		{
    			num = 1;
    		}
    		delay500ms();
    	}
    
    
     switch(num)
    	{								  // 选择显示模式
    		case	1:	{	
    						for(pt=0;pt<15;pt++)	 					   // 	style 1
    					    {       									    // 第一个点是直流分量所以不能用。style 1	第一种是直接显示的,适合节奏比較强的音乐
    							LEDBuf[pt]=0xffff;
    							tmp = dd[pt+2].real;					//2 6 8 10....32由于计算的是64个点	0到N是计算0到2PI。所以仅仅须要看计算0到二分之N所以是0到32有由于一共是16列所以偶数 
    							tmp = (tmp/8)+1;							//将变换后的功率转换为LED灯的幅值。看里面有多少个16假如为32的话就是0xff做移2位变成11111100然后取反就为00000011(还进行了加一处理此处为算加一的目的是让第一行时钟亮)一次进行16次变成新的LED数组
    							LEDBuf[pt]<<=tmp;	
    							LEDBuf[pt]=~(LEDBuf[pt]); 
    						}
    						
    						break;
    					}
    		case	2:	{
    						for(pt=0;pt<15;pt++)	 					   //	style 2
    					    {       
    							if(refreshflag[pt]<(dd[pt].real/8)+1)		// 另外一种是带下落效果的,跟第一种差不太多。           
    							{	
    															 //增加了 refreshflag[pt]来进行下降  
    								LEDBuf[pt]=0xffff;
    								tmp = dd[pt+2].real;
    								tmp = (tmp/8)+1;
    								refreshflag[pt] = tmp;		 
    								tmp = refreshflag[pt];
    								LEDBuf[pt]<<=tmp;	
    								LEDBuf[pt]=~(LEDBuf[pt]);
    							}
    							else
    							{
    							 	if(refreshflag[pt]>1)
    								{
    									
    									refreshflag[pt]--;                         
    								}
    								LEDBuf[pt]=0xffff;
    								tmp = refreshflag[pt];
    								LEDBuf[pt]<<=tmp;
    								
    								LEDBuf[pt]=~(LEDBuf[pt]);
    			                //	delayms(25);
    							}
    							
    						}
    						break;
    					}
    		case	3:	{														//	style 3
    						for(pt=0;pt<15;pt++)	 							//第三种就是在另外一种的效果上取最高的点
    					    {    
    							LEDBuf[pt]=0xffff; 
    							tmp = dd[pt+2].real;
    							tmp = (tmp/8)+1;
    							if(refreshflag[pt]<tmp)		           
    							{
    								refreshflag[pt] = tmp;			
    							}
    							else
    							{
    							 	if(refreshflag[pt]>1)
    								{
    									refreshflag[pt]--;                         
    								}
    								tmp = refreshflag[pt];			
    							}
    							LEDBuf[pt]&=(0x0001<<(tmp-1));				   //与另外一种差别就是取最高点比如0xff和一个00010000想与	00010000所以仅仅有一个灯亮
    						}
    						break;
    					}
    
    		case	4:	{										   			//		style	4 	  最后一种是第一种和第三种的结合体吧
    						for(pt=0;pt<15;pt++)	 
    					    {    
    							LEDBuf[pt]=0xffff; 
    							tmp = dd[pt+2].real;
    							tmp = (tmp/8)+1;
    							LEDBuf[pt]<<=tmp;	
    							LEDBuf[pt]=~(LEDBuf[pt]);
    							if(refreshflag[pt]<tmp)		           	   //首先叫他变成第一种。然后叫最上面那个灯进行下降效果。

    和音乐播放器的效果非常像。 { refreshflag[pt] = tmp; } else { if(refreshflag[pt]>1) { refreshflag[pt]--; } tmp = refreshflag[pt]; } LEDBuf[pt]|=(0x0001<<(tmp-1)); } } }



            每次按键改遍num的值,每一个值相应一种显示效果四种效果凝视相当easy理解,我就只是多介绍了。对比着实际效果看代码会更easy理解。效果视频和完整的代码下载在概述里面。

             1.幅值量化

                   代码之中有这样一句tmp = (tmp/8)+1有小伙伴可能没看懂,以下我解释下

                       a.tmp是什么?

                       答:tmp是你要亮灯的个数。

                       b.为什么是8而不是其余的数?

                       答:调试的结果,要综合点阵的行数。声音的大小考虑。假设你换成16,那么你要提高你的输入音量。

    再说的简单点,这个8乘以行数要小于频谱的最大值(或者基本不超过)。所以说即使是如今。我调高输入源的音量或者减少输入源的音量,频谱也会发生变化。8是一个我兼顾了输出声音的大小(由于这个设计中是能够输出声音的)。调试出来的一个值。

                       c.还是不明确为什么要这么写?

                       答:我们要LED量化频谱,你的行数相当于分辨率,终于人眼要看到是是几行,假如你是10行那么你最移的位数是定死的,超过10显示的是全亮(没考虑+1,第一行必须亮的情况。为了美观)。那么你必需要控制你这个频谱可以大致显示到屏幕中,所以正常的tmp必需要除一个数来压缩它的频谱。以下我画一张图:

    假设不处理直接左移则会出现全屏皆亮的情况,处理之后。则可避免。


    三.点阵输出图像

    	 for(i=0;i<16;i++)
    		{																// 显示
    			//LineInput(0x00);
    			P2 = ColScan_2[i];
    			LineInput(LEDBuf[i]);
    			LineInput(0x0000);	  
    	
    		}
    
    void LineInput(uint dat)                   // 单列数据显示
    {
        uchar n;
        _RCLK = 0;
        for(n=0;n<16;n++)
        {
            _SRCLK = 0;
            _SER  = (dat>>n)&0x01;         //将数据的值串入输入SER中,然后并行输出
            _SRCLK = 1;
        }
        _RCLK = 1;
    }
    


    四.TDA2822输出声音

         依照下图进行连接,输入的音频信号



    官方的图片照这连就OK了,喇叭选择的是8Ω,0.5W的。

    效果一般。但还过得去。



    參考: STC官方手冊

                   百度百科

  • 相关阅读:
    书籍下载点
    总结一下散乱的开发点滴(3) (高手勿入)
    [收藏]Dynamic Controls in ASP.NET
    [收藏] ORACLE中函数
    面试题收集,面试和被面试中煎熬~~
    一句SQL得出表中重复的数据(TMP)
    总结一下散乱的开发点滴(4) (高手勿入)
    一个同步的例子
    关于学习的反思(下)系网开发记(4)
    关于学习的反思(上)系网开发记(2)
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5239978.html
Copyright © 2011-2022 走看看