//STC89C52RC_双倍速_外部晶振24MHz
#include "reg51.h"
#include "intrins.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define uchar unsigned char
#define uint unsigned int
unsigned char ir_dat_buf[4] = {0}; //红外遥控接收码存放位置
unsigned char mode; //红外线接收模式缓存
sbit P32 = P3^2; //IR
void Delay1120us(void)
{
TL1 = 0xC4;
TH1 = 0xEE;
TR1 = 1;
while(!TF1);
TR1 = 0;
TF1 = 0;
}
void Delay840us(void)
{
TL1 = 0x38;
TH1 = 0xF3;
TR1 = 1;
while(!TF1);
TR1 = 0;
TF1 = 0;
}
unsigned char ir_read(void) // 数据 0: 0.56ms低电平,0.56ms高电平
{ // 数据 1: 0.56ms低电平,1.58ms高电平
unsigned char i,ir_temp = 0;
for(i = 0; i < 8; i++)
{
while(!P32); //等待0.56ms低电平结束
Delay840us(); //从高电平开始延时0.84ms
if(P32 == 1)
{
ir_temp = (ir_temp << 1) + 1; //读到数据1
Delay1120us(); //延时等待1.68ms高电平结束
}
else
{
ir_temp = ir_temp << 1; //读到数据0
}
}
return ir_temp;
}
void main()
{
TMOD = 0x11; //set timer0 as mode1 (16-bit)
TL0 = 0; //定时4ms
TH0 = 0;
TR0 = 1; //timer0 start running
TF0 = 1;
IT0 = 1; //set INT0 int type (1:Falling 0:Low level)
ET0 = 1; //enable timer0 interrupt
EX0 = 1; //enable INT0 interrupt
EA = 1; //open global interrupt switch
mode = 0;//红外线接收清除
while (1)
{
switch(mode)
{
case 1: {mode=0;}break;
case 2: {mode=0;}break;
case 3: {mode=0;}break;
default: break;
}
}
}
void exint0() interrupt 0 //按键一次: 依次发送 引导码 + 地址 + 地址取反 + 数据 + 数据取反
{
static unsigned i;
EX0 = 0; //关闭外部中断,仍可以执行以下程序
for(i = 0; i < 10; i++) // 引导码由9ms低电平及4.5ms高电平组成, 接着是低8位地址码, 高8位地址码
{ // 连发码由9ms低电平及2.25ms高电平组成, 跟着是0.56ms低电平, 然后都是高电平
Delay840us();
if(P32) //检测引导码9ms是否有高电平,有则退出
{
EX0 = 1;
return;
}
}
while(!P32); //等待高电平的到来 注:尽量采用延时来检测,不然可能会进入死循环
Delay840us();
Delay840us(); // 检测连按; 延时2.52ms,检测是否有低电平,有表示按键连按,且退出
Delay840us();
if(!P32)
{
EX0 = 1;
return;
}
while(P32); //等待4.5ms高电平结束,开始接收数据
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
ir_dat_buf[0] = ir_read();
ir_dat_buf[1] = ir_read();
ir_dat_buf[2] = ir_read();
ir_dat_buf[3] = ir_read();
EX0 = 1; //开启外部中断,等下次信号
}
void tm0_isr() interrupt 1 using 1
{
ET0 = 0;//禁止外部中断,防止在接收到数据后处理过程中,再按遥控造成冲突
TL0 = 0x60; //定时4ms
TH0 = 0xC1;
if(((ir_dat_buf[0] == 0x00) && (ir_dat_buf[1] == 0xff))&&((ir_dat_buf[2])== ~(ir_dat_buf[3])))//用户码0x00,0xFF
{
switch(ir_dat_buf[2])
{
case 0x45: {mode=1;}break;
case 0x46: {mode=2;}break;
case 0x47: {mode=3;}break;
default: break;
}
ir_dat_buf[0]=0;//清除红外线接收缓存
ir_dat_buf[1]=0;//清除红外线接收缓存
ir_dat_buf[2]=0;//清除红外线接收缓存
ir_dat_buf[3]=0;//清除红外线接收缓存
}
ET0 = 1; //充许外部中断,处理完数据后再打开外部中断
} |