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官方手冊

                   百度百科

  • 相关阅读:
    php命令注入
    mysql事物
    安装php环境
    移除服务器缓存实例
    show user profile synchronization tools
    manual start user profile import
    JSON is undefined. Infopath Form People Picker in SharePoint 2013
    asp.net web 应用站点支持域账户登录
    Load sharepoint envirement by powershell
    sharepoint 2016 download
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5239978.html
Copyright © 2011-2022 走看看