• 实验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]!='')

         {                         //显示字符

           lcd_wdat(cdis1[m]);

           m++;

         }

     

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

         m =0;

        while(cdis2[m]!='')

         {

           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_();

          }

     }

    }

     

  • 相关阅读:
    【BZOJ4517】排列计数(排列组合)
    【BZOJ2733】永无乡(线段树,启发式合并)
    【BZOJ1237】配对(贪心,DP)
    【BZOJ1492】货币兑换Cash(CDQ分治)
    CDQ分治模板
    【BZOJ3932】任务查询系统(主席树)
    【BZOJ3295】动态逆序对(BIT套动态加点线段树)
    【BZOJ3626】LCA(树上差分,树链剖分)
    图书管理系统
    树集合,树映射
  • 原文地址:https://www.cnblogs.com/kissazi2/p/3174567.html
Copyright © 2020-2023  润新知