搜档网
当前位置:搜档网 › 基于51单片机的红外遥控

基于51单片机的红外遥控

基于51单片机的红外遥控
基于51单片机的红外遥控

基于51单片机的红外遥控

红外遥控是无线遥控的一种方式,本文讲述的红外遥控,采用STC89C52单片机,1838红外接收头和38k红外遥控器。

1838红外接收头:

红外遥控器:

原理:

红外接收的原理我不赘述,百度文库上不少,我推荐个网址,这篇文章写得比较清楚,也比较全面,

我主要讲下程序的具体意思,在了解原理的基础上,我们知道,当我们在遥控器上每按下一个键,遥控器上的红外发射头都会发出一个32位的编码(32位编码分成4组8位二进制编码,前16位为用户码和用户反码,后16位为数据码和数据反码,用户码表示遥控器类型,数据码表示按键编码),不同的键对应不同的编码,红外接收头接收到这个编码后,发送给单片机,再进行相关操作。

源程序1:(这个程序的功能是将用户码和用户反码,数据码和数据反码显示在1602液晶上,因为遥控器买回来是不会说明按键对应什么码值,所以先自己测试,确定每个按键

的码值)

#include

#include<stdio.h>

#include

#defineuint unsigned int

#define uchar unsigned char

#define _Nop()_nop_()

#define TURE 1

#define FALSE 0

/*端口定义*/

sbit lcd_rs_port= P3^5;/*定义LCD控制端口*/

sbitlcd_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++);

}

////////////////////////////////////

ucharcode line0[16]={" user: "};

uchar code line1[16]={"data: "};

ucharcode lcd_mun_to_char[16]={"0123456789ABCDEF"};

unsigned char irtime;//红外用全局变量

bitirpro_ok,irok;

unsignedchar IRcord[4];//用来存放用户码、用户反码、数据码、数据反码unsigned char irdata[33];//用来存放32位码值

void ShowString (unsigned charline,char*ptr);

//////////////////////////////////////////////

void Delay(unsigned char mS);

void Ir_work(void);

voidIrcordpro(void);

voidtim0_isr (void) interrupt 1 using 1//定时器0中断服务函数

{

irtime++;

voidex0_isr(void)interrupt0using 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 interrupt0for fallingedge on/INT0 (P 3.2)

EX0 = 1; //Enable EX0Interrupt

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(ucharms)/*LCD1602 延时*/

{

uchar j;

while(ms--){

for(j=0;j<250;j++)

{;}

}

}

//////////////////////////////////////////////

voidlcd_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(); // EnableGlobal 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;

sbitled5=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;

??case0x18:led2=0; //按1键,灯2亮

????break;

?case 0x5e: led3=0; //按2键,灯3亮

??break;

??case0x08: led4=0;//按3键,灯4亮

????break;

???case 0x1c:led5=0;//按4键,灯5亮

????break;

?}

?}

}

附连接图

相关主题