红外遥控接收模块+普中51单片机+江科大自化协

2024-08-05  

1 实验现象

  LCD1602上显示红外解码遥控器地址、键值。通过红外遥控器,按下某个按键时,遥控器通过红外发光二极管发射红外线,红外一体化接受头接受信号,并对其解码,单片机处理相应的信息,将得到的数据显示在LCD1602上。

2 实验原理

 红外遥控是一种无线、非接触控制技术,具有抗干扰性能力强,信息传输可靠,功耗低、成本低、易实现等显著优点,被诸多电子设备特别是家用电器广泛采用,在工业设备中也得到广泛应用。

什么是红外线?红外线是一种肉眼看不见的光。红外线是波长介于微波和可见光之间的电磁波,波长在760nm和1000nm之间,是波形比红光长的非可见光。

如何发出红外光?红外发射二极管就可以发出红外线。最常用的红外发射管是发出940nm的红外光。它的外形类似二极管,但是它发射出来的是红外光,是我们肉眼所看不到的。发光二极管的亮度会随着电路的增大而增加,同样的道理,红外发射管发射红外线的强度也会随着电流的增大而增强。

红外遥控基本原理:红外遥控器常用的载波的方式传送二级制编码,常用的载波频率为38KHz,通常的红外遥控器是将遥控信号(二进制脉冲码)调制在38KHz的载波上,井缓冲放大后送至红外发光二极管,转化为红外信号发射出去的。

3 系统设计

4 硬件设计(略)

5 软件设计


5.1 主函数


#include

#include "lcd1602.h"

#include "InfraredRemote.h"


unsigned char Num;

unsigned char address;

unsigned char command;


void main()

{

    LCD1602_Init();

    LCD1602_ShowString(1,1,"ADDR  CMD  NUM");

    LCD1602_ShowString(2,1,"00    00   000");

    

    IR_init();

    

    while(1)

    {

        if(IR_getdataflag()||IR_getrepeatflag()) //如果收到数据帧或者收到连发帧

        {

            address=IR_getaddress();    //获取遥控器地址码

            command=IR_getcommand();    //获取遥控器命令码

            

            LCD1602_ShowHexNum(2,1,address,2);    //显示遥控器地址码

            LCD1602_ShowHexNum(2,7,command,2);    //显示遥控器命令码

            

            if(command==IR_VOL_MINUS)    //如果遥控器VOL-按键按下

            {

                Num--;                    //Num自减

            }

            

            if(command==IR_VOL_ADD)        //如果遥控器VOL+按键按下

            {

                Num++;                    //Num自增

            }

            LCD1602_ShowNum(2,12,Num,3);//显示Num

        }

    }

}


5.2 红外遥控接收函数


#include

#include "timer0.h"

#include "exint0.h"


unsigned int     IR_time;        //记录相邻两个下降沿的时间

unsigned char     IR_state;        //状态机设计

unsigned char     IR_data[4];        //用来接收数据32位,4个字节

unsigned char    IR_pdata;        //用来记录接收第几位数据,0-31


unsigned char     IR_dataflag;    //数据接收完毕标识信号

unsigned char     IR_repeatflag;    //重复发送标识信号

unsigned char     IR_address;        //接收地址

unsigned char     IR_command;        //接收命令


/**

  * @brief  红外遥控初始化

  * @param  无

  * @retval 无

  */

void IR_init(void)

{

    exint0_init();        //外部中断INT0

    timer0_init();        //定时器T0

}


/**

  * @brief  红外遥控获取收到数据帧标志位

  * @param  无

  * @retval 是否收到数据帧,1为收到,0为未收到

  */

unsigned char IR_getdataflag(void)

{

    if(IR_dataflag)

    {

        IR_dataflag=0;

        return 1;

    }

    else

        return 0;

}


/**

  * @brief  红外遥控获取收到连发帧标志位

  * @param  无

  * @retval 是否收到连发帧,1为收到,0为未收到

  */

unsigned char IR_getrepeatflag(void)

{

    if(IR_repeatflag)

    {

        IR_repeatflag=0;

        return 1;

    }

    else

        return 0;

}


/**

  * @brief  红外遥控获取收到的地址数据

  * @param  无

  * @retval 收到的地址数据

  */

unsigned char IR_getaddress(void)

{

    return IR_address;

}


/**

  * @brief  红外遥控获取收到的命令数据

  * @param  无

  * @retval 收到的命令数据

  */

unsigned char IR_getcommand(void)

{

    return IR_command;

}


//外部中断0中断函数,下降沿触发执行,状态机设计

void int0_routine(void) interrupt 0

{

    if(IR_state==0)        //状态0,空闲状态

    {

        timer0_SetCounter(0);    //设置计数器起始值,从0开始计数

        timer0_Run(1);            //启动定时器T0

        IR_state=1;

    }

    else if(IR_state==1)    //状态1,等待Start信号或Repeat信号

    {

        IR_time=timer0_GetCounter(); //获取上一次中断到此次中断的时间

        timer0_SetCounter(0);        //设置计数器起始值,从0开始计数

        //如果计时为9ms+4.5ms=13.5ms,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)

        if(IR_time>12442-500 && IR_time<12442+500)    //起始信号(11.0592MHz)

        {

            IR_state=2;        //状态2,接收数据

        }

        //如果计时为9ms+2.25ms=11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)

        else if(IR_time>10368-500 && IR_time<10368+500)    //重复信号

        {

            IR_repeatflag=1;    //置收到连发帧标志位为1

            timer0_Run(0);        //关闭定时器T0

            IR_state=0;            //置状态为0

        }

        else  IR_state=1;        //接收错误,状态保持

    }

    else if(IR_state==2)        //接收数据状态

    {

        IR_time=timer0_GetCounter();     //获取上一次中断到此次中断的时间

        timer0_SetCounter(0);            //设置计数器起始值,从0开始计数

        //如果计时为560+560=1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)

        if(IR_time>1032-500 && IR_time<1032+500)        //数据0

        {

            IR_data[IR_pdata/8] &= ~(0x01<<(IR_pdata%8));    //数据对应位清0

            IR_pdata++;        //数据位置指针自增

        }

        //如果计时为560+1690=2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)

        else if(IR_time>2074-500 && IR_time<2074+500)    //数据1

        {

            IR_data[IR_pdata/8] |= (0x01<<(IR_pdata%8));    //数据对应位置1

            IR_pdata++;        //数据位置指针自增

        }

    }

    else                //接收出错

    {

        IR_pdata=0;        //数据位置指针清0

        IR_state=1;        //置状态为1

    }

    if(IR_pdata>=32)    //接收完所有数据

    {

        IR_pdata=0;        //数据位置指针清0

        //判断地址码和地址反码,数据码和数据反码是否相反,数据验证

        if((IR_data[0]==~IR_data[1])&&(IR_data[2]==~IR_data[3]))    

        {

            IR_address=IR_data[0];    //转存数据,地址数据

            IR_command=IR_data[2];    //命令数据

            IR_dataflag=1;            //置收到数据帧标志位为1

        }

        timer0_Run(0);            //关闭定时器T0

        IR_state=0;                //空闲状态

    }        

}


#ifndef _InfraredRemote_h_

#define _InfraredRemote_h_


#define IR_POWER        0x45

#define IR_MODE            0x46

#define IR_MUTE            0x47


#define IR_START_STOP    0x44

#define IR_PREVIOUS        0x40

#define IR_NEXT            0x43


#define IR_EQ            0x07

#define IR_VOL_MINUS    0x15

#define IR_VOL_ADD        0x09


#define IR_0            0x16

#define IR_RPT            0x19

#define IR_USD            0x0D


#define IR_1            0x0C

#define IR_2            0x18

#define IR_3            0x5E


#define IR_4            0x08

#define IR_5            0x1C

#define IR_6            0x5A


#define IR_7            0x42

#define IR_8            0x52

#define IR_9            0x4A


void IR_init(void);

unsigned char IR_getdataflag(void);

unsigned char IR_getrepeatflag(void);

unsigned char IR_getaddress(void);

unsigned char IR_getcommand(void);

    

#endif


5.3 外部中断INT0


#include


void exint0_init(void)

{

    IT0=1;

    IE0=0;

    EX0=1;

    EA=1;

    PX0=1;

}


//void int0_routine(void) interrupt 0

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。