遥控调光灯设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

在现代社会发展中环保节能是必然的发展的趋势。

电子遥控技术的发展使现代人的生活习惯慢慢走向便利,本设计就设计一款可遥控调光。

它主要以51单片机为主控芯片,由ADC0809对旋转亮度旋钮进转把模拟量换成数字量。

使用PWM驱动方式,通过调速PWM脉冲的脉宽比控制双向可控硅的导通角从而达到LED亮度连续可调。

遥控部分使用AT89C2051单片机进行红外编码调制提高抗干扰能力,接收用红外一体化接收头,由51单片机对信号进行解码,实现整机控制。

关键词:ADC0809 PWM调制红外编码连续可调
摘要 (2)
1方案论证 (4)
1方案论述 (4)
2 方案论证 (4)
2硬件电路的设计 (4)
1 电路方框图 (4)
2主要单元电路 (5)
3软件的部分设计 (6)
1遥控红外编码部分 (7)
2主机解码部分 (10)
5系统测试 (12)
1 主机功能测试 (12)
2 从机功能测试 (12)
6总结 (13)
7参考文献 (13)
8附录 (13)
一.方案论证
1.方案论述
方案一:手动调节由电位器直接控制双向可控硅的导通角,遥控发射部分用NE555多谐振荡电路控制红外发光管,接收部分用SONYCX20106红外接收芯片,在经过分频电路,再来通过切换电阻阻值来调节可控硅的导通角。

方案二:手动调节由电位器直接控制可控硅的导通角完成,红外发射部分由小单片机AT89C2051来完成,接收有红外一体化接收,然后在由单片机完成数据处理,用单片机的I/O切换不同阻值电阻来控制可控硅的导通角。

方案三:手动调节先由电位器来调节一个模拟量,在由AD0809来转换成一个数字量,再由单片机来处理。

红外发射部分还是由小单片机AT89C2051来完成,接收部分是由红外一体化接收,在由单片机处理,用PWM调制方式控制输出电压。

2. 方案论证
(1)方案一里面电路简单,但达不到题目要求采用单片机为主控芯片的要求,功能也不能完全实现,所以舍弃此方案。

(2)方案二电路简单易控制,但在手动调节和遥控调节会互相干扰,达不到便利的目的,所以就舍弃此方案。

(3)方案三电路较复杂,程序控制也较难,在成本控制方面因为使用了AD0809所以也不是很理想。

但在功能方面手动调节和遥控调可以相互转换。

功能也就比较强大,达到题意的基本要求。

综上所述这里采用方案三。

二. 硬件电路的设计
1. 电路方框图: (1)主机电路方框图:
(2)遥控电路方框图:
2. 主要单元电路 (1)调光电路
从单片机P1.6出来的PWM 调制信号控制可控硅的导通角,导通角越大灯的亮度越高。

(2)模数转换电路
(3)遥控电路
三.软件设计:
其中PWM程序使用定时器1作为PWM脉冲输出的基本单位。

程序中定时器0工作在模式2,且计时高低字节寄存器TH1、TL1的初始值为0x97H。

定时器的定时过程如图5-9所示。

从上图可以看出,中断与中断之间相隔时间为256us(即每256产生中断一次)。

程序中每一脉冲的周期有“P”个基本时间单位。

如果“P”为00H,则表示脉冲周期为256个基本时间单位。

因此每一个脉冲周期计算如下:脉冲周期=25625us
=65536us
=65.536ms
程序中“clock”设为“FFH”,表示总共送出去255个高电平部分逐次曾大的脉冲。

输出的脉冲波形如图5-10所示。

输出脉冲中,第一个脉冲“T1”的脉宽比例为
1.遥控红外编码部分
/*******************************************
发送8位红外数据
*******************************************/
void sendcode_8(void)
{
uchar i;
for(i=0; i<8; i++)
{
set_count = 28;//发送0.56ms 38k红外波(编码中的0.56ms低电平)
flag = 1;
count = 0;
TR0 = 1;
while (count<set_count);
TR0=0;
if(ircode & 0x01)//判断红外编码最低位,1宽的高电平,0窄的高电平
{
set_count = 120;
}
else
{
set_count=38;
}
flag=0;
count=0;
TR0=1;
while( count <s et_count);
TR0=0;
ircode = ircode>>1;
}
}
/******************************************* 发送2位红外数据
*******************************************/ void sendcode_2(void)//前26位系统码最后两位{
uchar i;
for(i=0;i<2;i++)
{
set_count=28;
flag = 1;
count = 0;
TR0 = 1;
while (count<set_count);
TR0 = 0;
if(ircode&0x01)
{
set_count = 120;
}
else
{
set_count = 38;
}
flag = 0;
count = 0;
TR0 = 1;
while(count<set_count);
TR0=0;
ircode = ircode>>1;
}
}
/******************************************* 发送红外数据
*******************************************/ void sendcode(void)
{
set_count = 575;//发送9ms 38K红外光
flag = 1;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
set_count = 320;//间隔4.5ms
flag = 0;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
ircode = irsys[0];//发送26位系统码的前1-8位
sendcode_8();
ircode = irsys[1];//发送26位系统码的前9-16位
sendcode_8();
ircode = irsys[2];//发送26位系统码的前17-24位
sendcode_8();
ircode = irsys[3];//发送26位系统码的前24-26位
sendcode_2();
ircode = irdata;//发送8位数据码
sendcode_8();
ircode = ~irdata; //发送8位数据反码
sendcode_8();
set_count = 28;//发送0.56ms 38k红外波(编码中的0.56ms低电平)flag = 1;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
ir = 1;
delay(23);//延时23ms(编码中的23ms高电平)
set_count = 575;//发送9ms 38k红外波
flag=1;
count=0;
TR0=1;
while(count<set_count);
TR0=0;
set_count = 330;//间隔4.5ms
flag = 0;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
set_count = 30;//发送0.56ms 38k红外波(编码中的0.56ms低电平)flag = 1;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
ir = 1;
}
/*******************************************
定时器初始化
*******************************************/
void init_timer()
{
EA = 1;
TMOD = 0X02;//8位自动重载模式
ET0 = 1;
TH0 = 0XE8;//定时13us,38K红外波,晶振22.1184
TL0 = 0XE8;
}
2.主机解码部分
void init(void) // 时器初使化
{
ir=1; //红外端口写1
EA=1; //开总中断
TMOD=0x22; //定时器0\1,模式2,8位自动装载模式TH0=0Xd1;
TL0=0Xd1;
TH1=156;
TL1=156;
TR1=1;
ET1=1;
IT1=1; //INT1下降沿触发
ET0=1;
EX1=1;
}
/***********************************************
定时器0中断
***********************************************/
void time0() interrupt 1 //时器中断
{
count++;//定时器中断次数累加
}
/**********************************************
外部中断,红外解码程序
**********************************************/
void int1() interrupt 2///外部中断
{
TR0=1;//开定时器中断
if (count>12&&count<270)//如果信号合法,则放入buf_count,count清0,对下一个脉冲信号计时{
buf_count=count;
count=0;
}
delay_10us(10);//延时100us以消除下降沿跳变抖动
if (ir==0)//INT1引脚稳定为低电平,则表法确实是信号,count重新计时,因上面延时了50us,故要补偿1次TO中断
{
count=2;
}
if (buf_count>12 && buf_count<270)//若收到的信号合法,则再进行信号分析
{
if (ir_status==0)//如果之前未收到引导码
{
if (buf_count>210 && buf_count<270)//判断是否引导码13.5ms
{
ir_status=1;//系统标记
buf_count=0;
}
}
else if(ir_status ==1 )///收到引导码
{
if (common_code_count >= 25)//若收完26个脉冲
{
ir_status=2;//数据解码标记
common_code_count=0;//系统码计算清零
buf_count=0;//中断计数暂存清0
}
else if ((buf_count>40 && buf_count<70) || (buf_count>12 && buf_count<32))
{
buf_count = 0;
common_code_count++;//每收到一个信号自加1
}
}
else if (ir_status == 2)//进入数据编码接收
{
if (key_bit_count < 8)//收到数据少于8位,则将收到的数据写入buf_key_code
{
if (buf_count>40 && buf_count<70)
{
buf_count = 0;
buf_key_code >>= 1;
buf_key_code |= 0x80;//收到1
key_bit_count++;//数据脉冲累加
}
else if (buf_count>12 && buf_count<32)//收到0
{
buf_count=0;
buf_key_code>>=1;//收到0
key_bit_count++;
}
}
else //若收完8位数据则做以下处理
{
ir_status = 0;//接收状态返回到空闲
key_code = buf_key_code;
key_bit_count = 0;
buf_key_code = 0;
buf_count = 0;
TR0 = 0;
new_code = 1;
}
}
}
}
四.系统测试
4、1主机功能测试
这里测试是以数字示波器(型号:DS5022M,带宽:25MHz,实时采样率:500MSa/s)数字万用表(型号:VC9807A+),旋转主机亮度旋钮,测量旋钮上的电压与PWM频率(如下表所示):
(注:其中我们设定1/13为高亮度,6/13为中亮度,11/13中低亮度)
电压与脉宽如下图所示:
由上图看出ACD0809转换数据较准确。

4、1从机功能测试
从机部分的测试,我们只测量距离。

实际制作中,距离可以达到8米左右。

五.总结
1.这是我们第一次参加这样的比赛,感觉很累很辛苦。

但我们感觉很高兴,我们通过几天的奋战,做出了我赛题所要求的产品。

2.我们在这次比赛中确实学到了很多东西,队友的分工合作直接影响到工作的效率,在比赛中也体会到那么一点一个产品开发的流程的味道。

3.这次比赛也为我们9月份的全国赛提供了一次演练的机会,得到了比赛时间按安排的宝贵经验。

4.这次比赛也让我们认识到自身的缺陷,让我们知道以后该训练的重点
六.参考文献
[1]《电子电工实践指导》王港元主编·江西科学技术出版社(第四版)
[2]《C51单片机典型模块设计与应用》边春元李文涛江杰杜平等编著
[3]《模拟电子技术》周雪主编·西安电子科技大学出版社(修订版)
[4]《常用集成电路应用实例》荷希才编·电子工业出版社
[5]《数字集成电路应用300例》黄继昌等编·人民邮电出版社
[6]《单片机C语言应用程序设计》马忠梅等编·北京航空航天大学出版社
[7]《单片机外围电路设计》沙占友王彦朋孟志永等编·电子工业出版社
七、附录
附录一:
主机原程序代码:
#include <reg52.h>
#include <math.h>
#define uint unsigned int
#define uchar unsigned char
#define AD_data P2
uint k,k_on,off,TH;
uchar time;
bit ON_OFF; //电位器调接允许端,0允许,1允许
sbit ALE =P3^6; //ADC0809 地址锁存允许信号
sbit EOC =P3^1; //ADC0809 转换结束信号
sbit OE =P3^4; //ADC0809 输出允许
sbit clock=P3^0; //ADC0809 外部时钟脉冲输入端
sbit LAMP =P1^6; //高亮度LED驱动
sbit ir=P3^3; //红外端口
uchar key_code=0; //遥控键值
uchar new_code=0; //有无新按键
uint buf_key_code=0; //键值暂存
uchar key_bit_count=0; //键编码脉冲计数
uint count=0; //定时中断次数计数
uint buf_count=0; //定时中断计数暂存
uchar common_code_count=0; //前导码脉冲计数
uchar ir_status=0; //脉冲接收器所处的状态,0:无信号,1:系统码接收区,2:数据编码接收区void delay_10us(unsigned char y)//延时子程序10us
{
unsigned char x;
for(x=y;x>0;x--);
}
void delay_ms(uint z)//延时子程序1ms
{
uint x,y;
for(x=z;x>0;x--)
for(y=113;y>0;y--);
}
void init(void) // 时器初使化
{
ir=1; //红外端口写1
EA=1; //开总中断
TMOD=0x22; //定时器0\1,模式2,8位自动装载模式TH0=0Xd1;
TL0=0Xd1;
TH1=156;
TL1=156;
TR1=1;
ET1=1;
IT1=1; //INT1下降沿触发
ET0=1;
EX1=1;
}
/***********************************************
***********************************************/
void time0() interrupt 1 //时器中断
{
count++;//定时器中断次数累加
}
/**********************************************
外部中断,红外解码程序
**********************************************/
void int1() interrupt 2///外部中断
{
TR0=1;//开定时器中断
if (count>12&&count<270)//如果信号合法,则放入buf_count,count清0,对下一个脉冲信号计时
{
buf_count=count;
count=0;
}
delay_10us(10);//延时100us以消除下降沿跳变抖动
if (ir==0)//INT1引脚稳定为低电平,则表法确实是信号,count重新计时,因上面延时了50us,故要补偿1次TO 中断
{
count=2;
}
if (buf_count>12 && buf_count<270)//若收到的信号合法,则再进行信号分析
{
if (ir_status==0)//如果之前未收到引导码
{
if (buf_count>210 && buf_count<270)//判断是否引导码13.5ms
ir_status=1;//系统标记
buf_count=0;
}
}
else if(ir_status ==1 )///收到引导码
{
if (common_code_count >= 25)//若收完26个脉冲
{
ir_status=2;//数据解码标记
common_code_count=0;//系统码计算清零
buf_count=0;//中断计数暂存清0
}
else if ((buf_count>40 && buf_count<70) || (buf_count>12 && buf_count<32)) {
buf_count = 0;
common_code_count++;//每收到一个信号自加1
}
}
else if (ir_status == 2)//进入数据编码接收
{
if (key_bit_count < 8)//收到数据少于8位,则将收到的数据写入buf_key_code {
if (buf_count>40 && buf_count<70)
{
buf_count = 0;
buf_key_code >>= 1;
buf_key_code |= 0x80;//收到1
key_bit_count++;//数据脉冲累加
}
else if (buf_count>12 && buf_count<32)//收到0
{
buf_count=0;
buf_key_code>>=1;//收到0
key_bit_count++;
}
}
else //若收完8位数据则做以下处理
{
ir_status = 0;//接收状态返回到空闲
key_code = buf_key_code;
key_bit_count = 0;
buf_key_code = 0;
buf_count = 0;
TR0 = 0;
new_code = 1;
}
}
}
}
void RUN_AD(void)
{
ALE = 0;
delay_ms(20);
ALE = 1; //启动AD转换
delay_ms(20);
ALE = 0;
while(0 == EOC);
OE = 1;
k = AD_data;
if(abs(k_on-k)>5) {ON_OFF = 0;off = 0;} //重新激活旋转亮度调节
k_on=k;
OE = 0;
if(!ON_OFF) TH = k;
P0=k;
}
void time_t1(void)interrupt 3
{
clock=~clock; //ADC0809外部时钟信号
time++;
if (time >= 128) { time = 0;LAMP = 1|off;} //PWM调节
if (time >= TH/2) LAMP = 0|off;
}
/*************************************
主程序
*************************************/
void main()
{
init(); //定时器初始化
while(1)
{
while(!new_code) RUN_AD(); //判断是否有新按键,如果有则执行下面程序,没有则一直循环if(key_code < 50) //遥控器对应
{
switch(key_code) //按键处理
{
case 30: off = ~off; break; //开关
case 31: ON_OFF = 1; TH = 220; break; //低亮度
case 26: ON_OFF = 1; TH = 140; break; //中亮度
case 27: ON_OFF = 1; TH = 10; break; //高亮度
}
new_code=0;
}
}
}
附录二:
从机程序代码:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
bit irout;//红外管状态
sbit ir=P1^2;//红外发射管控制脚
uint count, set_count;//中断计数,设定中断次数
bit flag,keyflag;//红外发送标志,按键标志位
uchar irsys[4]={0x1a,0xa1,0xdc,0x03};//26位系统码,最后一个字节只用2位uchar ircode,irdata;
/**********************************************
延时1ms
***********************************************/
void delay(uint z)//延时1ms,晶振22.1184M
{
uint x,y;
for(x=z;x>0;x--)
for(y=225;y>0;y--);
}
/**********************************************
按键扫描
**********************************************/
void keyscan(void)
{
uchar keytemp;
P3=0xff;
keytemp=P3&0x0f;
if(keytemp!=0x0f)
{
delay(20);
keytemp=P3&0x0f;
if(keytemp!=0x0f)
keyflag=1;//有按键标志
switch(keytemp)
{
case 0x0e:irdata=27;break;//按键1对应该遥控器P+的键值
case 0x0d:irdata=26;break;//按键2对应该遥控器P-的键值
case 0x0b:irdata=31;break;//按键3对应该遥控器VOL+的键值
case 0x07:irdata=30;break;//按键4对应该遥控器VOL-的键值}
}
}
/*******************************************
发送8位红外数据
*******************************************/
void sendcode_8(void)
{
uchar i;
for(i=0; i<8; i++)
{
set_count = 28;//发送0.56ms 38k红外波(编码中的0.56ms低电平)
flag = 1;
count = 0;
TR0 = 1;
while (count<set_count);
TR0=0;
if(ircode & 0x01)//判断红外编码最低位,1宽的高电平,0窄的高电平
{
set_count = 120;
}
else
{
set_count=38;
}
flag=0;
count=0;
TR0=1;
while( count <s et_count);
TR0=0;
ircode = ircode>>1;
}
}
/*******************************************
发送2位红外数据
*******************************************/
void sendcode_2(void)//前26位系统码最后两位{
uchar i;
for(i=0;i<2;i++)
{
set_count=28;
flag = 1;
count = 0;
TR0 = 1;
while (count<set_count);
TR0 = 0;
if(ircode&0x01)
{
set_count = 120;
}
else
{
set_count = 38;
}
flag = 0;
count = 0;
TR0 = 1;
while(count<set_count);
TR0=0;
ircode = ircode>>1;
}
}
/******************************************* 发送红外数据
*******************************************/
void sendcode(void)
{
set_count = 575;//发送9ms 38K红外光
flag = 1;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
set_count = 320;//间隔4.5ms
flag = 0;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
ircode = irsys[0];//发送26位系统码的前1-8位
sendcode_8();
ircode = irsys[1];//发送26位系统码的前9-16位
sendcode_8();
ircode = irsys[2];//发送26位系统码的前17-24位
sendcode_8();
ircode = irsys[3];//发送26位系统码的前24-26位
sendcode_2();
ircode = irdata;//发送8位数据码
sendcode_8();
ircode = ~irdata; //发送8位数据反码
sendcode_8();
set_count = 28;//发送0.56ms 38k红外波(编码中的0.56ms低电平)flag = 1;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
ir = 1;
delay(23);//延时23ms(编码中的23ms高电平)
set_count = 575;//发送9ms 38k红外波
flag=1;
count=0;
TR0=1;
while(count<set_count);
TR0=0;
set_count = 330;//间隔4.5ms
flag = 0;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
set_count = 30;//发送0.56ms 38k红外波(编码中的0.56ms低电平)flag = 1;
count = 0;
TR0 = 1;
while(count < set_count);
TR0 = 0;
ir = 1;
}
/*******************************************
定时器初始化
*******************************************/
void init_timer()
{
EA = 1;
TMOD = 0X02;//8位自动重载模式
ET0 = 1;
TH0 = 0XE8;//定时13us,38K红外波,晶振22.1184 TL0 = 0XE8;
}
/*******************************************
主函数
*******************************************/
void main(void)
{
init_timer();
count=0;
flag=0;
irout=1;
while(1)
{
keyscan();
if(keyflag)//若有新按键
{
delay(10);
sendcode();//发送红外编码
delay(500);
keyflag=0;//按键标志清零
}
}
}
/*******************************************
定时器中断
*******************************************/
void timer0(void) interrupt 1
{
count++;
if(flag==1)
{
irout=~irout;
}
else
{
irout=1;
}
ir=irout;
}。

相关文档
最新文档