📄 p87lpc762+nb9148红外线遥控.c
字号:
//P87LPC762+NB9148红外线遥控
//2006年8月
//Philips公司的51LPC系列
//NB9148为遥控发射专用电路,16引脚可形成18只按键
//NB9149为遥控接收专用电路,可完成10个功能控制
//NB9150为遥控接收专用电路,可完成18个功能控制
//本实验的遥控接收采用通用的红外线接收头
//遥控接收接8脚P1_4的INT1输入口;晶振为11.0592MHz
#include <REG768.H> //87LPC768寄存器定义头文件
#include <stdio.h>
#include <intrins.h>
#define REDINT 0x06 //红外线间隔
//存放消息标志的可位寻址字节Message,Message=NULL时无任消息
unsigned char bdata Message;
//在接收过程中置位,检测标置位Get可以有效防止其它进程干扰接收,防止数据丢失
sbit RedMsg =Message^0; //红外遥控消息
sbit RedRead=Message^1; //位接收过程标志
sbit RedBit =Message^2; //接收到的位值
sbit RSend =Message^3; //红外接收中重新发送标志
//存放遥控的字数据,低4位存放接收到的bit的位移,高12位从低到高存放接收到的bit
unsigned char bdata RedDataL,RedDataH;
//RedDataH字节低6位代表指令,只有一个1,C1~C3是用户码,H表示连续,S1S2分别表示第一二组单发
sbit RedData0=RedDataL^4; //C1
sbit RedData1=RedDataL^5; //C2
sbit RedData2=RedDataL^6; //C3
sbit RedData3=RedDataL^7; //H
sbit RedData11=RedDataH^0; //D6
sbit RedData10=RedDataH^1; //D5
sbit RedData9=RedDataH^2; //D4
sbit RedData8=RedDataH^3; //D3
sbit RedData7=RedDataH^4; //D2
sbit RedData6=RedDataH^5; //D1
sbit RedData5=RedDataH^6; //S2
sbit RedData4=RedDataH^7; //S1
unsigned char bdata State; //状态字节
sbit RedControl=State^6; //遥控状态
//定时器T00的高位定时参数为Timer,定时256*Timer+(80--336)个周期,共139Timer+(43~
//182)us<37ms。定时器T01的高位定时节参数为nTimer,定时256*nTimer+(24~280)个周期,
//139nTimer+(13~152)us<9.1s。RedCon存放红外接收时的载波计数
unsigned char data RedCon,Timer;
unsigned int nTimer; //定时整型参数
void Count0(void) interrupt 1 using 3 //定时器T00中断,最大定时37ms
{if(Timer!=0) //检测定时器T00的扩展高位
{Timer--;
return;
}
}
//INT1用于红外解码状态遥控解码数据处理,nTimer=1定时152~291us
void Inte1() interrupt 2 using 2
{for(nTimer=8;nTimer>1;nTimer--); //使处理周期达到51机器周期=27.7us使得RedCon<32
if(RedRead) RedCon++; //0信号宽度a=420us,1信号宽度a=1260us,周期4a=1680us
else //开始计数或者重新发送时开始计数
{RedBit=0; //复位接收位
RedCon=0; //复位载波计数
RedRead=1; //置位位接收标志
if(!ET1) //首次接收时没有启动定时器T01接收第一个位
{TF1=0; //复位定时器T01溢出标志
ET1=1; //启动T01定时
RedDataL=0; //复位红外数据
RedDataH=0; //复位红外数据
RSend=0; //复位重新发送标志
}
}
}
void Count1(void) interrupt 3 using 3 //定时器T01中断,最大定时9.1s
{if(nTimer!=0) //检测定时器T01的扩展高位
{nTimer--;
return;
}
ET1=0; //关闭T01定时
if(RedRead) //红外接收状态
{if((RedDataL&0xF)==12) //第一阶段接收已经结束
{RSend=1; //置位重新发送标志以便校验
RedDataL&=0xF0; //复位位指针以便校验
}
if(RedCon>27-REDINT&&RedCon<27+REDINT)
RedBit=1;
else RedBit=0; //低电平计数9表示0 27表示1
if(RSend) //检验重复发送的数据是否与第一次符合
{switch(RedDataL&0xF)
{case 0: //检验重复发送的第1位数据
if(RedBit!=RedData0) goto RClear;
break;
case 1: //检验重复发送的第2位数据
if(RedBit!=RedData1) goto RClear;
break;
case 2: //检验重复发送的第3位数据
if(RedBit!=RedData2) goto RClear;
break;
case 3: //检验重复发送的第4位数据
if(RedBit!=RedData3) goto RClear;
break;
case 4: //检验重复发送的第5位数据
if(RedBit!=RedData4) goto RClear;
break;
case 5: //检验重复发送的第6位数据
if(RedBit!=RedData5) goto RClear;
break;
case 6: //检验重复发送的第7位数据
if(RedBit!=RedData6) goto RClear;
break;
case 7: //检验重复发送的第8位数据
if(RedBit!=RedData7) goto RClear;
break;
case 8: //检验重复发送的第9位数据
if(RedBit!=RedData8) goto RClear;
break;
case 9: //检验重复发送的第10位数据
if(RedBit!=RedData9) goto RClear;
break;
case 10: //检验重复发送的第11位数据
if(RedBit!=RedData10) goto RClear;
break;
case 11: //检验重复发送的第12位数据
if(RedBit!=RedData11) goto RClear;
RedMsg=1; //接受到经过检验正确的编码后置位遥控消息
RedBit=0; //复位接收位
RSend=0; //复位重新发送标志
RedRead=0; //复位接收过程标志
RedCon=0; //复位载波计数
return;
default: //重复发送的数据多于12位时判断为错误
goto RClear;
}
}
else
{switch(RedDataL&0xF)
{case 0: //保存首次发送的第1位数据
RedData0=RedBit;
break;
case 1: //保存首次发送的第2位数据
RedData1=RedBit;
break;
case 2: //保存首次发送的第3位数据
RedData2=RedBit;
break;
case 3: //保存首次发送的第4位数据
RedData3=RedBit;
break;
case 4: //保存首次发送的第5位数据
RedData4=RedBit;
break;
case 5: //保存首次发送的第6位数据
RedData5=RedBit;
break;
case 6: //保存首次发送的第7位数据
RedData6=RedBit;
break;
case 7: //保存首次发送的第8位数据
RedData7=RedBit;
break;
case 8: //保存首次发送的第9位数据
RedData8=RedBit;
break;
case 9: //保存首次发送的第10位数据
RedData9=RedBit;
break;
case 10: //保存首次发送的第11位数据
RedData10=RedBit;
break;
case 11: //保存首次发送的第12位数据
RedData11=RedBit;
break;
default: //首次发送的数据多于12位时判断为错误
goto RClear;
}
}
RedDataL++; //位位移加1
RedBit=0; //复位接收位
RedRead=0; //复位接收过程标志
RedCon=0; //复位载波计数
nTimer=423; //用定时140a 检测同步信号208a
TF1=0; //复位定时器T01益出标志
ET1=1; //启动定时器
}
else if(RSend) //在位接收没有结束时发生定时中断需要复位接收信息(同步)
{RClear:
RedDataL=0; //复位红外数据
RedDataH=0; //复位红外数据
RedBit=0; //复位接收位
RedRead=0; //复位接收过程标志
RSend=0; //复位重新发送标志
RedCon=0; //复位载波计数
ET1=0; //关闭T01定时
}
}
void main(void)
{
IEN0=0x14; //只打开INT1中断
WDRST=0x1E; //看门狗清0
WDRST=0xE1;
WDCON=0x12; //40-90ms看门狗(>最大延时37ms)
TCON=0x40; //定时器1开始工作,INT1低电平触发
TMOD=0x23; //定时器0扩展成两个8位定时器T00和T01用于同步控制
if((WDCON&0x30)!=0x30) //看门狗陷阱复位时无需初始化
{Message=0; //无消息
State=0; //正常复位无任何状态
}
while(1) //消息循环
{WDRST=0x1E; //看门狗清0
WDRST=0xE1;
EX1=RedControl; //设置遥控中断INT1
if(RedMsg) //执行遥控指令
{EX1=0; //在指令没有处理完之前不能重复中断
switch(RedDataH) //这里加入红外指令的控制过程
{case 0x82: //Channel 1
break;
case 0xA0: //Channel 2
break;
}
EX1=1;
RedDataL=0; //复位红外数据
RedDataH=0; //复位红外数据
RedMsg=0; //复位红外遥控消息
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -