转载请注明出处: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的值,每个值对应一种显示效果四种效果注释相当容易理解,我就不过多介绍了。对照着实际效果看代码会更容易理解,效果视频和完整的代码下载在概述里面。
三.点阵输出图像
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官方手册
百度百科
原文地址:http://blog.csdn.net/ruoyunliufeng/article/details/38023539