zoukankan      html  css  js  c++  java
  • 车载红外遥控之51单片机解码

    对单片机的了解学习,是作为简单的遥控器解码学习的基础,因为本次DIY是通过MCU作为解码媒介的。但实验中的DIY方式又不必需要功能强大的ARM系列单片机去实现,一般0851单片机就能解决。

    本实验的演示功能是通过对红外遥控键值解码后,对设定的目标键值做出响应,实验中的响应是单片机对继电器的开合、通断控制,可以简单理解为单片机检测到遥控器某个指定的按键按下,则控制继电器实现开关的切换功能,实现过程如下:

    Figure 1原理图

    首先是选型,由于物资条件,我们考虑成本,

    所以选择的都是廉价器件,器件有车载MP3

    外遥控,1318红外接收头,51系列的stc15F104w

    芯片,一个11.0592MHZ的晶振,两个100pf的电

    容,一个继电器,一个二极管1N4148,一个PNP三极管9012/S8550,两个200欧姆电阻。

    其次是电路搭建,电路通过红外遥控接收头,将接收到的遥控编码信息发送至单片机,单片机对红外遥控的键值解码后在P3.5口输出控制信

    号,控制继电器的开关效果。具体的电路原理图见

    原理图所示。

     最后,实现解码功能的51程序流程图如右图

    所示:首先硬件上电,软件初始化外部中断,初始

     

    化定时器配置,之后是不断地轮询单片机的中断引

     

    脚,检测单片机的引脚状态是否改变,如果引脚状态被改变了,说明端口有数据到来,此时单片机的定时器将在中断中被激活。定时器被激活的作用是用来给给每个二进制数据位进行定时的,将高低电平状态产生的时间存储到一个数组里面,最后将该时间值数组转换成高低电平状态。

     

     左图是红外遥控采集单片机中断引脚的高低电平时间,并将得到的时间放在irdate数组里,我们使用的红外遥控的编码是32位的编码。由引导码、用户码、数据码和数据码反码组成32位的编码方式。实验测试得到,引导码是有9ms的高电平和4.5ms的低电平组成。用户码或数据码中的每一个位可以是位‘1’,也可以是位‘0’。区分‘0’和‘1’是利用脉冲的时间间隔来区分,这种编码方式称为脉冲位置调制方式。英文简写PPM。其脉冲调制是使用455KHz晶体产生的载波脉冲实现。

     

    总结:通过本次实验,了解到了红外遥控编码及解码的工作原理。并实践应用51单片机解码实现继电器的吸合开关电路控制。实验中用到了单片机的外部中断配置和单片机的定时器配置。

     具体代码如下

    hwjm.c
    #include<stc15f104w.h>
    #include"hwjm.h"
    #include"delay.h"
    #include"music.h"
    
    uchar irreceok;//一整数据接收完毕
    uchar irprosok;
    unsigned char b;
    extern unsigned char b;
    //uchar irtime,irtime1;//第一步时间存储
    uchar irtime;    //第一步时间存储
    uchar startflag;
    uchar bitnum;
    uchar ircode[4];
    extern unsigned char Count;
    extern uchar smg_gyangji[];
    //uchar display[8];
    
    uchar irdate[33];//接收数组此为一些时间变量;0.25ms或者2.256ms
    uchar anjianjiema[]={0x16,0x0c,0x18,0x5e,0x08,0x1c,0x5a,0x42,0x52,0x4a};//0-7;
    uchar code table[]={
    0x3f,0x06,0x5b,0x4f,
    0x66,0x6d,0x7d,0x07,
    0x7f,0x6f,0x77,0x7c,
    0x39,0x5e,0x79,0x71};
    //uchar smg_gyangji[]={
    //0xC0,0xF9,0xA4,0xB0,
    //0x99,0x92,0x82,0xF8,
    //0x80,0x90,0x88,0x83,
    //0xC6,0xA1,0x86,0x8E    
    //};
    
    
    //////////////红外接收到数据的数据函数////////////////////////
    void hwxm_irrece(void)
    {
        if(startflag)//第一次红外数据为引导码不起作用所以startflag为0直接跳过
                {
                        if(irtime>30)//检测引导吗;
                        {
                                bitnum=0;
                        }
                        irdate[bitnum]=irtime;//存的是时间0.25/0.256或是2.25/0.256时刻提取计时器实计数
                        irtime=0;
                        bitnum++;//红外接收数据数组下标每次检测到一次下降沿引发中断时加一
                        if(bitnum==33)//
                        {
                                bitnum=0;
                                irreceok=1;//档主函数判断是否当一次红外数据发送并接收完毕
                        }
                                
                }
                else
                {
                    startflag=1;//中断触发后中断标志变量startflag将一直为1;
                    irtime=0;
                }
        
    
    }
    
    void hwxm_irpros(void)
    {
        uchar k,i,j;
        uchar value;
        k=1;//只提取用户吗;4*8=32位;
        for(j=0;j<4;j++)//四个码
        {
                for(i=0;i<8;i++)//每个码有8位
                {
                        value=value>>1;//7ci第一次vlalue等于0右移后等于0; 
                        if(irdate[k]>6)
                        {
                                value=value | 0x80;//10000000
                        }
                        k++;
                }
                ircode[j]=value;//为2进制
            }
            irprosok=1;//对时间转化成2进制的转换完毕;
    }
    int.c
    #include<stc15f104w.h>
    #include"int.h"
    #include"hwjm.h"
    extern uchar ircode[4];
    extern unsigned char Count;
     unsigned char Temp2;
    sfr T2MOD=0xc9;
    void timer0init(void)    //计时器零初始化
    {
            EA=1;
            ET0=1;
            TH0=0X00;
            TL0=0X00;//工作方式0
            TMOD=0X02;
            TR0=1;
    }
    
    void timer1init(void)    //计时器1初始化//最大值是255    
    {
            EA=1;
            ET1=1;
            T2H=0XDC;
            T2L=0X00;
            T2MOD=0X02;//工作方式2,8位初值自动重装8位定时器/计数器
            TR1=1;
    }
    
    
    void int0init(void)//中断0初始化函数
    {
            EA=1;    
            EX0=1;
            IT0=1;    //为跳变触发方式,电平从高到低的负跳变有效IT0=0时为低电平有效的电平触发方式
    }
    
    ////////////////////////////////////////////////////////////////////////
    ///////////计时器0服务函数//////////////////
    void timer0() interrupt 1
    {
            irtime++;
            
    }
    
    void timer1() interrupt 3
    {
             TH1 = 0xDC;
             TL1 = 0x00;
             Count++;  
        
        
    }
    ///////中断服务函数////////////////
    void int0 () interrupt 0//外部中断 服务函数
    {
        hwxm_irrece();
        hwxm_irpros();
        if(ircode[2]==0x45||ircode[2]==0x47)
            Temp2 = Count;
    }

    main.c

    #include<stc15f104w.h>
    #include"delay.h"
    #include"music.h"
    #include"hwjm.h"
    #include"int.h"
    ///////////////////////////////
    extern unsigned char b;
    extern uchar ircode[4];
    extern uchar smg_gyangji[];
    extern uchar anjianjiema[];
    unsigned char Count;
    extern uchar irreceok;//一整数据接收完毕
    extern uchar irprosok;
    
    sbit JD=P3^0;
    sbit D=P3^1;
    void main(void)
    {
        timer1init();
        timer0init();
        int0init();
        P0=0xff;
        while(1)
        {
            unsigned char b;
    
            
            
            
    
        
                if(irreceok)//判断总中断服务函数中对接收时间的存储是否接收完眎rreceok为接收完毕标志位;
                {
                        hwxm_irpros();//解码服务函数;将时间间隔大小转换成16进制数
                        irreceok=0;//解码是否完毕;
                }
                if(irprosok)
                {
    
                        irprosok=0;//对时间做出相应的十六进制转化完成标志清零;
                        for(b=0;b<10;b++)
                            {
                                    if(ircode[2]==anjianjiema[b])
                                    {
                                        delay_50us(2);
                                        if(ircode[2]==anjianjiema[0])
                                        {
                                            JD=1;
                                            D=1;
                                        }
                                        else 
                                        {
                                            JD=0;
                                            D=0;
                                                                                    
                                        }
                                            
    
                                                        
                                    }
                                }
                                            
                }        
    
            }
    }

     

  • 相关阅读:
    C# 5.0 CallerMemberName CallerFilePath CallerLineNumber 在.NET4中的使用
    Protocol Buffers 语法指南
    ERP、SCM及电子商务关系分析
    ]进程注入是王道之为NhibernateProfiler增加“附加到进程”功能原理(源码)
    架构师职位与软件文档的思考
    OSGI:从面向接口编程来理解OSGI
    开源的.NET桌面程序自动更新组件 ——Sharp Updater 2.1发布
    C#开源文件实时监控工具Tail&TailUI
    SQL 存储过程入门(变量)
    Python入门笔记(2):基础(上)
  • 原文地址:https://www.cnblogs.com/pertor/p/7512362.html
Copyright © 2011-2022 走看看