注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
77554971的个人空间 https://home.eeworld.com.cn/space-uid-229832.html [收藏] [复制] [分享] [RSS]
日志

电视机红外遥控和接收的制作_落叶★秋枫的空间

已有 1328 次阅读2010-11-30 10:33

红外遥控器发送数据时,是将二进制数据调制成一系列的脉冲信号红外发射管发射出去,红外载波为频率38KHz的方波,红外接收端在收到38KHz的载波信号时,会输出低电平,否则输出高电平,从而可以将“时断时续”的红外光信号解调成一定周期的连续方波信号,再经过1838一体化红外接收头解调便可以恢复出原数据信号。

红外遥控器的原理到处是,这里就不多废话了,直接上图:

程序:

#include

#include

#include

#define uint unsigned int

#define uchar unsigned char

sbit ir=P3^2 ;

//红外端口

sbit P2_0=P2^0 ; //LED1端口

sbit P2_1=P2^1 ; //LED2端口

sbit P2_2=P2^2 ; //LED3端口

sbit P2_3=P2^3 ; //LED4端口

sbit P2_4=P2^4 ; //LED5端口

sbit P2_5=P2^5 ; //LED6端口

sbit P2_6=P2^6 ; //LED7端口

sbit P2_7=P2^7 ; //LED8端口

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:数据编码接收区

///延时子程序 10us

void delay_10us(unsigned char y)

{

unsigned char x ;

for(x=y;x>0;x--);

}

/////初始化

void init(void)

{

ir=1 ;

//红外端口写 1

EA=1 ;

//开总中断

TMOD=0x02 ;

//定时器0,模式2,8 位自动装载模式

TH0=0Xd1 ;

//定时50us

TL0=0Xd1 ;

IT0=1 ;

//INT1 下降沿触发

ET0=1 ;

//允许定时器中断

EX0=1 ;

//允许外部中断

}

/***********************************************

定时器中断

***********************************************/

///定时器中断

void time0()interrupt 1

{

count++;

//定时器中断次数累加

}

/**********************************************

外部中断,红外解码程序

**********************************************/

///外部中断

void int1()interrupt 0

{

TR0=1 ;

//开定时器中断

//如果信号合法,则放入buf_count,count 清 0,对下一个脉冲信号计时

if(count>12&&count<270)

{

buf_count=count ;

count=0 ;

}

delay_10us(10);

//延时 100us 以消除下降沿跳变抖动

//INT1 引脚稳定为低电平,则表法确实是信号,count 重新计时,因上面延时了50us,故要 补偿 1 次TO 中断

if(ir==0)

{

count=2 ;

}

//若收到的信号合法,则再进行信号分析

if(buf_count>12&&buf_count<270)

{

//如果之前未收到引导码

if(ir_status==0)

{

//判断是否引导码 13.5ms

if(buf_count>210&&buf_count<270)

{

ir_status=1 ;

//系统标记

buf_count=0 ;

//

}

}

///收到引导码

else if(ir_status==1)

{

//若收完26 个脉冲

if(common_code_count>=25)

{

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)

{

//收到数据少于8 位,则将收到的数据写入buf_key_code

if(key_bit_count<8)

{

if(buf_count>40&&buf_count<70)

{

buf_count=0 ;

buf_key_code>>=1 ;

buf_key_code|=0x80 ;

//收到 1

key_bit_count++;

//数据脉冲累加

}

//收到0

else if(buf_count>12&&buf_count<32)

{

buf_count=0 ;

buf_key_code>>=1 ;

//收到0

key_bit_count++;

}

}

//若收完 8 位数据则做以下处理

else

{

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 main()

{

init(); //中断初始化。

P2_0=P2_1=P2_2=P2_3=P2_4=P2_5=P2_6=P2_7=1;//初始化,使全部LED灯灭。

while(1)

{

while(!new_code);

//判断是否有新按键,如果有则执行下面程序,没有则一直循环

switch(key_code%16) //判断哪个按键。

{case 1:P2_0=~P2_0;break; //当按下按键1,LED1亮或灭。

case 2:P2_1=~P2_1;break; //当按下按键2,LED2亮或灭。

case 3:P2_2=~P2_2;break; //当按下按键3,LED3亮或灭。

case 4:P2_3=~P2_3;break; //当按下按键4,LED4亮或灭。

case 5:P2_4=~P2_4;break; //当按下按键5,LED5亮或灭。

case 6:P2_5=~P2_5;break; //当按下按键6,LED6亮或灭。

case 7:P2_6=~P2_6;break; //当按下按键7,LED7亮或灭。

case 8:P2_7=~P2_7;break; //当按下按键8,LED8亮或灭。

}

new_code=0; //按键标志位清“0”,进入下一次循环判断。

}

}

红外发射原理图:

晶振用的是22.1184M

三级管驱动红外发射电路: R16另一边接P1.0

红外发射程序如下:(参考网上程序)

#include

#define uint unsigned int

#define uchar unsigned char

bit irout;//红外管状态

sbit ir=P1^7;//红外发射管控制脚

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;

P2=0xff;

keytemp=P2&0xff;

if(keytemp!=0xff)

{

delay(20);

keytemp=P2&0xff;

if(keytemp!=0xff)

keyflag=1;//有按键标志

switch(keytemp)

{

case 0xfe:irdata=1;break;//按键1

case 0xfd:irdata=2;break;//按键2

case 0xfb:irdata=3;break;//按键3

case 0xf7:irdata=4;break;//按键4

case 0xef:irdata=5;break;//按键5

case 0xdf:irdata=6;break;//按键6

case 0xbf:irdata=7;break;//按键7

case 0x7f:irdata=8;break;//按键8

}

}

}

/*******************************************

发送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

TR0=0;

if(ircode&0x01)//判断红外编码最低位,1宽的高电平,0窄的高电平

{

set_count=120;

}

else

{

set_count=38;

}

flag=0;

count=0;

TR0=1;

while(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

TR0=0;

if(ircode&0x01)

{

set_count=120;

}

else

{

set_count=38;

}

flag=0;

count=0;

TR0=1;

while(count

TR0=0;

ircode=ircode>>1;

}

}

/*******************************************

发送红外数据

*******************************************/

void sendcode(void)

{

set_count=575;//发送9ms 38K红外光

flag=1;

count=0;

TR0=1;

while(count

TR0=0;

set_count=320;//间隔4.5ms

flag=0;

count=0;

TR0=1;

while(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

TR0=0;

ir=1;

delay(23);//延时23ms(编码中的23ms高电平)

set_count=575;//发送9ms 38k红外波

flag=1;

count=0;

TR0=1;

while(count

TR0=0;

set_count=330;//间隔4.5ms

flag=0;

count=0;

TR0=1;

while(count

TR0=0;

set_count=30;//发送0.56ms 38k红外波(编码中的0.56ms低电平)

flag=1;

count=0;

TR0=1;

while(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;

}

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章