打印
[经验分享]

51单片机红外遥控

[复制链接]
23|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
磨砂|  楼主 | 2025-1-13 07:42 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
51单片机红外遥控
实现功能
数码管上显示红外解码遥控器键值



红外遥控介绍
1、红外遥控简介
红外遥控是一种无线、非接触控制技术,具有抗干扰能力强,信息传输可靠, 功耗低,成本低,易实现等显著优点,被诸多电子设备特别是家用电器广泛采用, 并越来越多的应用到计算机系统中。

红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成

2、红外发射装置
红外发射装置,也就是通常我们说的红外遥控器是由键盘电路、红外编码电路、电源电路和红外发射电路组成。红外发射电路的主要元件为红外发光二极管。 它实际上是一只特殊的发光二极管。我们配套的红外遥控器使用的是 NEC 协议。

NEC 码的位定义:一个脉冲对应 560us 的连续载波,一个逻辑 1 传输需要 2.25ms(560us 脉冲+1680us 低电平),一个逻辑 0 的传输需要 1.125ms(560us 脉冲+560us 低电平)。而红外接收头在收到脉冲的时候为低电平,在没有脉冲的时候为高电平,这样,我们在接收头端收到的信号为:逻辑 1 应该是 560us 低 +1680us 高,逻辑 0 应该是 560us 低+560us 高。所以可以通过计算高电平时间判断接收到的数据是 0 还是 1。NEC 码位定义时序图如下图所示:



NEC 遥控指令的数据格式为:引导码、地址码、地址反码、控制码、控制反码。引导码由一个 9ms 的低电平和一个 4.5ms 的高电平组成,地址码、地址反 码、控制码、控制反码均是 8 位数据格式。按照低位在前,高位在后的顺序发送。采用反码是为了增加传输的可靠性(可用于校验)。数据格式如下:



NEC 码还规定了连发码(由 9ms 低电平+2.5m 高电平+0.56ms 低电平 +97.94ms 高电平组成),如果在一帧数据发送完毕之后,红外遥控器按键仍然没有放开,则发射连发码,可以通过统计连发码的次数来标记按键按下的长短或次数。

3、红外接收设备
红外接收设备是由红外接收电路、红外解码、电源和应用电路组成。红外遥 控接收器的主要作用是将遥控发射器发来的红外光信好转换成电信号,再放大、 限幅、检波、整形,形成遥控指令脉冲,输出至遥控微处理器。

硬件原理



从上图中可知,红外接收头的输出管脚接至单片机 P3.2 管脚上,为了保证红外接收头输出管脚默认为高电平,需外接一个 10K 上拉电阻,可在上图并没有 看到有上拉电阻,在前面介绍最小系统时已知道,单片机 IO 口都增加了 10K 上 拉电阻,所以此处可省。

软件编写
程序框架如下:

编写数码管显示功能
编写红外解码函数
编写主函数
#include <REGX52.H>

//红外遥控管脚位定义
sbit IRED=P3^2;
//数码管位选管脚定义
sbit LSC=P2^4;
sbit LSB=P2^3;
sbit LSA=P2^2;
//用于存放地址码、地址反码、控制码、控制反码
unsigned char Ired_Data[4];
//共阴极数码管显示 0~F 的段码数据
char SmgTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00};

void delay(unsigned int x)
{
        while(x--);
}

void Ired_Init()
{
        IT0=1;    //下降沿触发
        EX0=1;    //打开中断 0 允许
        EA=1;     //打开总中断
        IRED=1;   //初始化端口
}

void Ired() interrupt 0    //外部中断 0 服务函数
{
        unsigned char Ired_Hight_Time=0;
        unsigned char i,j;
        unsigned int Time=0;
       
        if(IRED==0)
        {
            //引导信号判断
                Time=1000;
                while((IRED==0)&&(Time!=0))   //等待引导信号 9ms 低电平结束,若超过 10ms 强制退出
                {
                        delay(1);     //延时约 10us
                        Time--;   
                        if(Time==0)
                                return ;
                }
                if(IRED==1)    //引导信号 9ms 低电平已过,进入 4.5ms 高电平
                {
                        Time=500;
                        while((IRED==1)&&(Time!=0))   //等待引导信号 4.5ms 高电平结束,如超过 5ms 强制退出
                        {
                                delay(1);
                                Time--;
                                if(Time==0)
                                        return ;
                        }

                        //地址码,反地址码,控制码,反控制码的收集
                        for(i=0;i<4;i++)   //循环 4 次,读取 4 个字节数据
                        {
                                for(j=0;j<8;j++)   //循环 8 次读取每位数据即一个字节
                                {
                                        Time=600;
                                        while((IRED==0)&&(Time!=0))    //等待数据 1 或 0 前面的 0.56ms 结束,若超过 6ms 强制退出
                                        {
                                                delay(1);
                                                Time--;
                                                if(Time==0)
                                                        return;       
                                        }
                                        Time=20;
                                        while(IRED)  //等待数据 1 或 0 后面的高电平结束,若超过 2ms 强制退出
                                        {
                                                delay(10);    //约 0.1ms
                                                Ired_Hight_Time++;
                                                if(Ired_Hight_Time>20)
                                                        return ;
                                        }
                                        Ired_Data>>=1;   //先读取的为低位,然后是高位
                                        if(Ired_Hight_Time>=8)   //如果高电平时间大于 0.8ms,数据则为 1,否则为 0.
                                                Ired_Data|=0x80;    //用或运算不影响其他位的数字
                                        Ired_Hight_Time=0;   //重新清零,等待下一次计算时间
                                }
                        }
                }
                if(Ired_Data[2]!=~Ired_Data[3])   //校验控制码与反控制码,错误则返回
                {
                        for(i=0;i<4;i++)
                                Ired_Data=0;
                        return ;
                }
        }
}

void smg(unsigned char Location[],unsigned char Number)   //数码管显示函数
{
        unsigned char i=0;
        unsigned char Pos_Temp=Number-1;
       
        for(i=Pos_Temp;i<8;i++)
        {
                switch(i)  //位选
                {
                        case 0: LSC=1; LSB=1; LSA=1; break;
                        case 1: LSC=1; LSB=1; LSA=0; break;
                        case 2: LSC=1; LSB=0; LSA=1; break;
                        case 3: LSC=1; LSB=0; LSA=0; break;
                        case 4: LSC=0; LSB=1; LSA=1; break;
                        case 5: LSC=0; LSB=1; LSA=0; break;
                        case 6: LSC=0; LSB=0; LSA=1; break;
                        case 7: LSC=0; LSB=0; LSA=0; break;
                }
                P0=Location[i-Pos_Temp];   //传送段选数据
                delay(100);   //延时一段时间,等待显示稳定
                P0=0x00;   //消影
        }
}

void main()
{
        unsigned char Ired_Buff[3];
       
        Ired_Init();
        while(1)
        {
                Ired_Buff[0]=SmgTable[Ired_Data[2]/16];   //将控制码高 4 位转换为数码管段码
                Ired_Buff[1]=SmgTable[Ired_Data[2]%16];   //将控制码低 4 位转换为数码管段码
                Ired_Buff[2]=0X76;   //显示 H 的段码
                smg(Ired_Buff,6);
        }
}

————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/zhouhaoNB_/article/details/127346124

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

103

主题

4186

帖子

2

粉丝