51单片机学习笔记【九】——红外通信实验

一.红外通信基础

1.红外线原理

红外线是波长在760nm~1mm之间的非可见光。红外通信装置由红外发射管和红外接受管组成,红外发射管是能发射出红外线的发光二极管,发射强度随着电流的增大而增大;红外接受管是一个具有红外光敏感特征的PN节的光敏二极管,只对红外线有反应,产生光电流。

2.信号调制原理

  • 基带信号:从信号源发出没有经过调制的原始信号,特点是频率较低,信号频率从0开始,频谱较宽。
  • 调制:就是用待传送信号去控制某个高频信号的幅度、相位、频率等参量变化的过程,即用一个信号去装载另一个信号。

红外遥控器使用38KB的载波对原始信号进行解调,原理如下

调制后产生一定频段的高低电平,但红外接收头接受到的信号和调制后的信号电平相反。

3.NEC协议

红外遥控由多种协议控制,这里介绍最主要,应用最广的NEC协议。NEC数据格式:引导码、用户码、用户码(或者用户码反码)、按键键码和键码反码,最后一个停止位。

  • 引导码:9ms的载波+4.5ms的空闲。
  • 比特值“0”:560us的载波+560us的空闲。
  • 比特值“1”:560us的载波+1.68ms的空闲。

    协议规定低位首先发送。一串信息首先发送9ms的AGC(自动增益控制)的高脉冲,接着发送4.5ms的起始低电平,接下来是发送四个字节的地址码和命令码。如果你一直按那个按键,一串信息也只能发送一次,一直按着,发送的则是以110ms为周期的重复码。

二.实验例程

1.实验原理

产生下降沿,进入外部中断0的中断函数,延时一下之后检IO口是否还是低电平,是就等待9ms的低电平过去。等待完9ms低电平过去,再去等待4.5ms的高电平过去。接着开始接收传送的4组数据先等待560us的低电平过去检测高电平的持续时间,如果超过1.12ms那么是高电平(高电平的的持续时间为1.69ms,低电平的持续时间为565us。)检测接收到的数据和数据的反码进行比较,是否等到的数据是一样的。

2.实验说明

本实验通过单片机控制红外接受设备接受红外发送设备发送的信号,并通过数码管的显示判断是否接受到信号。实验接线为JP10接J12,J6的A,B,C分别接P2.2,P2.3,P2.4。

3.源代码

/**************************************
  > File Name: 红外通信原理
  > Author: pengshp
  > Mail: [email protected]
  > Date: 2015年 7 月 27 日
***************************************/
#include<reg51.h>
#define GPIO_DIG P0

sbit LSA  = P2^2;
sbit LSB  = P2^3;
sbit LSC  = P2^4;
sbit IRIN = P3^2;                           //红外接收器位声明

unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                                 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char DisplayData[8];               //用来存放要显示的8位数的值
unsigned char IrValue[6];                   //用来存放读取到的红外值
unsigned char Time;

void DigDisplay();                          //动态显示函数
void IrInit();
void DelayMs(unsigned int);

void main()
{
    IrInit();
    while(1)
    {
        IrValue[4]=IrValue[2]>>4;           //高位
        IrValue[5]=IrValue[2]&0x0f;         //低位
        DisplayData[0] = 0x00;
        DisplayData[1] = DIG_CODE[IrValue[4]];
        DisplayData[2] = DIG_CODE[IrValue[5]];
        DisplayData[3] = 0x76;
        DisplayData[4] = 0x00;
        DisplayData[5] = DIG_CODE[IrValue[4]];
        DisplayData[6] = DIG_CODE[IrValue[5]];
        DisplayData[7] = 0x76;
        DigDisplay();
    }
}

void DelayMs(unsigned int x)                 //0.14ms误差 0us
{
    unsigned char i;
    while(x--)
    {
        for (i = 0; i<13; i++);
    }
}

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

void ReadIr() interrupt 0
{
    unsigned char j,k;
    unsigned int err;
    Time=0;
    DelayMs(70);
    if(IRIN==0)                              //确认是否真的接收到正确的信号
    {
        err=1000;                            //1000*10us=10ms,超过说明接收到错误的信号
        while((IRIN==0)&&(err>0))            //等待前面9ms的低电平过去
        {
            DelayMs(1);
            err--;
        }
        if(IRIN==1)                          //如果正确等到9ms低电平
        {
            err=500;
            while((IRIN==1)&&(err>0))        //等待4.5ms的起始高电平过去
            {
                DelayMs(1);
                err--;
            }
            for(k=0;k<4;k++)                 //共有4组数据
            {
                for(j=0;j<8;j++)             //接收一组数据
                {
                    err=60;
                    while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
                    {
                        DelayMs(1);
                        err--;
                    }
                    err=500;
                    while((IRIN==1)&&(err>0))//计算高电平的时间长度。
                    {
                        DelayMs(1);          //0.14ms
                        Time++;
                        err--;
                        if(Time>30)
                        {
                            EX0=1;
                            return;
                        }
                    }
                    IrValue[k]>>=1;          //k表示第几组数据
                    if(Time>=8)              //如果高电平出现大于565us,那么是1
                    {
                        IrValue[k]|=0x80;
                    }
                    Time=0;                  //用完时间要重新赋值
                }
            }
        }
        if(IrValue[2]!=~IrValue[3])          //反码取反后与原码相同则说明信号接受正确
        {
            return;
        }
    }
}

void DigDisplay()
{
    unsigned char i;
    unsigned int j;
    for(i=0;i<8;i++)
    {
        switch(i)                           //位选,选择点亮的数码管
        {
            case(0):
                LSA=0;LSB=0;LSC=0; break;   //显示第0位
            case(1):
                LSA=1;LSB=0;LSC=0; break;   //显示第1位
            case(2):
                LSA=0;LSB=1;LSC=0; break;   //显示第2位
            case(3):
                LSA=1;LSB=1;LSC=0; break;   //显示第3位
            case(4):
                LSA=0;LSB=0;LSC=1; break;   //显示第4位
            case(5):
                LSA=1;LSB=0;LSC=1; break;   //显示第5位
            case(6):
                LSA=0;LSB=1;LSC=1; break;   //显示第6位
            case(7):
                LSA=1;LSB=1;LSC=1; break;   //显示第7位
        }
        GPIO_DIG=DisplayData[i];            //发送段码
        j=10;                               //扫描间隔时间设定
        while(j--);
        GPIO_DIG=0x00;                      //消隐
    }
}

:红外遥控原理具体参考资料:传送门

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-29 05:04:42

51单片机学习笔记【九】——红外通信实验的相关文章

[51单片机学习笔记ONE]-----LED灯的多种使用方法

一.交替闪烁8个LED灯,时间间隔为1s 1 /****************************************************** 2 实验名称: 交替闪烁8个LED灯,时间间隔1s 3 实验时间: 2014年12月2日 4 ******************************************************/ 5 6 #include <reg51.h> 7 8 void delay(unsigned char a); 9 10 void m

[51单片机学习笔记TWO]----蜂鸣器

蜂鸣器音乐播放实验 首先应该了解一下蜂鸣器音乐播放的原理,在这里我只讲一下电磁式蜂鸣器驱动原理(还有一种是压电式蜂鸣器): 电磁式蜂鸣器驱动原理: 蜂鸣器发声原理是电流通过电磁线圈,使电磁圈产生磁场来驱动振动膜发声的.因此需要一定的电流才能驱动它,而单片机I/O引脚输出的电压较小.单片机输出的TTLK电平基本驱动不了蜂鸣器,因需要增加一个放大电路.这里用三极管作为放大电路.下面是原理图: 我这里的J8端是跟芯片的P1^5端口相连,当P1^5输出高电平时,三极管截止,蜂鸣器不发声,反之,输出低电平

51单片机学习笔记【六】——串口通信实验

一.串口通信基础 1.串行通信 串行通信将数据字节分成一位一位的形式在一条传输线上逐个传送.单片机采用串行通信.特点是:传输线少,长距离传送成本低,但数据传送控制复杂. 串行通信的传输的传输方向:单工(数据传输只能沿一个方向),办双工(传输数据和接受数据分布进行),全双工(传输和接受同步进行). 单片机采用异步通信,发送和接受设备使用各自的时钟频率,容易实现,但传输效率不高,数据格式 2.MAX232 实验通过MAX232电平转换芯片,可把计算机串口电平(-12V~+12V)转换为单片及TTL电

51单片机学习笔记【五】——1602液晶屏

一.1602液晶屏基础 1.LCD1602简介 1602液晶也叫1602字符型液晶,它是一种专门用来显示字母.数字.符号的点阵型液晶模块.它是由若干个5x7或者5x11的点阵字符位组成,每个点阵字符位都可以用显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能很好的显示图片.本次使用型号为SMC1602A LCM的液晶屏. 2.LCD1602接口信号说明 3.控制接口说明 4.指令说明 二.实验例程 1.电路原理图 2.实验说明 本实验通

[51单片机学习笔记FOUR]----16*16LED点阵

一.LED点阵发光原理 8*8单色单片机结构图如下: 从电路图中很简单的就可以看出来,想要点亮点阵中的某一个LED灯.只要使得那个灯所在的行输出高电平,所在列输出低电平就好. 二.点阵扫描实验 1 /*********************************************** 2 实验名称: 点阵扫描 3 实验说明: 扫描每个LED灯,检查点阵是否完好 4 实验时间: 2014/12/24 5 ******************************************

51单片机学习笔记【八】——步进电机

一.步进电机基础 1.定义 步进电机是将电脉冲转化为角位移的执行机构,主要使用永磁性步进电机,本实验使用的步进电机为四线双性步进电机: 步进电机的相数指产生不同极性N,S磁场的激磁线圈对数,常用m表示: 步进电机的拍数指完成一个磁场周期性变化所需脉冲数,以四线二相电机为例: 单向四拍:A/-B-A-B/ 双向四拍:A/B-AB-AB/-A/B/ 单&双八拍:A/-A/B-B-AB-C-A-AB/-B/-A/B/ 步进角指定子没改变一次通电状态,转子转过的角度,与磁极数,定子相数,通电方式节拍成负

[51单片机学习笔记FIVE]----独立按键

一.8个按键控制8个LED灯 1 /******************************************************************************* 2 实验名称: 8个独立按键控制8盏LED灯(按下哪个键,那个键对应的LED亮) 3 实验时间: 2015/1/20 4 *******************************************************************************/ 5 #include

[51单片机学习笔记THREE]----继电器

继电器是一种电控制器件,它是当输入量(如电压,电流,温度等)达到规定值时,使得被控量发生阶跃性变化的一种电器. 比如说:我们只需要用一个12V,0.1A的参数量去控制一个继电器,然后让继电器去充当几百万伏特,几百万安培的设备的开关. 无论在什么地方,如果想让控制者处于安全的环境中,就可以用继电器.让我们去接触安全的一边,让继电器去接触危险的一边,我们只要控制继电器的动作,继电器就会帮助我们连接我们不想亲自去碰的一些线路. 继电器的分类千千万,这里就不多说了. 最近因为好像没什么地方要用到,这里先

51单片机学习笔记【七】——蜂鸣器和继电器

一.蜂鸣器 1.蜂鸣器基础 蜂鸣器按驱动方式分为有源蜂鸣器和无源蜂鸣器,有源蜂鸣器内部带振荡器,接入一个低电平便会响:无源蜂鸣器不带振荡器,让它响要接500HZ~4.5KHZ之间的脉冲信号来驱动才会响.很实验采用的是无源蜂鸣器. 2.电路原理图 3.实验说明 本实验通过控制蜂鸣器分别在4KHZ和1KHZ频率下发声,实验接线为JP8接P1.5. 4.程序源代码 /************************************** > File Name: 蜂鸣器实验 > Author: