原创 第四十课 红外遥控之二 牛刀小试(最简单的程序)

2009-6-9 21:18 5545 18 18 分类: MCU/ 嵌入式

第四十课 红外遥控之二 牛刀小试(最简单的程序)


在学习本节前,希望能对上节H-3010X系列遥控的编码有所了解


程序讲解:


1、红外遥控头文件(IRDA.H)


/*--------------------------------------------------------------*/
//文件: IRDA.H
//遥控器: H-3010X - CHUNGHOP - 34个按键  红外接收头:TL1838
//编码: RC-5协议,
// 双相位编码发送,
//(0->1)为1, (1->0)为0
//周期T = 1.688ms,
//解码: 定时采样
//单片机: STC89C51RC
//晶振: 12MHz
//红外接收:1838
//日期: 2009-5-9
//时间: 17:29 



/*--------------------------------------------------------------*/
#ifndef __IRDA_H__   //防止重复定义
#define __IRDA_H__



/*--------------------------------------------------------------*/
//红外接口定义 对应开发板硬件
sbit IRDA = P3^2;   //外部中断INT0



/*--------------------------------------------------------------*/
//变量定义
#define  D_ERROR   0          //容错值 
#define  T_1 80                     //1.688ms
#define  T_1_4 (T_1/4)         //422
unsigned char T20_C;            //20us计数次数
unsigned int  IRDA_dat;         //13位数据
unsigned char IRDA_dat_bit; //13bits
unsigned char IRDA_cmd;     //指令码
unsigned char IRDA_sys;       //系统码
unsigned char IRDA_con;      //长按/双击
bit IRDA_ok;                        //接收数据有效



/*--------------------------------------------------------------*/
//按键键码 (本程序没用到)
/*unsigned char code key_code[] = {
                             0x0c,   //                     0,
 0x26,     0x23,     0x2d,   //  1,      2,        3,
0x01, 0x02, 0x03, 0x04,  //  4,   5,     6,   7,
0x05, 0x06, 0x07, 0x08,  //  8,   9,    10, 11,
0x09, 0x00, 0x0a, 0x1e,  //  12, 13,   14, 15,
0x0e, 0x29, 0x2c, 0x2b,  //  16, 17,   18, 19,
 0x10,     0x0f,       0x20,  //  20,     21,    22,
 0x11,     0x0d,      0x21,  //  23,     24,    25,
0x12, 0x14, 0x1c, 0x38,   //  26, 27,  28, 29,
0x13, 0x15, 0x1d, 0x3f     //  30, 31,  32, 33,
};
#define key_code_num sizeof(key_code) //取得键码大小



/*--------------------------------------------------------------*/
//宏定义---便于理解和阅读
#define Close_IRDA EX0 = 0; //关闭中断,等待任务执行完毕
#define Open_IRDA EX0 = 1; //开启中断,接收遥控按键



/*--------------------------------------------------------------*/
//函数声明
void T0_init(void);       //定时器0初始化
void INT0_init(void);   //外部中断0初始化
void IRDA_init(void);   //遥控接收初始化



/*--------------------------------------------------------------*/
//定时器0初始化(让单片机采集数据与接收头受到的串行数据同步)
void T0_init(void)
{
    TMOD |= 0x02;    //自动重新装载
    TH0  = 0xeb;         //20us
    TL0  = 0xeb;          //20us
    IE  |= 0x82;            //EA = 1; ET0 = 1;
    PT0  = 1;                //优先级
    TR0  = 0;                //关闭
}



/*--------------------------------------------------------------*/
//定时器0计数
void T0_intservice(void) interrupt 1
{
 T20_C++;              //20us
}



/*--------------------------------------------------------------*/
//外部中断0初始化
void INT0_init(void)
{
    EX0 = 1;           //外部中断INT0
    IT0 = 0;             //低电平触发
}



/*--------------------------------------------------------------*/
//外部中断0遥控接收
//起始位: 1.5位  1,1
//控制字:  1 位  x
//用户码:  5 位  0,0,0,0,0
//指令码:  6 位  x,x,x,x,x,x
//数据长度: 14位  1,1,x,0,0,0,0,0,x,x,x,x,x,x
void INT0_intservice(void) interrupt 0
{
 EX0 = 0;              //关闭外部中断
 TR0 = 1;              //启动定时器
 T20_C = 0;          //清计数器
 IRDA_dat = 0;     //初始化数据
 while(T20_C < T_1_4 + D_ERROR)  //第一位起始位为1(IRDA = 0)
 {
  if(IRDA)             //防止自然误触发!!!
  {
   TR0 = 0;            //关闭定时器
   EX0 = 1;            //启动外部中断
   return;                 //退出中断服务程序
  }
 }                          //第一位起始位丢弃
 T20_C = 0;          //清计数器
 IRDA_dat_bit = 0;    //接收数据位清0
 while(IRDA_dat_bit < 13)  //接收13位数据
 {
  if(T20_C > T_1 + D_ERROR)   //1.688ms
  { 
   IRDA_dat <<= 1;      //接收到的数据为高到低
   IRDA_dat |= IRDA;  //接收一位
   T20_C = 0;               //清计数器
   IRDA_dat_bit++;      //接收数据位++
  }
 }
 TR0 = 0;                     //关闭定时器
 IRDA_dat = ~IRDA_dat;   //接收数据取反还原
 IRDA_sys = (unsigned char)((IRDA_dat & 0x07c0)>>6);  //取得系统码
 if((IRDA_dat & 0x1000) && (IRDA_sys == 0x00))          //接收数据有效
 {                   //第二个起始位1    //系统码00000
  IRDA_cmd = (unsigned char)(IRDA_dat & 0x3f);             //取得指令码
  IRDA_con = (bit)(IRDA_dat & 0x0800);                          //取得控制字
  IRDA_ok  = 1;                                                 //置位接收有效标志位        
 }
 else     //纠错处理
 {
  IRDA_cmd = 0;                 //全部清0
  IRDA_con = 0;
  IRDA_ok  = 0;
 }
 while(!IRDA);   //等待IRDA变为1,否则又进入中断服务了!!!
 EX0 = 1;          //打开外部中断
}



/*--------------------------------------------------------------*/
//遥控接收初始化
void IRDA_init(void)
{
 T0_init();      //定时器0初始化
 INT0_init();  //外部中断0初始化
}



/*--------------------------------------------------------------*/
//按键检测  将指令码转化为按键键值(用户自定义,本程序没用到)
/*unsigned char IRDA_key_code(void)
{
 unsigned char i;
 i = 34;              //默认键值,即没有按键按下时返回值
 if(IRDA_ok)    //有按键按下
 {
  EX0 = 0;        //关闭中断,等待以下任务执行完毕
  for(i = 0; i < key_code_num; i++)
  {     //查表-将指令码转化为按键键值(用户自定义)
   if(key_code == IRDA_cmd) break;
  }
  IRDA_ok = 0;  //清接收有效标志位
//  speaker();        //蜂鸣器指示
  EX0 = 1;           //开启中断,接收遥控按键
 }
 return i;
}
/*--------------------------------------------------------------*/
#endif


2、主程序:


/*--------------------------------------------------------------*/
#include <AT89X52.H>
#include "Beep.H"
#include "IRDA.H"          //红外接受处理头文件


/*--------------------------------------------------------------*/
//延时50000+0us 函数定义
void delay50ms(void)
{
    unsigned char i,j,k;
    for(i=165;i>0;i--)
    for(j=60;j>0;j--)
    for(k=1;k>0;k--);
}


/*--------------------------------------------------------------*/
void main(void)

 IRDA_init();
 while(1)
 {
  if(IRDA_ok)    //检测按键
  {
   IRDA_ok = 0;
   Close_IRDA   //关闭红外,等待以下任务执行完毕 
   speaker();
   P1 = ~IRDA_cmd;  //测试指令码
//   P1 = ~IRDA_sys;  //测试用户码
//   P1 = ~IRDA_con;  //测试控制字
  }
  Open_IRDA            //开启红外,接收遥控按键
  delay50ms();
 }
}


本节重点


1、相关说明


红外接受头TL1838的数据输出口与单片机P3^2口相接(外部中断INT0设为低电平触发),当遥控器发出高电平时,接收头接收到后,输出为低(这就是把外部中断INT0设为低电平触发的原因)。


2、整体思想


1、当外部中断触发时(若持续时间小于1/4个周期,则被认为无效),且持续时间大于一个周期,则对中断口(P3.2)数据进行处理,重新判断外部中断时间是否大于一个周期,若大于则再进行处理,直到接受到的13位数据(开始的半位数据忽略了)处理完!

2、先校验接收到的数据是否符合编码标准,再对接收到的数据进行取反还原(因为遥控器发出高电平时,接收头接收到后,输出为低。)


3、将接收到的数据分到对应的部分主要是以下几位:


1)起始码部分——1.5 位(忽略前面0.5位,即一个逻辑“1”);数据的第12位


2)控制码部分—1 位;数据的第11位


3)系统码部分—5 位:00000;(数据的第6~10位)<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


4)指令码部分—6 位。(数据的第0~5位)


4、主程序就是将处理好的各位数据送到P1口让LED显示,这样我们就可以清晰的看到遥控器各个按键对应的编码的各个部分数据了,从而给我们的解码带来方便!


相关程序:https://static.assets-stash.eet-china.com/album/old-resources/2009/6/9/6211c553-618a-4000-9e4b-302560d8200d.rar

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
18
关闭 站长推荐上一条 /3 下一条