[求助] 按键按下时数码管显示会有些闪烁

werjufour   2015-1-31 21:07 楼主
大侠们!
帮帮忙,按键按下时,数码管会有些闪烁不知道是怎么回事,要如何消除呢?另外该程序还有哪些不足之处请指出。
在此谢谢你们了!电路图在附件里,程序如下:
/*************************************************************
实验效果:用定时器定时来控制继电器的工作,初始时定时为150分钟、
继电器吸合、同时所定的时间在三位数码管上显示出来。开始时定时器
工作,按下S1定时器工作,每过1分钟时间减1,当所定的150分钟减为0时
继电器释放、定时器不工作、数码管不显示单片机进入掉电模式。按下S1、
S2、S3均可唤醒单片机。S1的作用是按下该键时定时器关闭或者启动之间
进行切换,同时数码管显示位置1;S2的作用是按下该键时数码管显示或者
不显示之间进行切换;S3的作用是只有定时器关闭和数码管显示位置1时按
下该键才起作用,每按该键定时时间减15分钟。同时每个按键按下时都会
发出滴的一声。晶振采用12MHZ.
****************************************************************/
#include"STC15F204EA.h"
#include
#define GPIO_DIG P1
#define Fosc 12000000

sbit DS1=P3^7;
sbit DS2=P0^0;/*我所使用的单片机是A版本P0.0。B版本为P5.4*/
sbit DS3=P0^1;/*我所使用的单片机是A版本,所以这里用P0.1。B版本为P5.5*/      
sbit S3=P3^0;
sbit S2=P3^2;
sbit S1=P3^3;
sbit BZ=P3^4;
sbit RELAY=P3^5;
int Time, Num=150;
bit flag=1;/*数码管显示位置1显示*/
bit BZ_flag;
unsigned char code DIG[10]={0x7e,0x0c,0xb6,0x9e,0xcc,0xda,0xfa,0x0e,0xfe,0xde};
void Delay3ms();                //@12.000MHz
void display(unsigned int b);

main()
{       
    unsigned char n;
    BZ=0;
    /*喂狗*/
    WDT_CONTR=0x34;/*12.000MHz,看门狗溢出时间为1秒左右,溢出之后看门狗复位*/
    P5M0=0x30;
    P3M0=0xB0;
          P1M0=0XFF;

    IT1=1;/*外部中断1为下降沿触发方式*/
    IT0=1;/*外部中断0为下降沿触发方式*/
    INT_CLKO=0x40;/*允许外部中断4中断*/
    EX1=1;/*允许外部中断1中断*/
    EX0=1;/*允许外部中断0中断*/       
    PX1=1;/*设置外部中断1为高优先级*/

    TMOD=0x00;/*设定定时器0工作模式为0*/
        AUXR=0x00;/*设定定时器0工作在12T模式*/
        TH0=(65536-Fosc/12/20)>>8;/*给定时器0赋初值,定时50ms*/
        TL0=(65536-Fosc/12/20);
        ET0=1;/*开定时器0中断允许*/
        TR0=0;/*关闭定时器0*/
        EA=1;/*打开总中断*/



        while(1)
        {       

        WDT_CONTR=0x34;/*12.000MHz,看门狗溢出时间为1秒左右,溢出之后看门狗复位*/
        /*喂狗*/
        RELAY=1;/*打开继电器*/
        if(BZ_flag==1)
        {
            BZ=1;
            for(n=7;n>0;n--)
                display(Num);
            BZ=0;
            BZ_flag=0;   
        }
        if(flag==1)/*数码管显示*/
            display(Num);
        else/*关闭数码管显示*/
        {
           //DS1=1;DS2=1;DS3=1;
            GPIO_DIG=0;
        }
        }                          
}
void Timr0() interrupt 1
{
        Time++;
    if(Time==1200)
    {
        Time=0;
        Num--;
        if(Num<=0)
        {
            Num=180;
            RELAY=0;/*关闭继电器*/
            TR0=0;/*关闭定时器0*/
            GPIO_DIG=0;/*关闭数码管*/
            flag=1;
            PCON=0x02;/*掉电模式,单片机睡觉*/
        }   
    }
}

void Int0() interrupt 0
{
    display(Num);/*这个函数执行大约10毫秒时间  按键延时消抖*/
    if(S2==0)
    {
        BZ_flag=1;
        flag=~flag;/*数码管显示位取反*/
    }
}

void Int1() interrupt 2
{   
    display(Num);/*这个函数执行大约10毫秒时间  按键延时消抖*/
    if(S1==0)
    {
        BZ_flag=1;
        TR0=~TR0;/*定时器0启动关闭切换*/
            Num--;/*显示时间减1说明定时器0是已经启动或者关闭进行了切换*/
        flag=1;
    }

}

void Int4() interrupt 16
{
    display(Num);/*这个函数执行大约10毫秒时间  按键延时消抖*/
    if(S3==0)
    {   
        BZ_flag=1;
        if((TR0==0)&&(flag==1))/*当定时器0关闭和数码管显示时才可以进行调节时间*/
        {
            Num=Num-15;
            if(Num<=0)
            Num=180;
        }
    }
}
void display(unsigned int b)
{
    unsigned char bit100,bit10,bit1;
    unsigned int a;
        a=b;
        bit100=a/100;/*提取百位*/
        a=a%100;

        bit10=a/10;/*提取十位*/

        bit1=a%10;/*提取个位*/

    if(b>=100)
    {  
        DS1=1;
            /*送出数字段码*/
            GPIO_DIG=DIG[bit100];
            DS3=0; /*打开第一个数码的位选*/
        Delay3ms();
            DS3=1;
            /*送出数字段码*/
            GPIO_DIG=DIG[bit10];
            DS2=0;/*打开第二个数码的位选*/
        Delay3ms();
        DS2=1;
            /*送出数字段码*/
            GPIO_DIG=DIG[bit1];
            DS1=0;/*打开第三个数码的位选*/
        Delay3ms();
    }
    else if((b>=10)&&(b<100))
    {   
        DS1=1;
        Delay3ms();
            /*送出数字段码*/
            GPIO_DIG=DIG[bit10];
            DS2=0;/*打开第二个数码的位选*/
        Delay3ms();
        DS2=1;
            /*送出数字段码*/
            GPIO_DIG=DIG[bit1];
            DS1=0;/*打开第三个数码的位选*/
        Delay3ms();
    }
    else
    {
        DS1=1;
        Delay3ms();
        Delay3ms();
            /*送出数字段码*/
            GPIO_DIG=DIG[bit1];
            DS1=0;/*打开第三个数码的位选*/
        Delay3ms();
    }

}        

void Delay3ms()                //@12.000MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        i = 36;
        j = 1;
        do
        {
                while (--j);
        } while (--i);
}


    Sheet2.pdf (2015-1-31 21:04 上传)

    74.73 KB, 下载次数: 8

    定时器.pdf (2015-1-31 21:04 上传)

    103.11 KB, 下载次数: 6

回复评论 (19)

中断里面延时,当然会有闪烁的。
点赞  2015-1-31 21:46
那要怎么弄呢?
按键按下不是要延时消抖吗?
点赞  2015-1-31 23:05
引用: werjufour 發表於 2015-1-31 23:05
那要怎麼弄呢?
按鍵按下不是要延時消抖嗎?
多想想,延时要怎么写,才不会在循环绕,将mcu都耗在循环了



点赞  2015-2-1 22:42
需要多任务思想才能解决。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我的博客
点赞  2015-2-2 13:42
这个比较麻烦,中断里面占用的时间太多,导致没时间刷屏。
专业电子方案/zigbee方案设计,毕业设计。QQ:1397905781
点赞  2015-2-2 14:35
中断的处理,越简短越好
So TM what......?
点赞  2015-2-2 18:19
使用定时器中断来扫描显示。定时器的中断优先级设高。
点赞  2015-2-2 20:08
引用: 延时可以用定时器落,但是外部中断里的延时也用定时器来延时吗?这样做不是很复杂吗?




点赞  2015-2-2 22:11
引用: 你好!
什么是多思想任务呢?





点赞  2015-2-2 22:12
例如实时操作系统。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我的博客
点赞  2015-2-3 08:22
引用: 不太明白你说的意思,能够集体点吗?




点赞  2015-2-3 22:14
引用:

程序更改后,按键按下之后数码管不在闪烁了,但是,我按键按下时蜂鸣器响不知道该放哪儿了,能够给点提示吗?


点赞  2015-2-3 22:20
引用:
/*************************************************************
实验效果:用定时器定时来控制继电器的工作,初始时定时为150分钟、
继电器吸合、同时所定的时间在三位数码管上显示出来。开始时定时器
工作,按下S1定时器工作,每过1分钟时间减1,当所定的150分钟减为0时
继电器释放、定时器不工作、数码管不显示单片机进入掉电模式。按下S1、
S2、S3均可唤醒单片机。S1的作用是按下该键时定时器关闭或者启动之间
进行切换,S2的作用是按下该键时数码管显示或者不显示之间进行切换,
S3的作用是只有定时器关闭和数码管显示时按下该键才起作用,每按
该键定时时间减15分钟。同时每个按键按下时都会发出滴的一声。晶振采
用12MHZ.
****************************************************************/
#include"STC15F204EA.h"
#include
#define GPIO_DIG P1
#define Fosc 12000000

sbit DS1=P3^7;
sbit DS2=P0^0;/*我所使用的单片机是A版本P0.0。B版本为P5.4*/
sbit DS3=P0^1;/*我所使用的单片机是A版本,所以这里用P0.1。B版本为P5.5*/      
sbit S3=P3^0;
sbit S2=P3^2;
sbit S1=P3^3;
sbit BZ=P3^4;
sbit RELAY=P3^5;
int Time, Num=150;
unsigned char bit100,bit10,bit1;
unsigned char code DIG[10]={0x7e,0x0c,0xb6,0x9e,0xcc,0xda,0xfa,0x0e,0xfe,0xde};
void Delay3ms();                //@12.000MHz
void Delay10ms();                //@12.000MHz

main()
{       
    unsigned int a;
    BZ=0;
    /*喂狗*/
    WDT_CONTR=0x34;/*12.000MHz,看门狗溢出时间为1秒左右,溢出之后看门狗复位*/
    P5M0=0x30;
    P3M0=0xB0;
          P1M0=0XFF;
   
    IT1=1;/*外部中断1为下降沿触发方式*/
    IT0=1;/*外部中断0为下降沿触发方式*/
    INT_CLKO=0x40;/*允许外部中断4中断*/
    EX1=1;/*允许外部中断1中断*/
    EX0=1;/*允许外部中断0中断*/       

    TMOD=0x00;/*设定定时器0、1工作模式为0*/
        AUXR=0x00;/*设定定时器0、1工作在12T模式*/
        TH0=(65536-Fosc/12/20)>>8;/*给定时器0赋初值,定时50ms*/
        TL0=(65536-Fosc/12/20);
        TH1=(65536-3*Fosc/12000)>>8;/*给定时器0赋初值,定时3ms*/
        TL1=(65536-3*Fosc/12000);
        ET0=1;/*开定时器0中断允许*/
        ET1=1;/*开中断允许*/
    PT1=1;/*设置定时器1为高优先级*/
        TR0=0;/*关闭定时器0*/
        TR1=1;/*关闭定时器1*/
        EA=1;/*打开总中断*/



        while(1)
        {       

        WDT_CONTR=0x34;/*12.000MHz,看门狗溢出时间为1秒左右,溢出之后看门狗复位*/
        /*喂狗*/
            a=Num;
            bit100=a/100;/*提取百位*/
            a=a%100;
   
            bit10=a/10;/*提取十位*/
   
            bit1=a%10;/*提取个位*/
        RELAY=1;/*打开继电器*/

        if(TR1==0)/*关闭数码管显示*/
        {
           //DS1=1;DS2=1;DS3=1;
            GPIO_DIG=0;
        }
        }                          
}
void Timr0() interrupt 1
{
        Time++;
    if(Time==20)
    {
        Time=0;
        Num--;
        if(Num<=0)
        {
            Num=180;
            RELAY=0;/*关闭继电器*/
            TR0=0;/*关闭定时器0*/
            GPIO_DIG=0;/*关闭数码管*/
            TR1=0;
            PCON=0x02;/*掉电模式,单片机睡觉*/
        }   
    }
}

void Int0() interrupt 0
{
    Delay10ms();
    if(S2==0)
    {
        TR1=~TR1;/*数码管显示位取反*/

    }   
}

void Int1() interrupt 2
{   
    Delay10ms();
    if(S1==0)
    {
        TR0=~TR0;/*定时器0启动关闭切换*/
        if(TR0==1)
            Num--;/*显示时间减1说明定时器0是已经启动或者关闭进行了切换*/
    }
}

void Int4() interrupt 16
{
    Delay10ms();
    if(S3==0)
    {   
        if((TR0==0)&&(TR1==1))/*当定时器0关闭和数码管显示时才可以进行调节时间*/
        {
            Num=Num-15;
            if(Num<=0)
            Num=180;
        }
    }
}
void Timr1() interrupt 3
{

    unsigned char n;
   
    if(Num>=100)
    {
        switch(n)
        {
            case(0):DS1=1;/*关闭第3位数码管显示*/                      
                        GPIO_DIG=DIG[bit100];/*送出数字段码*/
                        DS3=0; /*打开第一个数码的位选*/
                    break;
            case(1):DS3=1;/*关闭第1位数码管显示*/                 
                        GPIO_DIG=DIG[bit10];/*送出数字段码*/
                        DS2=0;/*打开第二个数码的位选*/
                    break;
            case(2):DS2=1;/*关闭第2位数码管显示*/                       
                        GPIO_DIG=DIG[bit1];/*送出数字段码*/
                        DS1=0;/*打开第三个数码的位选*/
                    break;
        }
    }
    else if((Num>=10)&&(Num<100))
    {   
        switch(n)
        {            
            case(0): DS1=1;/*关闭第3位数码管显示*/
                     break;                      
            case(1): DS3=1;/*关闭第1位数码管显示*/               
                          GPIO_DIG=DIG[bit10];/*送出数字段码*/
                         DS2=0;/*打开第二个数码的位选*/
                     break;
            case(2): DS2=1;/*关闭第2位数码管显示*/                       
                         GPIO_DIG=DIG[bit1];/*送出数字段码*/
                          DS1=0;/*打开第三个数码的位选*/
                     break;
        }
    }
    else
    {
        switch(n)
        {
            case(0): DS1=1;/*关闭第3位数码管显示*/
                     DS3=1;/*关闭第1位数码管显示*/
                     break;            
            case(1): DS2=1;/*关闭第2位数码管显示*/
                     break;      
            case(2): GPIO_DIG=DIG[bit1];/*送出数字段码*/
                         DS1=0;/*打开第三个数码的位选*/
                     break;
        }
    }
    n++;
    if(n>2)
    n=0;
}        

void Delay3ms()                //@12.000MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        i = 36;
        j = 1;
        do
        {
                while (--j);
        } while (--i);
}
void Delay10ms()                //@12.000MHz
{
        unsigned char i, j;

        _nop_();
        _nop_();
        i = 117;
        j = 183;
        do
        {
                while (--j);
        } while (--i);
}




点赞  2015-2-3 22:24
引用: werjufour 发表于 2015-2-3 22:20
程序更改后,按键按下之后数码管不在闪烁了,但是,我按键按下时蜂鸣器响不知道该放哪儿了,能够给点提示吗?
看不明白。



点赞  2015-2-4 20:11
引用: 我说的问题看不明白呢?还是我的程序呢?我说我按下按键的时候,要让蜂鸣器响,就刚才那个程序该怎么加入这一功能



点赞  2015-2-4 20:52
“按键按下之后数码管不在闪烁了,但是,我按键按下时蜂鸣器响不知道该放哪儿了”
是这里看不明白。
点赞  2015-2-7 20:10
用了那么多中断,它们之间也是会相互影响的。
点赞  2015-3-10 01:09
可以试下赛元的触摸MCU,Q2593454153
  • QQ图片20150310103447.png
点赞  2015-3-10 10:59
楼主 你好  能加个Q好友么 我也遇到了同样问题 能交流一下么 如果可以的话+QQ2433688846
点赞  2015-8-7 22:35
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复