红外遥控器的解码
实测距离10米时不会错误或需要重复按遥控器 (*^__^*) ……
接收头
(原文件名:接收头.jpg.jpg)
正确解码
(原文件名:20110103426.jpg)
第一行显示的是:地址码+地址码+操作码+操作码反码 接受数据正确时第二行显示OK 旁边的数字是连_发次数
错误解码
(原文件名:20110103427.jpg)
第一行显示的是:地址码+地址码+操作码+操作码反码 接受数据错误时第二行显示error 旁边的数字是连_发次数
51开发板配的万能遥控器
(原文件名:20110103428.jpg)
/*红外遥控接收板*/
/*程序:伍耀斌 13715528667 版本号:2010-8-31*
资源分配:AT89C2051 p3.1用作指示灯驱动(低电平触发)
p1.1~1.6用作继电器(高电平触发)
P1.7用作遥控接收
*/
#include <AT89X52.h>
#define uchar unsigned char //定义为无符号字付 ~~typedef unsigned char uchar;
#define uint unsigned int //~~typedef unsigned int uint;
// 定义说明:
//RAM区定义 全部大写
//数值定义 全部小写
//地址标号 首字母大写,其余小写
//uchar code BitTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //11111110,11111101,11111011,11110111,11101111,11011111
//uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF};
//{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF}; 新板,段位没有加2003
//{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00}; 旧板,段位没有加2003
//uchar DispBuf[4]; //四位扫描
//unsigned char codes[8]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};// 顺时针
//{0x0b,0x09,0x0d,0x0c,0x0e,0x06,0x07,0x03}}; //9,18,36,45,54,63,72,81度 逆时针{0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09}
static uchar ONE; //存放个位数据
static uchar TWO; //存放十位数据
static uchar THREE; //存放百位数据
static uchar FOUR; //存放千位数据
static uchar FIVE;
static uchar SIX;
static uchar SEVEN;
static uchar EIGHT;
static uint TS; //定义为静态变量 Ts=5msX200=1000ms=1S
//static uchar TS;
static uchar SEC; //秒变量
static uchar MIN; //分变量
static uchar HOUR; //小时变量
static uchar KEY; //放键值(做系这里的目的是为了以后可以随时调用)
static uchar SET;
static uchar CODE; //码变量
static uchar counts;
static uchar TSS;
static uchar TP;
static uchar SPstait;
static uchar codeTime;
static uchar HeadCode_Reced;
static uchar HeadCode;
static uchar IrFallEdge;
static uchar Ir_Dealed;
static uchar Irprot_LastState;
static uchar Receive_OK;
static uchar codeCnt;
static uchar vData1;
static uchar vData2;
static uchar vData3;
static uchar vData4;
static uchar vData;
//============================================================
void Time (void); //时间处理
void Light(void); //灯控制子程序
void Sp (void); //蜂鸣器子程序
//============================================================
void main(void)
{
TMOD=0x01; //定时器1用0模式,定时器0用1模式00000001
TH0=(65536-125)/256; //取整数
TL0=(65536-125)%256; //取余数
TH1=(8192-1500)/32; //用正常的8M为2000,但用瑞德的8M经补偿后为
TL1=(8192-1500)%32;
//IE=0x8A;
TR0=1; //开定时器
TR1=1;
EA=1; //开总中断
ET0=1; //开定时器1中断
ET1=1;
//--------付初值区-----------
TS=0;
TSS=0;
SEC=0;
MIN=0;
HOUR=0;
CODE=0;
P3_1=1;
P3_2=1;
P3_0=0;
P1_1=0;
P1_2=0;
P1_3=0;
P1_4=0;
P1_5=0;
P1_6=0;
P1_7=1;
//P3=0; //由于驱动电路是高电平触发,所发未开机前需对端口付0
vData1=vData2=vData3=vData4=0;
//---------------------------
while(1) //嚟度放以后要添加的服务子程序
{
Time (); //时间处理程序
Light();
Sp();
}
}
//=================================================================
/*内中断0 用于计时*/
void Timer0(void) interrupt 1 //开定时器0中断,工作于方式0,中断号为1
{
TH0=(65536-70)/256; //125ms出中断一次.用瑞德的8M经补偿后为70
TL0=(65536-70)%256;
TS++;
TP++;
//P3_1=~P3_1;
if(TS==80) //Ts=125us*80=10ms
{TS=0;
TSS++;
}
//====================================================================================
codeTime++;
if(codeTime>=80)
{
codeTime=80;
HeadCode_Reced=0;//80*125us=10ms时间未接收到低电平信号则清头码接收标志位
Ir_Dealed=0;
}
//-------------------------------------------------
P1_7=1; //先给该口付1
if(P1_7==1)
{
Irprot_LastState=1;//置接收端口为1状态标志
}
//---------------------------------------------------------------------
else //该口出现了低电平证明有可能是收到红外信号
{
if(Irprot_LastState) //出现低电平后如证实之前出现高电平,证明确实是有红外信号
{
Irprot_LastState=0;// 将接收状态清0
if(HeadCode_Reced)//查询是否已接收过头码。有就进入解码,无就进入头码(4.5ms计时)
{
// vData4<<=1;
// if(vData3&0x80){vData4|=0x01;}
// vData3<<=1;
// if(vData2&0x80){vData3|=0x01;}
// vData2<<=1;
// if(vData1&0x80){vData2|=0x01;}
// vData1<<=1;
if(codeTime>15&&codeTime<21)//若头码已接收过,则判断当前接收的是1码或0码 //FTM2->8-<16-11(125*11=1.375,示波器读出0为0.8ms1为1.6ms)
{ //HFJ->15-<21--11(125*15=1.875,示波器读出0为1.2ms1为2.4ms)
vData|=0x01; //两个下降沿之间的时间大于125us*11=1.375ms,条件满足则接收的为1码
}
else if(codeTime>6&&codeTime<12) //HFJ->6-<12
//FTN2->3-<8
{
vData&=0xFE; ; //两个下降沿之间的时间小于125us*12=15ms条件不满足则接收的为0码
}
else
{
vData1=vData2=vData3=vData4=0;
HeadCode_Reced=0;
}
//==================================================
switch(codeCnt)
{case 7: vData1=vData; vData=0;
case 15: vData2=vData; vData=0;
case 23: vData3=vData; vData=0;
case 31: vData4=vData; vData=0;
}
vData<<=1;
//=======================================================
//-------------------------------------------------------------------------
codeCnt++;
if(codeCnt>=32) //一共接收32个信号位
{
codeCnt=0;
if(!Ir_Dealed)
{
Receive_OK=1;
}
}
codeTime=0; //接收完,将时间清0
//vData1=vData2=vData3=vData4=0;
}
else //头码总计时
{
if(codeTime>=80&&codeTime<120) //30 46(FTM2--3.750~5.750计的是低电平+高电平的总时间,即两个下降沿时间.示波器读出是4.9ms)
{ // 80 120(HFJ--10~15ms 计的是低电平+高电平的总时间,即两个下降沿时间.示波器读出是13.6ms)
HeadCode_Reced=1;
}
else
{
HeadCode_Reced=0;
}
codeCnt=0; //如果是第一次进入则将码计时时间codeTime与码位codeCnt清0
codeTime=0;
}
}
}
}
//======================================================================
/*内中断1 用于扫描显示*/
void Timer1(void) interrupt 3 //2m扫描显示程序。开定时器1中断,工作于方式0 "void 函数名() interrupt 中断号 using 工作组"
{//uchar tmp; // 中断号命名:外中断0为0、内部时钟中断0为1、外中断1为2、内部时钟中断1为3
//static uchar COUNT; //原为这个,现换下面的
TH1=(8192-1500)/32; //用正常的8M为2000,但用瑞德的8M经补偿后为
TL1=(8192-1500)%32;
}
//================================================================
/*时间处理子程序*/
void Time (void)
{if(TSS==100) //TSS=10msX100=1000ms=1S 修定为91
{TSS=0;
SEC++;
//P3_0=~P3_0;
}
if(SEC==60)
{SEC=0;
MIN++;
}
if(MIN==60)
{MIN=1;
HOUR++;
}
if(HOUR==13)
{HOUR=1;
}
}
//===========================================================================
//灯控制
void Light (void)
{
if(vData1==0x08&&vData4==0x17)
{P3_1=1; P1_6=0;P1_5=0;P1_4=0;P1_3=0;P1_2=0;}
else if(vData1==0x08&&vData4==0x1F)
//{P3_1=0;P1_5=1;}
{P1_7=0;P3_0=1;}
else if(vData1==0x08&&vData4==0x9F)
//{P3_1=1; P1_5=0;}
{P1_7=1;P3_0=0;}
else if(vData1==0x08&&vData4==0xC7)
{P3_1=0;P1_4=1;}
else if(vData1==0x08&&vData4==0x57)
{P3_1=1;P1_4=0;}
else if(vData1==0x08&&vData4==0x3F)
{P3_1=0;P1_6=1;}
else if(vData1==0x08&&vData4==0x5F)
{P3_1=1;P1_6=0;}
}
void Sp (void)
{ if(SPstait==1)
{if(TP==2) //Ts=125us*80=10ms
{TS=0;
P3_2=~P3_2;
}
}
}
/*红外遥控接收板*/
/*程序:伍耀斌 13715528667 版本号:2010-8-31*
资源分配:AT89C2051 p3.1用作指示灯驱动(低电平触发)
p1.1~1.6用作继电器(高电平触发)
P1.7用作遥控接收
*/
#include <AT89X52.h>
#define uchar unsigned char //定义为无符号字付 ~~typedef unsigned char uchar;
#define uint unsigned int //~~typedef unsigned int uint;
// 定义说明:
//RAM区定义 全部大写
//数值定义 全部小写
//地址标号 首字母大写,其余小写
//uchar code BitTab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; //11111110,11111101,11111011,11110111,11101111,11011111
//uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF};
//{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xFF}; 新板,段位没有加2003
//{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00}; 旧板,段位没有加2003
//uchar DispBuf[4]; //四位扫描
//unsigned char codes[8]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09};// 顺时针
//{0x0b,0x09,0x0d,0x0c,0x0e,0x06,0x07,0x03}}; //9,18,36,45,54,63,72,81度 逆时针{0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09}
static uchar ONE; //存放个位数据
static uchar TWO; //存放十位数据
static uchar THREE; //存放百位数据
static uchar FOUR; //存放千位数据
static uchar FIVE;
static uchar SIX;
static uchar SEVEN;
static uchar EIGHT;
static uint TS; //定义为静态变量 Ts=5msX200=1000ms=1S
//static uchar TS;
static uchar SEC; //秒变量
static uchar MIN; //分变量
static uchar HOUR; //小时变量
static uchar KEY; //放键值(做系这里的目的是为了以后可以随时调用)
static uchar SET;
static uchar CODE; //码变量
static uchar counts;
static uchar TSS;
static uchar TP;
static uchar SPstait;
static uchar codeTime;
static uchar HeadCode_Reced;
static uchar HeadCode;
static uchar IrFallEdge;
static uchar Ir_Dealed;
static uchar Irprot_LastState;
static uchar Receive_OK;
static uchar codeCnt;
static uchar vData1;
static uchar vData2;
static uchar vData3;
static uchar vData4;
static uchar vData;
//============================================================
void Time (void); //时间处理
void Light(void); //灯控制子程序
void Sp (void); //蜂鸣器子程序
//============================================================
void main(void)
{
TMOD=0x01; //定时器1用0模式,定时器0用1模式00000001
TH0=(65536-125)/256; //取整数
TL0=(65536-125)%256; //取余数
TH1=(8192-1500)/32; //用正常的8M为2000,但用瑞德的8M经补偿后为
TL1=(8192-1500)%32;
//IE=0x8A;
TR0=1; //开定时器
TR1=1;
EA=1; //开总中断
ET0=1; //开定时器1中断
ET1=1;
//--------付初值区-----------
TS=0;
TSS=0;
SEC=0;
MIN=0;
HOUR=0;
CODE=0;
P3_1=1;
P3_2=1;
P3_0=0;
P1_1=0;
P1_2=0;
P1_3=0;
P1_4=0;
P1_5=0;
P1_6=0;
P1_7=1;
//P3=0; //由于驱动电路是高电平触发,所发未开机前需对端口付0
vData1=vData2=vData3=vData4=0;
//---------------------------
while(1) //嚟度放以后要添加的服务子程序
{
Time (); //时间处理程序
Light();
Sp();
}
}
//=================================================================
/*内中断0 用于计时*/
void Timer0(void) interrupt 1 //开定时器0中断,工作于方式0,中断号为1
{
TH0=(65536-70)/256; //125ms出中断一次.用瑞德的8M经补偿后为70
TL0=(65536-70)%256;
TS++;
TP++;
//P3_1=~P3_1;
if(TS==80) //Ts=125us*80=10ms
{TS=0;
TSS++;
}
//====================================================================================
codeTime++;
if(codeTime>=80)
{
codeTime=80;
HeadCode_Reced=0;//80*125us=10ms时间未接收到低电平信号则清头码接收标志位
Ir_Dealed=0;
}
//-------------------------------------------------
P1_7=1; //先给该口付1
if(P1_7==1)
{
Irprot_LastState=1;//置接收端口为1状态标志
}
//---------------------------------------------------------------------
else //该口出现了低电平证明有可能是收到红外信号
{
if(Irprot_LastState) //出现低电平后如证实之前出现高电平,证明确实是有红外信号
{
Irprot_LastState=0;// 将接收状态清0
if(HeadCode_Reced)//查询是否已接收过头码。有就进入解码,无就进入头码(4.5ms计时)
{
// vData4<<=1;
// if(vData3&0x80){vData4|=0x01;}
// vData3<<=1;
// if(vData2&0x80){vData3|=0x01;}
// vData2<<=1;
// if(vData1&0x80){vData2|=0x01;}
// vData1<<=1;
if(codeTime>15&&codeTime<21)//若头码已接收过,则判断当前接收的是1码或0码 //FTM2->8-<16-11(125*11=1.375,示波器读出0为0.8ms1为1.6ms)
{ //HFJ->15-<21--11(125*15=1.875,示波器读出0为1.2ms1为2.4ms)
vData|=0x01; //两个下降沿之间的时间大于125us*11=1.375ms,条件满足则接收的为1码
}
else if(codeTime>6&&codeTime<12) //HFJ->6-<12
//FTN2->3-<8
{
vData&=0xFE; ; //两个下降沿之间的时间小于125us*12=15ms条件不满足则接收的为0码
}
else
{
vData1=vData2=vData3=vData4=0;
HeadCode_Reced=0;
}
//==================================================
switch(codeCnt)
{case 7: vData1=vData; vData=0;
case 15: vData2=vData; vData=0;
case 23: vData3=vData; vData=0;
case 31: vData4=vData; vData=0;
}
vData<<=1;
//=======================================================
//-------------------------------------------------------------------------
codeCnt++;
if(codeCnt>=32) //一共接收32个信号位
{
codeCnt=0;
if(!Ir_Dealed)
{
Receive_OK=1;
}
}
codeTime=0; //接收完,将时间清0
//vData1=vData2=vData3=vData4=0;
}
else //头码总计时
{
if(codeTime>=80&&codeTime<120) //30 46(FTM2--3.750~5.750计的是低电平+高电平的总时间,即两个下降沿时间.示波器读出是4.9ms)
{ // 80 120(HFJ--10~15ms 计的是低电平+高电平的总时间,即两个下降沿时间.示波器读出是13.6ms)
HeadCode_Reced=1;
}
else
{
HeadCode_Reced=0;
}
codeCnt=0; //如果是第一次进入则将码计时时间codeTime与码位codeCnt清0
codeTime=0;
}
}
}
}
//======================================================================
/*内中断1 用于扫描显示*/
void Timer1(void) interrupt 3 //2m扫描显示程序。开定时器1中断,工作于方式0 "void 函数名() interrupt 中断号 using 工作组"
{//uchar tmp; // 中断号命名:外中断0为0、内部时钟中断0为1、外中断1为2、内部时钟中断1为3
//static uchar COUNT; //原为这个,现换下面的
TH1=(8192-1500)/32; //用正常的8M为2000,但用瑞德的8M经补偿后为
TL1=(8192-1500)%32;
}
//================================================================
/*时间处理子程序*/
void Time (void)
{if(TSS==100) //TSS=10msX100=1000ms=1S 修定为91
{TSS=0;
SEC++;
//P3_0=~P3_0;
}
if(SEC==60)
{SEC=0;
MIN++;
}
if(MIN==60)
{MIN=1;
HOUR++;
}
if(HOUR==13)
{HOUR=1;
}
}
//===========================================================================
//灯控制
void Light (void)
{
if(vData1==0x08&&vData4==0x17)
{P3_1=1; P1_6=0;P1_5=0;P1_4=0;P1_3=0;P1_2=0;}
else if(vData1==0x08&&vData4==0x1F)
//{P3_1=0;P1_5=1;}
{P1_7=0;P3_0=1;}
else if(vData1==0x08&&vData4==0x9F)
//{P3_1=1; P1_5=0;}
{P1_7=1;P3_0=0;}
else if(vData1==0x08&&vData4==0xC7)
{P3_1=0;P1_4=1;}
else if(vData1==0x08&&vData4==0x57)
{P3_1=1;P1_4=0;}
else if(vData1==0x08&&vData4==0x3F)
{P3_1=0;P1_6=1;}
else if(vData1==0x08&&vData4==0x5F)
{P3_1=1;P1_6=0;}
}
void Sp (void)
{ if(SPstait==1)
{if(TP==2) //Ts=125us*80=10ms
{TS=0;
P3_2=~P3_2;
}
}
}
-----------------------------------------------------------------------
1、51的芯片一般只有两个外中断!外中断一般是用来做通信等高时序要求的。
2、对于家电类产品(如风扇、电暧器)在布板时对芯片的端口引出的位置有时可能很有要求(如板小,或者走线不便),所以如果只能用外中断来做接收端口是不太可能的。
3、我上述用的中断做法是采用查询方式(请细睇程序),即是在接收信号时不用在主程序中做延时子程序(浪费系统时间)。
4、我是在顺德瑞德电子开发部做电控板设计(主要客户有:美的生活电器、美的环境、九阳、东菱、山瑚风扇),或者你可能随便拆台如“美的”的风扇或者电暧器,看一看就明白。他们多用合泰或松瀚或三星的9454单片机。有时连复位口也用上来做遥控接收。反正我们公司开发部就没有一人会用外中断口来做遥控接收!
一周热门 更多>