基于单片机红外遥控器

基于单片机红外遥控器
基于单片机红外遥控器

单片机原理及系统课程设计

专业:自动化

班级:自动化1202

姓名:

学号:201209111

指导教师:于晓英

兰州交通大学自动化与电气工程学院

2014年12 月31日

基于单片机的红外遥控器

1方案设计

1.1题目

基于单片机的红外遥控器。

1.2设计目的

通过本次设计对所学的单片机知识有更深入的了解;特别是单片机的红外发送,红外接收,中断,定时,计数,频率,矩阵键盘以及红外遥控NEC协议的理解和掌握。同时也能熟练掌握keil软件和protues仿真软件,主要目的是让我们把所学的基础知识运用到实际当中去。

1.3方案

本设计主要应用了AT89C51单片机作为核心,综合应用了单片机中断系统、定时器、计数器等知识,应用红外线的优点。遥控操作的不同,遥控发射器通过对红外线发射频率的控制来区别不同的操作。遥控接收器通过对红外光接收频率的识别,判断出控制操作,来完成整个红外遥控发射、接收过程。

发射模块:单片机不工作时一直处于低功耗状态,采用了空闲节电工作方式。当遥控器的某一按键被按下以后,外部中断1产生中断,唤醒单片机进入工作状态,查询键盘按下的是哪一个按键,当确认按键后,控制软件启动定时器T0、T1,T1作为发射时间控制器,T0作为红外线发射频率控制器,T0定时溢出时中断程序使红外管接口电平反转一次,写入定时器的初值不同,在输出端口就得到不同的发射频率。T1定时溢出时中断程序关闭T0定时器,停止红外线发射。其设计原理框图如图1所示。

接收模块;利用单片机中的T0作为红外脉冲计数器,T1作为计数时间控制器。当电路中红外接收管接收到第一个红外脉冲时,外部中断1被触发,启动计数器T0和定时器T1。定时溢出,中断程序关闭计数器T0,读入计数值并进行判断,确定操作对象(遥控按键)对其进行反转操作,控制电路对所控制的负载进行开或关。其设计原理框图如图2所示。

1.4模块图

红外发射部分对应模块图如图1所示,红外接收部对应模块图如图2所示,其功能为方案所述。

图1发射部分模块图

图2 接收部分模块图

2硬件设计

2.1单片机最小系统

单片机的最小系统是指用最少的元件组成的单片机可以工作的系统,对51

2.2

线的低为分别为p1.7,p1.3。扫描键盘时通过先扫行再扫列确定按键的位置。

P 14

P 15

P 16

P 17

P10

P11

P12

P13

图3 矩阵键盘电路

2.3红外发射电路

图4为红外发射电路,当原始信号为低电平的时候,38KHZ 载波输出,当信号为低电平的时候不发送载波。用38KHZ 的载波去装载原始信号。

图4 红外发射电路

2.4红外接收电路

图5为红外接收电路,红外接收完成对红外信号的接收、放大、检波、整形,并解调出遥控编码脉冲,为了减少干扰,采用的是一体化红外接收头,它接收的红外信号频率为38KHZ 。

Demodulator

IRL1

IRLINK

红外接收发射管

U3

NOT

图6 仿真发射接收电路

2.6接收状态反映电路

图7所示为输出状态反映电路,当按下矩阵开关的四个不同按键,继电器分别响应开关状态。

P110

P114

P135

RL1

OMIH-SH-105D

RL2

OMIH-SH-105D

Q1

PNP

R6

2.2k D6

LED-RED R7

1k

Q2

PNP

R8

1k

R9

2.2k D7

LED-RED

R10

1k

L1

5V

L2

5V

2.7整体仿真电路

图8所示为整体仿真电路,红外遥控就是把红外线作为载体的遥控方式。由于红外线的波长远小于无线电波的波长,因此在采用红外遥控方式时,不会干扰其他电器的正常工作,也不会影响临近的无线电设备。常用的红外遥控系统一般分发射和接收两个部分。当按下遥控器按钮就会产生具有不同的编码数字脉冲,这种代码指令信号调制在38kHz的截波上,激励红外光二级管产生具有脉冲串的红外波,通过空间的传送到受控机内的遥控接收器。在接收过程中,红外波信号通过光电二级管转换为38kHz的电信号,此信号经过放大、检波、整形、解调、送到解码与接口电路,从而完成相应的遥控功能。但由于proteus仿真软件无法进行无线仿真,故利用中断在单片机产生频率为38KHZ的载波信号,装载原始信号,再在接收部分进行解调。控制继电器的开关。

图8 整体仿真电路

3软件设计

3.1流程图

流程图有两部分组成,分别为发射部分和接收部分。

图9 发送部分(左)接收部分(右)流程图

3.2源程序

源程序见附录。

4系统仿真

4.1仿真截图

图9所示为整体仿真结果,按下矩阵键盘的按键,相应的会有继电器的闭合,LED灯的亮灭。

图10 整体仿真电路

参考文献

[1] 王思明,张金敏,张鑫等.单片机原理及应用系统设计.北京:科学出版社,2012.

[2] 张金敏,董海棠,高博等,单片机原理应用系统设计.成都:西南交通大学出版社,2010.

[3]谭浩强.C程序设计(第四版).北京.清华大学出版社,2010.

附录

原理图

图1 发射过程原理图

源程序

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

红外发射源程序

*******************************************************************/ #include

#define uint unsigned int

#define uchar unsigned char //宏定义

#define K P1 //键盘使用管脚定义

sbit HL=P3^4;

sbit LED=P3^3; //红外管脚接口

static bit OP; //红外发射管的亮灭控制

static uint count; //延时计数器

static uint endcount; //终止延时计数器

static uchar flag; //红外发送标志

char iraddr1; //16位地址第一字节

char iraddr2; //16位地址第二字节

char Key_=0x10; //发送数据

uchar Data=0x00; //键盘参数

void SendIRdata(char p_irdata); //函数声明红外发送

uchar Key(); //键盘扫描

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

主函数

********************************************************************/ void main()

{ count=0;

flag=0;

OP=0;

HL=0; //初始化

EA=1; //总中断开

TMOD=0x11; //设置定时器0和1为16位模式

ET0=1; //定时器0中断允许

TH0=0xff;

TL0=0xe6; //设定定时大小38K 等加于26us中断一次

TR0=1; //开始计数

iraddr1=3;

iraddr2=252; //写16位地址

while(1) //循环发射

{ Key_=Key(); //检测按键

if(Key_!=0x10) //是否有按键按下

{ SendIRdata(Key_); //发送

Data=Key_; //读取参数显示

while(Key_!=0x10) //等待松开

{ Key_=Key();

}

}

LED=1;

}

}

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

定时器0中断处理函数

*******************************************************************/ void timeint(void) interrupt 1

{ TH0=0xff;

TL0=0xe6; //设定定时器初值

count++; //中断计数累加

if(flag==1)

{ OP=~OP; }

else

{ OP=0; }

HL=OP;

}

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

发送数据函数

*******************************************************************/ //发送的延时时间参数即(endcount)都是在12MHZ的值

void SendIRdata(char p_irdata)

{ int i;

char irdata=p_irdata;

//发送9ms的起始码

endcount=223;

flag=1;

count=0;

while(count

//发送4.5ms的结果码

endcount=117;

flag=0;

count=0;

do{}while(count

//发送16位地址的前八位

irdata=iraddr1;

for(i=0;i<8;i++)

{ //先发送0.56ms的38K红外波(即编码中的0.56ms的低电平)endcount=10;

flag=1;

count=0;

do{}while(count

//停止发送红外信号(即编码中的高电平)

if(irdata-(irdata/2)*2) //判断二进制的个位是1还是0

{ endcount=41;} //1

else

{ endcount=15; } //0

flag=0;

count=0;

do{}while(count

irdata=irdata>>1;

}

//发送16位地址的后八位

irdata=iraddr2;

for(i=0;i<8;i++)

{ //先发送0.56ms的38K红外波(即编码中的0.56ms的低电平)endcount=10;

flag=1;

count=0;

do{}while(count

//停止发送红外信号(即编码中的高电平)

if(irdata-(irdata/2)*2) //判断二进制的个位是1还是0 { endcount=41; } //1

else

{ endcount=15; } //0

flag=0;

count=0;

do{}while(count

irdata=irdata>>1;

}

//发送8位数据

irdata=p_irdata;

for(i=0;i<8;i++)

{ //先发送0.56ms的38K红外波(即编码中的0.56ms的低电平)endcount=10;

flag=1;

count=0;

do{}while(count

//停止发送红外信号(即编码中的高电平)

if(irdata-(irdata/2)*2) //判断二进制的个位是1还是0 { endcount=41; } //1

else

{ endcount=15; } //0

flag=0;

count=0;

do{}while(count

irdata=irdata>>1;

}

//发送8位数据反码

irdata=~p_irdata;

for(i=0;i<8;i++)

{ //先发送0.56ms的38K红外波(即编码中的0.56ms的低电平)endcount=10;

flag=1;

count=0;

do{}while(count

//停止发送红外信号(即编码中的高电平)

if(irdata-(irdata/2)*2) //判断二进制的个位是1还是0

{ endcount=41; } //1

else

{ endcount=15; } //0

flag=0;

count=0;

do{}while(count

irdata=irdata>>1;

}

//结束信息

endcount=10;

flag=1;

count=0;

do{}while(count

flag=0;

}

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

键盘扫描函数

*******************************************************************/ uchar Key()

{ //扫描键盘

K=0x7f;

if(K==0x77)

{ LED=0;

return 0x01;

}

else if(K==0x7b)

{ LED=0;

return 0x02;

}

else if(K==0x7d)

{ LED=0;

return 0x03;

}

else if(K==0x7e)

{ LED=0;

return 0x0A;

}

//无键盘按下

else

{ return 0x10; }

}

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

红外接收源程序

*******************************************************************/ #include

#define uchar unsigned char //宏定义

#define uint unsigned int

//时间计算

#define Imax 14000 //此处为晶振为11.0592时的取值,

#define Imin 8000 //如用其它频率的晶振时,

#define Inum1 1450 //要改变相应的取值。

#define Inum2 700

#define Inum3 3000

unsigned char Im[4]={0x00,0x00,0x00,0x00}; //解码变量

//全局变量

uchar Data=0x00;

uchar f;

unsigned long m,Tc;

unsigned char IrOK;

sbit LED1=P1^0; //4个输出

sbit LED2=P1^4;

sbit LED3=P3^5;

sbit LED4=P3^6;

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

外部中断解码程序_外部中断1

*******************************************************************/ void intersvr1(void) interrupt 2

{ TR0=1;

Tc=TH0*256+TL0; //提取中断时间间隔时长

TH0=0;

TL0=0; //定时中断重新置零

if((Tc>Imin)&&(Tc

{ m=0;

f=1;

return;

}

//找到启始码

if(f==1)

{ if(Tc>Inum1&&Tc

{ Im[m/8]=Im[m/8]>>1|0x80; m++; }

if(Tc>Inum2&&Tc

{ Im[m/8]=Im[m/8]>>1; m++; } //取码

if(m==32) //识别出32位

{ m=0;

f=0;

if(Im[2]==~Im[3]) //检验反码

{ IrOK=1;

TR0=0; //关闭定时器

}

else IrOK=0; //取码完成后判断读码是否正确

}

//准备读下一码

}

}

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

主程序

*******************************************************************/ void main(void)

{ m=0;

f=0;

EA=1; //开启总中断

IT1=1; //下降沿有效

EX1=1; //外部中断0开

TMOD=0x11; //定时器初始化

TH0=0; //T0赋初值

TL0=0;

TR0=0; //t0开始计时

while(1) //循环执行

{ if(IrOK==1) //如果解码成功

{ IrOK=0; //清空标志位

Data=Im[2]; //赋值信息

if(Data==0x0d) //判断是哪个按键按下

LED1=!LED1; //控制开关

else if(Data==0x0c)

LED2=!LED2;

else if(Data==0x0b)

LED3=!LED3;

else if(Data==0x0a)

LED4=!LED4;

}

}

}

相关主题
相关文档
最新文档