资源描述
______________________________________________________________________________________________________________
基于51单片机的红外遥控
红外遥控是无线遥控的一种方式,本文讲述的红外遥控,采用STC89C52单片机,1838红外接收头和38k红外遥控器。
1838红外接收头:
红外遥控器:
原理:
红外接收的原理我不赘述,百度文库上不少,我推荐个网址,这篇文章写得比较清楚,也比较全面,
我主要讲下程序的具体意思,在了解原理的基础上,我们知道,当我们在遥控器上每按下一个键,遥控器上的红外发射头都会发出一个32位的编码(32位编码分成4组8位二进制编码,前16位为用户码和用户反码,后16位为数据码和数据反码,用户码表示遥控器类型,数据码表示按键编码),不同的键对应不同的编码,红外接收头接收到这个编码后,发送给单片机,再进行相关操作。
源程序1:(这个程序的功能是将用户码和用户反码,数据码和数据反码显示在1602液晶上,因为遥控器买回来是不会说明按键对应什么码值,所以先自己测试,确定每个按键的码值)
#include<reg52.h>
#include<stdio.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define _Nop() _nop_()
#define TURE 1
#define FALSE 0
/*端口定义*/
sbit lcd_rs_port = P3^5; /*定义LCD控制端口*/
sbit lcd_rw_port = P3^6;
sbit lcd_en_port = P3^4;
#define lcd_data_port P0
///////////////////////////////////
void delay1 (void)//关闭数码管延时程序
{
int k;
for (k=0; k<1000; k++);
}
////////////////////////////////////
uchar code line0[16]={" user: "};
uchar code line1[16]={" data: "};
uchar code lcd_mun_to_char[16]={"0123456789ABCDEF"};
unsigned char irtime;//红外用全局变量
bit irpro_ok,irok;
unsigned char IRcord[4];//用来存放用户码、用户反码、数据码、数据反码
unsigned char irdata[33];//用来存放32位码值
void ShowString (unsigned char line,char *ptr);
//////////////////////////////////////////////
void Delay(unsigned char mS);
void Ir_work(void);
void Ircordpro(void);
void tim0_isr (void) interrupt 1 using 1//定时器0中断服务函数
{
irtime++;
}
void ex0_isr (void) interrupt 0 using 0//外部中断0服务函数
{
static unsigned char i;
static bit startflag;
if(startflag){
if(irtime<63&&irtime>=33)//引导码 TC9012的头码
i=0;
irdata[i]=irtime;
irtime=0;
i++;
if(i==33){
irok=1;
i=0;
}
}
else{
irtime=0;
startflag=1;
}
}
void TIM0init(void)//定时器0初始化
{
TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值
TH0=0x00;//reload value
TL0=0x00;//initial value
ET0=1;//开中断
TR0=1;
}
void EX0init(void)
{
IT0 = 1; // Configure interrupt 0 for falling edge on /INT0 (P3.2)
EX0 = 1; // Enable EX0 Interrupt
EA = 1;
}
void Ircordpro(void)//红外码值处理函数(关键函数)
{
unsigned char i, j, k=1;
unsigned char cord,value;
for(i=0;i<4;i++){//处理4个字节
for(j=1;j<=8;j++){ //处理1个字节8位
cord=irdata[k];
value=value>>1;
if(cord>7) value=value|0x80; //大于某值为1
k++;
}
IRcord[i]=value;
value=0;
}
irpro_ok=1;//处理完毕标志位置1
}
///////////////////////////////////////////
void lcd_delay(uchar ms) /*LCD1602 延时*/
{
uchar j;
while(ms--){
for(j=0;j<250;j++)
{;}
}
}
//////////////////////////////////////////////
void lcd_busy_wait() /*LCD1602 忙等待*/
{
lcd_rs_port = 0;
lcd_rw_port = 1;
lcd_en_port = 1;
lcd_data_port = 0xff;
_Nop();
_Nop();
_Nop();
_Nop();
while (lcd_data_port&0x80);
lcd_en_port = 0;
}
///////////////////////////////////////////////
void lcd_command_write(uchar command) /*LCD1602 命令字写入*/
{
lcd_busy_wait();
lcd_rs_port = 0;
lcd_rw_port = 0;
lcd_en_port = 0;
lcd_data_port = command;
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
lcd_en_port = 1;
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
lcd_en_port = 0;
}
/////////////////////////////////////////
void lcd_system_reset() /*LCD1602 初始化*/
{
lcd_delay(20);
lcd_command_write(0x38);
lcd_delay(100);
lcd_command_write(0x38);
lcd_delay(50);
lcd_command_write(0x38);
lcd_delay(10);
lcd_command_write(0x08);
lcd_command_write(0x01);
lcd_command_write(0x06);
lcd_command_write(0x0c);
}
//////////////////////////////////////////////////
void lcd_char_write(uchar x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/
{
x_pos &= 0x0f; /* X位置范围 0~15 */
y_pos &= 0x01; /* Y位置范围 0~ 1 */
if(y_pos==1) x_pos += 0x40;
x_pos += 0x80;
lcd_command_write(x_pos);
lcd_busy_wait();
lcd_rs_port = 1;
lcd_rw_port = 0;
lcd_en_port = 0;
lcd_data_port = lcd_dat;
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
lcd_en_port = 1;
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
lcd_en_port = 0;
}
void main(void)
{
uchar i;
lcd_system_reset(); /* 初始化LCD1602 */
lcd_data_port = 0xff;
for(i=0;i<16;i++) lcd_char_write(i,0,line0[i]);
for(i=0;i<16;i++) lcd_char_write(i,1,line1[i]);
EX0init(); // Enable Global Interrupt Flag
TIM0init();
while(1){//主循环
if(irok){
Ircordpro();
irok=0;
}
if(irpro_ok){ /*遥控成功接收*/
lcd_char_write(8,0,lcd_mun_to_char[IRcord[0]/0x10]);
lcd_char_write(9,0,lcd_mun_to_char[IRcord[0]%0x10]);
lcd_char_write(11,0,lcd_mun_to_char[IRcord[1]/0x10]);
lcd_char_write(12,0,lcd_mun_to_char[IRcord[1]%0x10]);
lcd_char_write(8,1,lcd_mun_to_char[IRcord[2]/0x10]);
lcd_char_write(9,1,lcd_mun_to_char[IRcord[2]%0x10]);
lcd_char_write(11,1,lcd_mun_to_char[IRcord[3]/0x10]);
lcd_char_write(12,1,lcd_mun_to_char[IRcord[3]%0x10]);
}//将码值显示在液晶上
}
}
源程序2:(在知道了按键编码的基础上,我们便可以加入判断,判断哪个键被按下,进而执行相关操作)
我只修改main函数,其他与源程序1相同
sbit led1=P1^0;
sbit led2=P1^1;
sbit led3=P1^2;
sbit led4=P1^3;
sbit led5=P1^4;//发光二极管控制端定义
void main(void)
{
uchar i;
lcd_system_reset(); /* 初始化LCD1602 */
lcd_data_port = 0xff;
for(i=0;i<16;i++) lcd_char_write(i,0,line0[i]);
for(i=0;i<16;i++) lcd_char_write(i,1,line1[i]);
EX0init(); // Enable Global Interrupt Flag
TIM0init();
while(1){//主循环
if(irok){
Ircordpro();
irok=0;
}
if(irpro_ok){ /*遥控成功接收*/
switch(IRcord[2])//为什么判断IRcord[2],因为这个里面存放的是数据码
{
case 0x0c: led1=0;//按0键,灯1亮
break;
case 0x18: led2=0; //按1键,灯2亮
break;
case 0x5e: led3=0; //按2键,灯3亮
break;
case 0x08: led4=0; //按3键,灯4亮
break;
case 0x1c: led5=0; //按4键,灯5亮
break;
}
}
}
}
附连接图
Welcome To
Download !!!
欢迎您的下载,资料仅供参考!
精品资料
展开阅读全文