实验9 红外接收单片机解码

 

1.实现对红外遥控器的解码,并用其实现一些简单的控制

 

/*******************************************************************************

*         lcd1602显示遥控器接p3.2                                             *                                        *

*        按下上面的按键分辨显示遥控器上面的按键数据                            *                                                            *

*       连接方法:使用红外功能时 J1跳线短接                                    *                                     *

********************************************************************************/

 

#include <reg51.h>

#include <intrins.h>

 

#define uchar unsigned char

#define uint  unsigned int

uchar code Number[]="0     /1     /2     /3     /4     /5     /6     /7     /8     /9     ";

uchar Order[]="switch/mode  /quiet /start /<     />     /eq    /vol-  /vol+  /rpt   /u/sd  ";

#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

 

void delay_140us(uchar x);  //x*0.14MS

void delay1(int ms);

void beep();

 

sbit IRIN = P3^2;         //红外接收器数据线

sbit BEEP = P1^5;         //蜂鸣器驱动线

sbit RELAY= P1^4;         //继电器驱动线

 

uchar IRCOM[7];

 

sbit LCD_RS = P2^6;            

sbit LCD_RW = P2^5;

sbit LCD_EN = P2^7;

 

uchar code  cdis1[]={" Red Control "};

uchar code  cdis2[]={"IR-CODE:"};

 

/*******************************************************************/

/*                                                                 */

/*检查LCD忙状态                                                    */

/*lcd_busy1时,忙,等待。lcd-busy0,闲,可写指令与数据。      */

/*                                                                 */

/*******************************************************************/

bit lcd_busy()

 {                         

    bit result;

    LCD_RS =0;

    LCD_RW =1;

    LCD_EN =1;

    delayNOP();

    result =(bit)(P0&0x80);

    LCD_EN =0;

    return(result);

 }

 

/*******************************************************************/

/*                                                                 */

/*写指令数据到LCD                                                  */

/*RS=LRW=LE=高脉冲,D0-D7=指令码。                             */

/*                                                                 */

/*******************************************************************/

void lcd_wcmd(uchar cmd)

{                         

   while(lcd_busy());

    LCD_RS =0;

    LCD_RW =0;

    LCD_EN =0;

    _nop_();

    _nop_();

    P0 = cmd;

    delayNOP();

    LCD_EN =1;

    delayNOP();

    LCD_EN =0; 

}

 

/*******************************************************************/

/*                                                                 */

/*写显示数据到LCD                                                  */

/*RS=HRW=LE=高脉冲,D0-D7=数据。                               */

/*                                                                 */

/*******************************************************************/

 

void lcd_wdat(uchar dat)

{                         

   while(lcd_busy());

    LCD_RS =1;

    LCD_RW =0;

    LCD_EN =0;

    P0 = dat;

    delayNOP();

    LCD_EN =1;

    delayNOP();

    LCD_EN =0;

}

 

/*******************************************************************/

/*                                                                 */

/*  LCD初始化设定                                                  */

/*                                                                 */

/*******************************************************************/

 

void lcd_init()

{

    delay1(15);                  

    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据

    delay1(5);

    lcd_wcmd(0x38);        

    delay1(5);

    lcd_wcmd(0x38);        

    delay1(5);

 

    lcd_wcmd(0x0c);      //显示开,关光标

    delay1(5);

    lcd_wcmd(0x06);      //移动光标

    delay1(5);

    lcd_wcmd(0x01);      //清除LCD的显示内容

    delay1(5);

}

 

/*******************************************************************/

/*                                                                 */

/*  设定显示位置                                                   */

/*                                                                 */

/*******************************************************************/

 

void lcd_pos(uchar pos)

{                         

  lcd_wcmd(pos |0x80);  //数据指针=80+地址变量

}

 

/*******************************************************************/

main()

{

   uchar m;

   

    IRIN=1;                    //I/O口初始化

    BEEP=1;

    RELAY=1;

   

    delay1(10);                 //延时

    lcd_init();                //初始化LCD            

       

    lcd_pos(0);                //设置显示位置为第一行的第1个字符

 

     m =0;

    while(cdis1[m]!='\0')

     {                         //显示字符

       lcd_wdat(cdis1[m]);

       m++;

     }

 

    lcd_pos(0x40);             //设置显示位置为第二行第1个字符

     m =0;

    while(cdis2[m]!='\0')

     {

       lcd_wdat(cdis2[m]);      //显示字符

       m++;

     }

 

 

    IE =0x81;                 //允许总中断中断,使能 INT0 外部中断

    TCON =0x01;               //触发方式为脉冲负边沿触发

 

   while(1);

 

}//end main

/**********************************************************/

void IR_IN() interrupt 0 using 0

{

  unsignedchar i,GroupIndex,BitIndex,Count140us=0;

     EX0 =0;            //关掉外部中断防止中断的再次发生进入检测引导码阶段(9ms的低电平4.5ms的高电平)

     delay_140us(15);

     if(IRIN==1)

     { EX0 =1;          //9ms的检测检测结束从新打开外部中断

       return;

      }

                           //确认IR信号出现

  while(!IRIN)            //IR变为高电平,跳过9ms的前导低电平信号。

    {delay_140us(1);}

 

     for(GroupIndex=0;GroupIndex<4;GroupIndex++)         //收集四组数据

     {

         for(BitIndex=0;BitIndex<8;BitIndex++)        //每组数据有8

         {

          while(IRIN)            // IR 变为低电平,跳过4.5ms的前导高电平信号。

            {delay_140us(1);}

           while(!IRIN)          // IR 变为高电平

            {delay_140us(1);}

            while(IRIN)           //计算IR高电平时长

             {

              delay_140us(1);

              Count140us++;          

              if(Count140us>=30){

                   EX0=1;

                   return;           //0.14ms计数过长自动离开。

              }

             }                        //高电平计数完毕               

            IRCOM[GroupIndex]=IRCOM[GroupIndex]>>1;                  //数据最高位补“0”

            if(Count140us>=8){IRCOM[GroupIndex]= IRCOM[GroupIndex]|0x80;}  //数据最高位补“1”

            Count140us=0;

         }//end for BitIndex

     }//end for GroupIndex

  

   if(IRCOM[2]!=~IRCOM[3])       // 判断有没有误码(有责放弃没有判断键码)

   { EX0=1;

     return;

    }

    //PrintDataByKey()

     switch(IRCOM[2])

     {                          // 显示遥控上的字符按键

        case0x45:

            lcd_pos(0x49);

            for(i=0;i<=5;i++)

            lcd_wdat(Order[i]);

            break;

       case0x46:

            lcd_pos(0x49);

            for(i=7;i<=12;i++)

            lcd_wdat(Order[i]);

            break;

       case0x47:

            lcd_pos(0x49);

            for(i=14;i<=19;i++)

            lcd_wdat(Order[i]);

            break;

       case0x44:

            lcd_pos(0x49);

            for(i=21;i<=26;i++)

            lcd_wdat(Order[i]);

            break;

       case0x40:

            lcd_pos(0x49);

            for(i=28;i<=33;i++)

            lcd_wdat(Order[i]);

            break;

       case0x43:

            lcd_pos(0x49);

            for(i=35;i<=40;i++)

            lcd_wdat(Order[i]);

            break;

       case0x07:

            lcd_pos(0x49);

            for(i=42;i<=47;i++)

            lcd_wdat(Order[i]);

            break;

       case0x15:

            lcd_pos(0x49);

            for(i=49;i<=54;i++)

            lcd_wdat(Order[i]);

            break;

        case0x09:

            lcd_pos(0x49);

            for(i=56;i<=61;i++)

            lcd_wdat(Order[i]);

            break;

       case0x19:

            lcd_pos(0x49);

            for(i=63;i<=68;i++)

            lcd_wdat(Order[i]);

            break;

       case0x0d:

            lcd_pos(0x49);

            for(i=70;i<=75;i++)

            lcd_wdat(Order[i]);

            break; 

       case0x16:                     //显示遥控上得数字

            lcd_pos(0x49);

            for(i=0;i<=5;i++)

            lcd_wdat(Number[i]);

            break;

       case0x0c:  

            lcd_pos(0x49);

            for(i=7;i<=12;i++)

            lcd_wdat(Number[i]);

            break;

       case0x18:

            lcd_pos(0x49);

            for(i=14;i<=19;i++)

            lcd_wdat(Number[i]);

            break;

       case0x5e:

            lcd_pos(0x49);

            for(i=21;i<=26;i++)

            lcd_wdat(Number[i]);

            break;

       case0x08:

            lcd_pos(0x49);

            for(i=28;i<=33;i++)

            lcd_wdat(Number[i]);

            break;

       case0x1c:

            lcd_pos(0x49);

            for(i=35;i<=40;i++)

            lcd_wdat(Number[i]);

            break;

       case0x5a:

            lcd_pos(0x49);

            for(i=42;i<=47;i++)

            lcd_wdat(Number[i]);

            break;

        case0x42:

            lcd_pos(0x49);

            for(i=49;i<=54;i++)

            lcd_wdat(Number[i]);

            break;

       case0x52:

            lcd_pos(0x49);

            for(i=56;i<=61;i++)

            lcd_wdat(Number[i]);

            break;

       case0x4a:

            lcd_pos(0x49);

            for(i=63;i<=68;i++)

            lcd_wdat(Number[i]);

            break;

     }

     beep();

     EX0 =1;

}

 

/**********************************************************/

void beep()

{

  unsignedchar i;

  for(i=0;i<100;i++)

   {

       delay_140us(4);

       BEEP=!BEEP;                 //BEEP取反

   }

  BEEP=1;                      //关闭蜂鸣器

}

/**********************************************************/

void delay_140us(unsignedchar x)    //x*0.14MS

{

     unsignedchar i;

      while(x--)

     {

        for(i =0; i<13; i++){}

     }

}

 

/**********************************************************/

void delay1(int ms)

{

 unsignedchar y;

  while(ms--)

 {

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

      {

        _nop_();

        _nop_();

        _nop_();

        _nop_();

      }

 }

}

 

posted @ 2013-07-05 22:44  陈哈哈  阅读(880)  评论(0编辑  收藏