一款遥控LED控制器,所有功能均由遥控器控制,它主要有如下功能:
1、遥控调光
2、旋钮调光
3、开关机功能
4、渐变
5、跳变
6、循环变化(渐变、跳变等)
7、变化速度可调整,并断电能记忆
一、原理图:
二、参考图片:
三、参考程序:
#include <reg51.h>
#include <intrins.h>
/*********定义EEPROM寄存器地址*********/
sfr DATA=0xC2;//数据寄存器
sfr ADDRH=0xC3;//地址寄存器高八位
sfr ADDRL=0xC4;//地址寄存器低八位
sfr CMD=0xC5;//命令模式寄存器
sfr TRIG=0xC6;//命令触发寄存器
sfr CONTR=0xC7;//控制寄存器
/*********定义AD转换寄存器地址*********/
sfr ADC_RES=0xbd;//AD转换结果寄存器
sfr ADC_C=0xbc;//AD转换控制寄存器
sfr P1ASF=0x9d;
#define c(x) (x*120000/120000)
#define uchar unsigned char
#define uint unsigned int
#define dengji 2//手动调光等级定义
sbit IR=P3^3;
sbit LED=P3^0;
uint temp;//红外线解码变量
uchar i;
uchar j;
char dat=0;//PWM变量
uchar num;//PWM定时器变量
uint flashnum;//渐变跳变定时器变量
uchar IRBUF[4]; //用于保存解码结果
uchar shudu=1;
bit power=1;//电位器调光与遥控调光切换标志位
bit flag;//遥控开关机切换标志位
bit flash;//跳变切换标志位
bit jian;//渐变切换标志位
bit zeng;//综合变化变量
/***************************************************************/
/****************************EEPROM子函数***********************/
/***************************************************************/
/****************************************/
/**********EEPROM读数据子函数************/
/****************************************/
uchar read(uint add)
{
CONTR=0x82;
CMD=0x01;
ADDRH=(add>>=8);
ADDRL=add&(0x00ff);
TRIG=0x5a;
TRIG=0xa5;
_nop_();
CONTR=0x00;
TRIG=0X00;
return DATA;
}
/****************************************/
/**********EEPROM写数据子函数************/
/****************************************/
void write(uint add,uchar vale)
{
CONTR=0x82;
CMD=0X02;
ADDRH=(add>>=8);
ADDRL=add&(0x00ff);
DATA=vale;
TRIG=0x5a;
TRIG=0xa5;
_nop_();
CONTR=0x00;
TRIG=0X00;
}
/****************************************/
/**********EEPROM擦除数据子函数**********/
/****************************************/
void sector(uint add)
{
CONTR=0x82;
CMD=0x03;
ADDRH=(add>>=8);
ADDRL=add&(0x00ff);
TRIG=0x5a;
TRIG=0xa5;
_nop_();
CONTR=0x00;
TRIG=0X00;
}
/****************************************/
/***************AD转换部分***************/
/****************************************/
uint adzhang1()
{
uint zona;
zona=0;
ADC_C=0;//控制寄存器清0
P1ASF=0;//IO口控制寄存器清0
ADC_C|=0x80;//打开控制寄存器电源
P1ASF|=0x80;//设置P1.7为AD输入口
ADC_C|=0xe7;//打开控制寄存器电源,并选择P1.7为AD输入端
//以上是初始化程序
ADC_RES=0;//转换结果寄存器清0
ADC_C|=0x08;//开始转换
//delay1(2);
while((ADC_C&0x10)==0);//判断结束标志位是否为不为1?若不为1则等待
ADC_C&=0xe7;//清除等待标志位
zona=ADC_RES*0.392156;//将255个等级变为100个等级 等级=100/255=0.392156
if(zona<1)
zona=0;
return zona;
}
/****************************************/
/***********遥控解码低电平检测***********/
/****************************************/
uint Low()
{
TL0=0;
TH0=0;
TR0=1;
while(!IR&&(TH0&0x80)==0);
TR0=0;
return TH0*256+TL0;
}
/****************************************/
/***********遥控解码高电平检测***********/
/****************************************/
uint High()
{
TL0=0;
TH0=0;
TR0=1;
while(IR&&(TH0&0x80)==0);
TR0=0;
return TH0*256+TL0;
}
/****************************************/
/************AD转换处理子函数************/
/****************************************/
void ADzhuan()
{
if(!power)//如果此标志位为1,则执行AD转换
dat = adzhang1();
}
/****************************************/
/**************LED闪烁子函数*************/
/****************************************/
void LEDflash()
{
if(flash==1)//如果此标志位为1,则执行闪烁程序
{
if(flashnum>=(shudu*800))//定时器时间到了吗?
{
bit kl;//定义一个标志位
flashnum=0;//到了就清0
kl=~kl;//将它取反,以便形成亮灭变化
if(kl==0)//如果为1,就让LED亮
dat=100;//等级为100,就最亮
else//否则灭
dat=0;//等级为0就为熄灭
}
}
}
/****************************************/
/**************LED渐变子函数*************/
/****************************************/
void LEDjian()
{
if(jian==1)//如果此标志位为1,则执行渐变程序
{
bit a;//定义一个标志位
if(flashnum>=(shudu*100))//定时器时间到了吗?
{
flashnum=0;//到了就清0
if(a==0)//如果为0就执行渐亮子函数
{
dat++;//时间到了就自动加1
if(dat>100)//如果加到大于100
{
a=1;//将标志位变为1
dat=100;//将变量变为最亮状态
}
}
else//如果a为1就执行渐暗子函数
{
dat--;//时间到了就自动减1
if(dat<(0-1))//如果减到小于0了,就将它变为0
{
a=0;//标志位变为0,以便执行渐亮子函数
dat=0;
}
}
}
}
}
/**********************************************/
/**************LED综合子函数*************/
/**********************************************/
void zonghe()
{
uchar ci,ii;
bit a,fla;//定义一个标志位
bit kl;//定义一个标志位
if(zeng==1)
{
if(flashnum>=(shudu*100))//定时器时间到了吗?
{
flashnum=0;
ii++;
if(ii>7)
{
ii=0;
if(fla==1)
{
kl=~kl;//将它取反,以便形成亮灭变化
if(kl==0)//如果为1,就让LED亮
dat=100;//等级为100,就最亮
else//否则灭
dat=0;//等级为0就为熄灭
ci++;
if(ci>=30)
{
ci=0;
fla=0;
}
}
}
if(fla==0)
{
if(a==0)//如果为0就执行渐亮子函数
{
dat++;//时间到了就自动加1
if(dat>100)//如果加到大于100
{
a=1;//将标志位变为1
dat=100;//将变量变为最亮状态
}
}
else//如果a为1就执行渐暗子函数
{
dat--;//时间到了就自动减1
if(dat<(0-1))//如果减到小于0了,就将它变为0
{
a=0;//标志位变为0,以便执行渐亮子函数
dat=0;
ci++;
if(ci>=4)
{
fla=1;
ci=0;
}
}
}
}
}
}
}
/****************************************/
/************遥控解码核心部分************/
/****************************************/
void decode()
{
while(1)
{
restart:
while(IR)/******空闲时处理其它的事情,即当遥控没有按下时,处理其它事情******/
{
ADzhuan();
LEDflash();
LEDjian();
zonghe();
}/******空闲时处理其它的事情,即当遥控没有按下时,处理其它事情******/
temp=Low();
if(temp<c(8500) || temp>c(9500)) continue;//引导脉冲低电平9000
temp=High();
if(temp<c(4000) || temp>c(5000)) continue;//引导脉冲高电平4500
for(i=0;i<4;i++) //4个字节
{
for(j=0;j<8;j++) //每个字节8位
{
temp=Low();
if(temp<c(200) || temp>c(800)) goto restart;
temp=High();
if(temp<c(200) || temp>c(2000)) goto restart;
IRBUF[i]>>=1;
if(temp>c(1120))
{
IRBUF[i]|=0x80;
}
}
}
return;
}
}
/****************************************/
/*********遥控解码键值处理子函数********/
/****************************************/
void numzhi()
{
switch(IRBUF[2])//判断数组2键值注:因为只有第2组才是按键码,所以判断数组2
{
/****************如果此键按下了,则遥控开关机****************11111**/
case 0x58:
flag=~flag;
if(flag==0)
dat=100;//dat为100时最亮
else
dat=0;//为0时熄灭
jian=0;//将渐变变量置0,以防止渐变子程序动作
flash=0;//将闪烁变量置0,以防止跳变子程序动作
zeng=0;//将综合程序变量置0,以防止综合子程序动作
break;
/***如果此键按下了,每按一次亮度会增加1个等级 共为100等级**22222**/
case 0x1b:if(flag==0)
{
dat+=dengji;
if(dat>=100)
dat=100;
jian=0;//将渐变变量置0,以防止渐变子程序动作
flash=0;//将闪烁变量置0,以防止跳变子程序动作
zeng=0;//将综合程序变量置0,以防止综合子程序动作
}
break;
/***如果此键按下了,每按一次亮度会减小1个等级 共为100等级**33333**/
case 0x1f:if(flag==0)
{
dat-=dengji;
if(dat<=(0-1))
dat=0;
jian=0;//将渐变变量置0,以防止渐变子程序动作
flash=0;//将闪烁变量置0,以防止跳变子程序动作
zeng=0;//将综合程序变量置0,以防止综合子程序动作
}
break;
/***每按一次跳变和渐变速度会减小1个等级 共为60等级,并写入改变的数值,以便开机记忆**44444**/
case 0x0f:if(flag==0)
{
shudu-=1;
if(shudu<=1)
shudu=1;
sector(0x0200);//擦除EEPROM,擦除地址为0X200
write(0x0200,shudu);//写入EEPROM,写入地址为0X200
}
break;
/***每按一次跳变和渐变速度会增加1个等级 共为60等级,并写入改变的数值,以便开机记忆**55555**/
case 0x1a:if(flag==0)
{
shudu+=1;
if(shudu>=30)
shudu=30;
sector(0x0200);//擦除EEPROM,擦除地址为0X200
write(0x0200,shudu);//写入EEPROM,写入地址为0X200
}
break;
/*********如果此键按下了,则执行手动调光与遥控切换,两者不能同时工作***********66666**/
case 0x1e:if(flag==0)
{
flash=1;//进入遥控后,让它先进入关机状态
dat=0;
power=~power;//手动调光与遥控切换标志位
jian=0;//将渐变变量置0,以防止渐变子程序动作
flash=0;//将闪烁变量置0,以防止跳变子程序动作
zeng=0;//将综合程序变量置0,以防止综合子程序动作
}
break;
/***********************如果此键按下了,则执行渐变子函数*******************77777**/
case 0x0e:if(flag==0)
{
jian=~jian;
dat=0;
flash=0;//将闪烁变量置0,以防止跳变子程序动作
zeng=0;//将综合程序变量置0,以防止综合子程序动作
}
break;
/***********************如果此键按下了,则执行跳变子函数*******************88888**/
case 0x19:if(flag==0)
{
flash=~flash;
dat=0;
jian=0;//将渐变变量置0,以防止渐变子程序动作
zeng=0;//将综合程序变量置0,以防止综合子程序动作
}
break;
case 0x1d:if(flag==0)
{
zeng=~zeng;
dat=0;
}
break;
}
}
/****************************************/
/***************主程序部分***************/
/****************************************/
main()
{
TMOD=0x11;//设置定时器0定时器1工作方式为1的状态下工作
EA=1;
TR0=1;//设置定时器0
ET0=1;
TL0=0;
TH0=0;
TR1=1;//设置定时器1
ET1=1;
TH1=(65536-20)/256; //定时器初值
TL1=(65536-20)%256;
shudu=read(0x0200);//开机读取EEPROM里面的速度变量shudu,从而形成断电记忆功能
while(1)
{
decode();//调用解码子函数
numzhi();//调用遥控键值子函数
}
}
/****************************************/
/***************定时器1部分**************/
/****************************************/
void zhong3() interrupt 3 //利用PWM来改变亮度
{
TH1=(65536-20)/256; //定时器0设定约1000us中断一次
TL1=(65536-20)%256;
num++;//PWM定时器
flashnum++;//闪烁渐变变量
if(num>=100)//此PWM等级为100,它由变量num与dat完成
num=0;
if(num<dat)
LED=0;//如果计数器变量小于PWM时,LED亮
else
LED=1;
}
/****************************************/
/***************定时器0部分**************/
/****************************************/
void zhong1() interrupt 1//用来产生遥控解码计时
{
TL0=0;
TH0=0;
}