从头学玩单片机STC15F104W《七》用中九接收机前屏做遥控解码器
编辑时间:2022-06-02 作者:金满斗 浏览量:2923 来源:原创

话不多说,做出来了,看效果。

显示分3次,用户码高8位,用户码低8位,遥控码。

源码已上传gitee。

构造图以前传过。就是这样的。

不过这个其实也不算完美,第一个是解码的头文件写的并不规范,不晓得是哪里的问题,不能拆分,拆分了会对别的造成干扰。

第二是有些遥控接收好像有问题,这个灵敏度不如下面的。

下面的这个通过遥控信号来直接控制中断,从原理上来说应该更好,但好像解码算法上又有问题,也许是我没搞懂吧。

避免时间长了遗失了,把那个高灵敏的源码贴上来。


#include<reg51.h>

sbit OUTPUT=P3^2;                //P3.2引脚为单片机外部中断0的触发引脚,同时连接红外接收模块IR 1838的输出端,在模块输出信号的同时进入外部中断0的服务函数
sbit Wei=P2^7;                //数码管模块位锁存

unsigned char Code[9]={0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};                //数码管显示从“1”到“9”的段码
unsigned char Code0[4];
unsigned char Code1[33];
unsigned char time;

bit m,n;                //定义两个标志位;标志位m表示一帧数据解码完毕,标志位n表示一帧数据接收完毕

void ET_0() interrupt 1 using 1                //定时器0中断
{
        time++;                //对两个下降沿之间的时间间隔进行计数
}

void EX_0() interrupt 0                //外部中断0
{
        static unsigned char i;
        static bit START;
        if(START)
        {
                if(time<63&&time>=33)                //引导码,9ms+4.5ms
                {
                        i=0;
                }
                Code1[i]=time;                //存储两个下降沿之间的时间间隔,将用于数据帧的“0”和“1”
                time=0;
                i++;
                if(i==33)
                {
                        n=1;
                        i=0;
                }
        }
        else
        {
                time=0;
                START=1;
        }
}

void ET0_init()                //定时器0中断初始化
{
        TMOD=0x02;                //定时器0工作在方式2
        TH0=0x00;                //重载值
        TL0=0x00;                //初始值
        ET0=1;                //开启定时器0中断
        TR0=1;
}

void EX0_init()                //外部中断0初始化
{
        IT0=1;                //设置外部中断0为下降沿触发
        EX0=1;                //开启外部中断0
        EA=1;                //开启总中断
}

void DECODE()                //红外解码
{
        unsigned char i,j,k;
        unsigned char x,y;
        k=1;
        for(i=0;i<4;i++)                //对数据帧中的4个字节进行处理
        {
                for(j=1;j<=8;j++)                //对一个字节中的8位进行处理
                {
                        x=Code1[k];
                        if(x>7)                //时间间隔大于某值则为1,与晶振(12MHz)相关,允许误差
                        {
                                y|=0x80;
                        }
                        if(j<8)
                        {
                                y>>=1;
                        }
                        k++;
                }
                Code0[i]=y;
                y=0;
        }
        m=1;
}

void NUMBER()                //将红外遥控器的按键值转换为数码管的段值
{
        switch(Code0[2])
        {
                case 0x0c:P0=Code[0];break;
                case 0x18:P0=Code[1];break;
                case 0x5e:P0=Code[2];break;
                case 0x08:P0=Code[3];break;
                case 0x1c:P0=Code[4];break;
                case 0x5a:P0=Code[5];break;
                case 0x42:P0=Code[6];break;
                case 0x52:P0=Code[7];break;
                case 0x4a:P0=Code[8];break;
                default:break;
        }
        m=0;
}

void main()
{
        ET0_init();
        EX0_init();
        
        P0=0xfe;                //取数码管模块左边第一位选通
        Wei=1;
        Wei=0;
        
        while(1)
        {
                if(n)
                {
                        DECODE();
                        n=0;
                }
                if(m)
                {
                        NUMBER();
                }
        }
}


来说两句吧