红外控制数码管扫描时的问题

2019-07-16 01:03发布

各位高人好:
       我是在用   STC89c516RD+,    DS1302,     红外发射器TC9012     红外接收头1838T
写一个电子时钟,时钟正常运行,在数码管上也正确显示,只是当进行红外控制时,当扫描的频率很低时,能够较好的按照预期效果执行;但当扫描的频率高时,程序根本接收不到我发送的正确信息,现象只是数码管在很短的时间内乱闪,然后恢复正常,没有起到红外的控制作用。不管是延时扫描还是定时扫描都不行,求大家帮忙啊,我改了好长时间都没有成功,都快崩溃了!
下面是程序
#include<reg52.h>
#define uc unsigned char
#define ui unsigned int
sbit led=P1^2;                                //流水灯控制位
sbit zhh=P1^3;                                //8*8点阵的行控制位
sbit wei=P1^1;                                //数码管位选控制
sbit duan=P1^0;                                //数码管段选控制
sbit dio=P3^2;                                //ds1302数据位
sbit sclk=P3^3;                                //ds1302时钟位
sbit rst=P3^4;                                //ds1302控制位
sbit en=P1^7;                                //1602控制位
uc dm[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段码0-9
uc wm[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位码
uc hc[]={0,0,0x40,0,0,0x40,0,0};//缓存显示的时钟数据,时,分,秒
uc hc1[33]={0};                                //用于接收解码后红外信号
uc shuju[4]={0};                        //接收到红外信号,整理为四个字节
uc hour,minute,second,jishi,done,ready,con,j;
/***************************************************
延时
***************************************************/
void delay(ui n)
{
        ui x,y;
        for(x=25;x>0;x--)                                //扫描频率高时x定为25,低时定为4000
                for(y=n;y>0;y--);
}
/***************************************************
显示函数
***************************************************/
void display()
{
        uc i;
        for(i=0;i<8;i++)
        {
                duan=1;
                P0=0x00;
                duan=0;
                P0=0xff;//用于消隐
                wei=1;
                P0=wm[i];
                wei=0;
                P0=0x00;//用于消隐
                duan=1;
                if(i==2||i==5)                                        //在时分秒中间加一杠
                        P0=hc[i];
                else
                        P0=dm[hc[i]];
                duan=0;
                delay(1);               
        //        TR1=1;                                                        //这是用定时来扫描
        //        while(!j);
        //        j=0;
        //        TR1=0;
        }
}

/***************************************************
初始化
***************************************************/
void init()
{
        P0=0xff;                        //关闭流水灯                               
        led=0;
        P0=0x00;                        //关闭点阵
        zhh=0;
        wei=0;                                //关闭数码管,在显示程序中再打开
        duan=0;
        rst=0;                                //关闭ds1302
        en=0;                                //关闭1602液晶
}
/***************************************************
1302设置    读写都按照1302的时序要求完成
***************************************************/
void write(uc dat)
{
        uc i;
        for(i=0;i<8;i++)
        {
                if(dat&0x01)
                        dio=1;
                else
                        dio=0;
                sclk=0;
                sclk=1;
                dat>>=1;
        }
}

void write1302(uc add,uc dat)
{
        rst=0;
        sclk=0;
        rst=1;
        write(add);
        write(dat);
        rst=0;
        sclk=1;
}

uc read()
{
        uc i,dat;
        for(i=0;i<8;i++)
        {
                if(dio)
                        dat|=0x80;
                sclk=1;
                sclk=0;
                dat>>=1;
        }
        return(dat);
}

uc read1302(uc add)
{
        uc dat;
        rst=0;
        sclk=0;
        rst=1;
        write(add);
        dat=read();
        rst=0;
        sclk=1;
        return(dat);
}

void init1302()                                                //1302初始化,时分秒的设置
{
        write1302(0x8e,0x00);

        write1302(0x80,(0/10*16+0%10));
        write1302(0x82,(46/10*16+46%10));
        write1302(0x84,(20/10*16+20%10));

        write1302(0x8e,0x80);
}

void change1302()                                        //1302更改,改变时分秒,在红外控制时用
{
        write1302(0x8e,0x00);

        write1302(0x80,(second/10*16+second%10));
        write1302(0x82,(minute/10*16+minute%10));
        write1302(0x84,(hour/10*16+hour%10));

        write1302(0x8e,0x80);
}
/***************************************************
DTB转换   
***************************************************/
void convert()
{
        hour=read1302(0x85);                                        //从1302中读取数据
        minute=read1302(0x83);
        second=read1302(0x81);
       
        hour=hour/16*10+hour%16;                                //将读取的BCD码转换为十进制
        minute=minute/16*10+minute%16;
        second=second/16*10+second%16;

        hc[0]=hour/10;                                                        //将时分秒的各位放入缓存
        hc[1]=hour%10;
        hc[3]=minute/10;
        hc[4]=minute%10;
        hc[6]=second/10;
        hc[7]=second%10;
}
/***************************************************
定时器初始化
***************************************************/
void tinit()
{
        TMOD=0x12;                                       
        TH0=0x00;
        TL0=0x00;
        TH1=(65536-4000)/256;
        TL1=(65536-4000)%256;
        EA=1;
        ET0=1;
        ET1=1;
        TR0=1;
}
/***************************************************
外部中断0初始化
***************************************************/
void einit()
{
        EX0=1;
        IT0=1;
}
/***************************************************
红外信号接收
***************************************************/
void rec()
{
        uc i,j,k=1,dat;
        for(i=0;i<4;i++)                                //将接收到的红外信号进行整理
        {
                for(j=0;j<8;j++)
                {
                        dat>>=1;
                        if(hc1[k]>7)                        //晶振为11.0592MHz
                                dat|=0x80;
                        k++;
                }
                shuju[i]=dat;
                dat=0;
        }
        ready=1;       
}
/***************************************************
红外信号解码
***************************************************/
void jiema()                                                //信号的散转
{
        switch(shuju[2])
        {
                case 0x47:
                        {
                                con=1;                                //开启红外控制
                        }
                break;
                case 0x15:
                        {
                                hour++;
                                if(hour==24)
                                        hour=0;
                        }
                break;
                case 0x07:
                        {
                                hour--;
                                if(hour>=24)
                                        hour=23;
                        }
                break;
                case 0x40:
                        {
                                minute++;
                                if(minute==60)
                                        minute=0;
                        }
                break;
                case 0x44:
                        {
                                minute--;
                                if(minute>=60)
                                        minute=59;
                        }
                break;
                case 0x46:
                        {
                                second++;
                                if(second==60)
                                        second=0;
                        }
                break;
                case 0x45:
                        {
                                second--;
                                if(second>=60)
                                        second=59;
                        }
                break;
                case 0x43:
                        {
                                con=0;                                        //关闭红外控制
                        }
                break;
        }
}
/***************************************************
红外处理
***************************************************/
void redcon()                                //红外信号综合处理
{
        if(done)
        {
                rec();
                done=0;
        }
        if(ready)
        {
                jiema();
                ready=0;
        }
}

/***************************************************
主函数
***************************************************/
void main()
{
        init();                                                //初始化
        init1302();
        tinit();
        einit();
        while(1)
        {       
                while(con==1)
                {
                        change1302();                        //将时分秒重新写入1302
                        convert();                                //将数据读出并转换为十进制
                        display();                                //显示
                }
                while(con==0)
                {
                        convert();                                //将数据读出并转换为十进制
                        display();                                //显示
                }
        }
}

void timer0() interrupt 1
{
        jishi++;                                //记录两个下降沿间的时间
}

void timer1() interrupt 3                //用于定时扫描时
{
        TH1=(65536-4000)/256;
        TL1=(65536-4000)%256;
        j=1;
}

void exter0() interrupt 0                                //红外中断控制
{
        static uc i;
        uc flag;
        if(flag)
        {
                if(jishi<55&&jishi>30)                                //辨别头码
                        i=0;
                hc1[i]=jishi;                                                //存后32位信号
                jishi=0;
                i++;
                if(i==33)
                {
                        i=0;
                        done=1;
                }
        }
        else
        {
                jishi=0;
                flag=1;
        }
        redcon();                                                //接收完后进行红外信号综合处理
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
tianmingxiyue
1楼-- · 2019-07-16 02:49
请高人们帮帮忙啊
sin88
2楼-- · 2019-07-16 05:30
本帖最后由 sin88 于 2013-5-27 22:28 编辑

#include<reg52.h>
#define uc unsigned char
#define ui unsigned int
sbit led=P1^2;                                //流水灯控制位
sbit zhh=P1^3;                                //8*8点阵的行控制位
sbit wei=P2^7;                                //数码管位选控制
sbit duan=P2^6;                                //数码管段选控制
sbit dio=P2^4;                                //ds1302数据位
sbit sclk=P2^5;                                //ds1302时钟位
sbit rst=P2^3;                                //ds1302控制位
sbit en=P1^7;                                //1602控制位
uc dm[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//段码0-9
uc wm[]={0XFE,0XFD,0XFB,0XF7,0XEF,0XDF};//位码
uc hc[]={0,0,0,0,0,0};//缓存显示的时钟数据,时,分,秒
uc hc1[33]={0};                                //用于接收解码后红外信号
uc shuju[4]={0};                        //接收到红外信号,整理为四个字节
uc hour,minute,second,jishi,done,ready,con;
/***************************************************
延时
***************************************************/
void delay(ui n)
{
        ui x,y;
        for(x=25;x>0;x--)                                //扫描频率高时x定为25,低时定为4000
                for(y=n;y>0;y--);
}
/***************************************************
显示函数
***************************************************/
void display()
{
        uc i;
        for(i=0;i<6;i++)
        {
                duan=1;
                P0=0x00;
                duan=0;
                P0=0xff;//用于消隐

                wei=1;
                P0=wm;
                wei=0;
                P0=0x00;//用于消隐

                duan=1;
                P0=dm[hc];
                duan=0;
                delay(1);               
        }
}

/***************************************************
初始化
***************************************************/
void init()
{
        P0=0xff;                        //关闭流水灯                              
        led=0;
        P0=0x00;                        //关闭点阵
        zhh=0;
        wei=0;                                //关闭数码管,在显示程序中再打开
        duan=0;
        rst=0;                                //关闭ds1302
        en=0;                                //关闭1602液晶
}
/***************************************************
1302设置    读写都按照1302的时序要求完成
***************************************************/
void write(uc dat)
{
        uc i;
        for(i=0;i<8;i++)
        {
                if(dat&0x01)
                        dio=1;
                else
                        dio=0;
                sclk=0;
                sclk=1;
                dat>>=1;
        }
}

void write1302(uc add,uc dat)
{
        rst=0;
        sclk=0;
        rst=1;
        write(add);
        write(dat);
        rst=0;
        sclk=1;
}

uc read()
{
        uc i,dat;
        for(i=0;i<8;i++)
        {
                if(dio)
                        dat|=0x80;
                sclk=1;
                sclk=0;
                dat>>=1;
        }
        return(dat);
}

uc read1302(uc add)
{
        uc dat;
        rst=0;
        sclk=0;
        rst=1;
        write(add);
        dat=read();
        rst=0;
        sclk=1;
        return(dat);
}

void init1302()                                                //1302初始化,时分秒的设置
{
        write1302(0x8e,0x00);

        write1302(0x80,(0/10*16+0%10));
        write1302(0x82,(46/10*16+46%10));
        write1302(0x84,(20/10*16+20%10));

        write1302(0x8e,0x80);
        rst=0;
        sclk=0;


}

void change1302()                                        //1302更改,改变时分秒,在红外控制时用
{
        write1302(0x8e,0x00);

        write1302(0x80,(hc[4]*16+hc[5]));
        write1302(0x82,(hc[2]*16+hc[3]));
        write1302(0x84,(hc[0]*16+hc[1]));

        write1302(0x8e,0x80);
}
/***************************************************
DTB转换   
***************************************************/
uc BCD(uc bcd){
    uc Decimal;
    Decimal=bcd>>4;
    return(Decimal=Decimal*10+(bcd&=0x0F));
}


void convert()
{
        hc[0]=BCD(hour)/10;                                                        //将时分秒的各位放入缓存
        hc[1]=BCD(hour)%10;
        hc[2]=BCD(minute)/10;
        hc[3]=BCD(minute)%10;
        hc[4]=BCD(second)/10;
        hc[5]=BCD(second)%10;
}
/***************************************************
定时器初始化
***************************************************/
void tinit()
{
        TMOD=0x12;                                       
        TH0=0x00;
        TL0=0x00;
        TH1=0;
        TL1=0;
        EA=1;
        ET0=1;
        ET1=1;
        TR0=1;
        TR1=1;
}
/***************************************************
外部中断0初始化
***************************************************/
void einit()
{
        EX0=1;
        IT0=1;
}
/***************************************************
红外信号接收
***************************************************/
void rec()
{
        uc i,j,k=1,dat;
        for(i=0;i<4;i++)                                //将接收到的红外信号进行整理
        {
                for(j=0;j<8;j++)
                {
                        dat>>=1;
                        if(hc1[k]>7)                        //晶振为11.0592MHz
                                dat|=0x80;
                        k++;
                }
                shuju=dat;
                dat=0;
        }
        ready=1;      
}
/***************************************************
红外信号解码
***************************************************/
void jiema()                                                //信号的散转
{
        switch(shuju[2])
        {
                case 0x47:
                        {
                                con=1;                                //开启红外控制
                        }
                break;
                case 0x40:
                        {
                                hour++;
                                if(hour==24)
                                        hour=0;
                        }
                break;
                case 0x44:
                        {
                                hour--;
                                if(hour>=24)
                                        hour=23;
                        }
                break;
                case 0x15:
                        {
                                minute++;
                                if(minute==60)
                                        minute=0;
                        }
                break;
                case 0x07:
                        {
                                minute--;
                                if(minute>=60)
                                        minute=59;
                        }
                break;
                case 0x0d:
                        {
                                second++;
                                if(second==60)
                                        second=0;
                        }
                break;
                case 0x19:
                        {
                                second--;
                                if(second>=60)
                                        second=59;
                        }
                break;
                case 0x45:
                        {
                                con=0;                                        //关闭红外控制
                        }
                break;
        }
}
/***************************************************
红外处理
***************************************************/
void redcon()                                //红外信号综合处理
{
        if(done)
        {
                rec();
                done=0;
        }
        if(ready)
        {
                jiema();
                ready=0;
        }
}

/***************************************************
主函数
***************************************************/
void main()
{
        init();                                                //初始化
        init1302();
        tinit();
        einit();
        while(1)
        {      
                while(con==1)
                {
                    TR1=0;
                    while(con){                        
                        convert();                                //将数据读出并转换为十进制
                        display();
                    }
                    change1302();                        //将时分秒重新写入1302
                    TR1=1;                                //显示
                }
                while(con==0)
                {
                        convert();                                //将数据读出并转换为十进制
                        display();                                //显示
                }
        }
}

void timer0() interrupt 1
{
        jishi++;                                //记录两个下降沿间的时间
}

void timer1() interrupt 3                //用于定时扫描时
{
        TH1=0;
        TL1=0;
        hour=read1302(0x85);                                        //从1302中读取数据
        minute=read1302(0x83);
        second=read1302(0x81);
}

void exter0() interrupt 0                                //红外中断控制
{
        static uc i;
        uc flag;
        if(flag)
        {
                if(jishi<55&&jishi>30)                                //辨别头码
                        i=0;
                hc1=jishi;                                                //存后32位信号
                jishi=0;
                i++;
                if(i==33)
                {
                        i=0;
                        done=1;
                }
        }
        else
        {
                jishi=0;
                flag=1;
        }
        redcon();                                                //接收完后进行红外信号综合处理
}

改好的了  
数码管驱动部分请无视,按我是我学习版上改的这块

现在不管你如何
扫描频率都没错
遥控解码部分是我手里遥控的键值,请无视


主要原因是1302不能读取的太频繁,不然就出错了
tianmingxiyue
3楼-- · 2019-07-16 10:20
sin88 发表于 2013-5-27 22:14
#include
#define uc unsigned char
#define ui unsigned int

真的非常感谢你,通过你修改过的程序,我的红外确实起作用了,其它的都是小问题,不懂了再向你请教

一周热门 更多>