加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

LED音乐频谱之输出数据处理

发布时间:2020-12-14 03:28:23 所属栏目:大数据 来源:网络整理
导读:转载请注明出处: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的频率

转载请注明出处: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位变成22222100然后取反就为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的值,每个值对应一种显示效果四种效果注释相当容易理解,我就不过多介绍了。对照着实际效果看代码会更容易理解,效果视频和完整的代码下载在概述里面。

???????? 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官方手册

?????????????? 百度百科

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读