• 已解决 73482 个问题
  • 已帮助 5993 位优秀工程师

如何让其他延时程序进行时不影响数码管动态扫描

Suwian 2016-10-26 浏览量:1835
例如:使用定时器进行一分钟的定时,然后在数码管上显示时,分,秒,然后每到1分钟蜂鸣器会报警3声.
当我进行蜂鸣器的延时时,数码管的动态扫描会暂停我所延时的时间.(单片机现象数码管在蜂鸣器响的时候不显示)
所以问一下大家有什么好的解决方法,谢谢.稍后上传我的源代码.
再次感谢!
1 0 收起

我来回答

上传资料:
选择文件 文件大小不超过15M(格式支持:doc、ppt、xls、pdf、zip、rar、txt)
最佳答案
  • 本帖最后由 MOP 于 2016-10-27 20:12 编辑

    Suwian 发表于 2016-10-27 20:03
    逻辑是对的,但是现象和预想的不符合,我等下回去把电路图和仿真文件发给您,您看看,是不是我哪里还有漏 ...
    嗨,我剛看了ALARM_TIME不用改喔,是5喔,前面沒講清楚抱歉:)
    也就是說除了PNP/NPN的邏輯差別,其他不用改
    之前的alarm()函数的第一个入口的判断为if(MIN>0&&val==0)这个是否也是需要相应的修改,因为第二次进来这个val!=0了。还有那个ALARM_TIME也是要改成6的吧,然后最后的那个判断函数if(beeper)的否则里那个BEEPER应该等于1吧,不然之后会一直响的。这是我的疑问如果说错了帮我解惑一下,谢谢
    再貼一次,就是判斷,ALARM_TIME都不用改,BEEPER會錯意是因為我以為你實體可能沒電晶體或者NPN,而PNP的話如我剛剛提到的初始化跟BEEPER=1即可,這樣應該都沒問題了:)

    • 发布于 2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

其他答案 数量:38
  • 单片机程序,数码管扫描显示,及计时 可以用一个定时器中断来完成,
    比如 8 个数码管 定时器用 2 ~ 2.5 mS,每次中断 刷新 一个数码管,同时可以 设置一个标志位
    在主程序 中记录中断 次数作为 定时 或者 延时,
    如 2.5mS 40次 就是 100mS,如果计时精度 要求高的 可以另外 用一个定时器,
    学会使用定时器,很多问题很好解决的。
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 1
    • 0

  • 本帖最后由 LiuYang 于 2016-10-26 10:55 编辑

    如果可以外接芯片,用8574之类的就可以了,不占用MCU资源;
    或者MCU上小系统,线程延时就可以了。如果不想上系统就用定时器中断吧。


    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 本帖最后由 SingleYork 于 2016-10-26 10:55 编辑

    哎哟,蜂鸣器的延时也用定时器去实现不就好了么?不要用延时函数,延时函数是会在那死延时!你既然会用定时器实现时、分、秒计时,那这个蜂鸣器延时还能难住你?
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 数码管扫描用定时器中断控制状态机,一次扫描显示一位,不要直接在主程序里面扫描延时显示
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 本帖最后由 Suwian 于 2016-10-26 11:38 编辑

    SingleYork 发表于 2016-10-26 10:53
    哎哟,蜂鸣器的延时也用定时器去实现不就好了么?不要用延时函数,延时函数是会在那死延时!你既然会用定时 ...
    谢谢你啊不过,蜂鸣器的响3声的程序不是这样写的吗
    void T1_Time() interrupt 3
    {
    TH1=(65536-50000)/10;
    TL1=(65536-50000)%10;
    num1++;
    if(num1==20)
    {
    num1==0;
    num2++;
    if(num2==60)
    {
    num2=0;
    for(i=3;i>0;i--)
    {
    fm = 0;
    delay(100);
    fm = 1;
    delay(100);
    }

    }

    }



    }
    我说的冲突是上面那个delay延时与数码管的动态扫描冲突

    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 楼主现在在外面,等回去把原程序贴下,谢谢大家!
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 本帖最后由 Suwian 于 2016-10-26 11:35 编辑

    独行客 发表于 2016-10-26 10:57
    数码管扫描用定时器中断控制状态机,一次扫描显示一位,不要直接在主程序里面扫描延时显示 ...
    那要如何把延时程序不影响主函数对数码管的扫描呢,我试过用两个定时器分别控制两个中端定0控制数码管的时分秒显示,定1控制蜂鸣器每1分钟响3声。void T1_Time() interrupt 3
    {
    TH1=(65536-50000)/10;
    TL1=(65536-50000)%10;
    num1++;
    if(num1==20)
    {
    num1=0;
    num2++;
    if(num2==60)
    {
    num2=0;
    for(i=3;i>0;i--)
    {
    fm = 0;
    delay(100);
    fm = 1;
    delay(100);
    }

    }

    }



    }

    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • #include
    #define uchar unsigned char
    #define uint unsigned int
    sbit dula=P2^6;
    sbit wela=P2^7;
    sbit fm = P2^3;
    uchar shi,ge,f_shi,f_ge,s_shi,s_ge,num,num1,num2,val;
    uchar CLK,MIN;
    uchar i=3;
    uchar code table[]={

    0x3F, //"0"
    0x06, //"1"
    0x5B, //"2"
    0x4F, //"3"
    0x66, //"4"
    0x6D, //"5"
    0x7D, //"6"
    0x07, //"7"
    0x7F, //"8"
    0x6F //"9"


    };


    void delay(uint xms)
    {
    uint i,j;
    for(i=xms;i>0;i--)
    for(j=110;j>0;j--);

    }

    void display1(uchar shi,uchar ge)
    {

    P0=0xfe;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0xfd;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void display2(uchar shi,uchar ge)
    {

    P0=0xf7;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0xef;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void display3(uchar shi,uchar ge)
    {

    P0=0xbf;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0x7f;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void SFM()
    {
    if(num==20)
    {
    num=0;
    val++;

    if(val==60)
    {
    val=0;
    MIN++;
    // while(i--)
    // {
    // fm=0;
    // delay(100);
    // fm=1;
    // delay(100);
    //
    // }
    // i=3;
    //
    if(MIN==60)
    {
    MIN=0;

    CLK++;
    if(CLK==1)
    CLK=0;
    }
    }
    shi = val/10;
    ge = val%10;
    f_shi = MIN/10;
    f_ge = MIN%10;
    s_shi = CLK/10;
    s_ge = CLK%10;
    }

    }
    void main()
    {
    TMOD=0x11;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    TH1=(65536-50000)/256;
    TL1=(65536-50000)%256;
    EA=1;
    ET0=1;
    ET1=1;
    TR1=1;
    TR0=1;
    while(1)
    {
    SFM();

    display3(shi,ge);

    display2(f_shi,f_ge);

    display1(s_shi,s_ge);




    }

    }


    void T0_Time() interrupt 1
    {
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    num++;
    //num1++;

    }
    void T1_Time() interrupt 3
    {
    TH1=(65536-50000)/256;
    TL1=(65536-50000)%256;
    num1++;
    if(num1==20)
    {
    num1=0;
    num2++;
    if(num2==60)
    {
    num2=0;
    while(i--)
    {
    fm=0;
    delay(100);
    fm=1;
    delay(100);

    }
    i=3;
    }
    }


    }
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • SingleYork 发表于 2016-10-26 10:53
    哎哟,蜂鸣器的延时也用定时器去实现不就好了么?不要用延时函数,延时函数是会在那死延时!你既然会用定时 ...

    #include
    #define uchar unsigned char
    #define uint unsigned int
    sbit dula=P2^6;
    sbit wela=P2^7;
    sbit fm = P2^3;
    uchar shi,ge,f_shi,f_ge,s_shi,s_ge,num,num1,num2,val;
    uchar CLK,MIN;
    uchar i=3;
    uchar code table[]={

    0x3F, //"0"
    0x06, //"1"
    0x5B, //"2"
    0x4F, //"3"
    0x66, //"4"
    0x6D, //"5"
    0x7D, //"6"
    0x07, //"7"
    0x7F, //"8"
    0x6F //"9"


    };


    void delay(uint xms)
    {
    uint i,j;
    for(i=xms;i>0;i--)
    for(j=110;j>0;j--);

    }

    void display1(uchar shi,uchar ge)
    {

    P0=0xfe;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0xfd;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void display2(uchar shi,uchar ge)
    {

    P0=0xf7;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0xef;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void display3(uchar shi,uchar ge)
    {

    P0=0xbf;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0x7f;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void SFM()
    {
    if(num==20)
    {
    num=0;
    val++;

    if(val==60)
    {
    val=0;
    MIN++;
    // while(i--)
    // {
    // fm=0;
    // delay(100);
    // fm=1;
    // delay(100);
    //
    // }
    // i=3;
    //
    if(MIN==60)
    {
    MIN=0;

    CLK++;
    if(CLK==1)
    CLK=0;
    }
    }
    shi = val/10;
    ge = val%10;
    f_shi = MIN/10;
    f_ge = MIN%10;
    s_shi = CLK/10;
    s_ge = CLK%10;
    }

    }
    void main()
    {
    TMOD=0x11;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    TH1=(65536-50000)/256;
    TL1=(65536-50000)%256;
    EA=1;
    ET0=1;
    ET1=1;
    TR1=1;
    TR0=1;
    while(1)
    {
    SFM();

    display3(shi,ge);

    display2(f_shi,f_ge);

    display1(s_shi,s_ge);




    }

    }


    void T0_Time() interrupt 1
    {
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    num++;
    //num1++;

    }
    void T1_Time() interrupt 3
    {
    TH1=(65536-50000)/256;
    TL1=(65536-50000)%256;
    num1++;
    if(num1==20)
    {
    num1=0;
    num2++;
    if(num2==60)
    {
    num2=0;
    while(i--)
    {
    fm=0;
    delay(100);
    fm=1;
    delay(100);

    }
    i=3;
    }
    }


    }
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 我想你应该这样实现,把蜂鸣器的响的时间做一个基数,然后一分钟等于1/基数,这样就是你中断的时间,你在定时器里设置这个时间,检测时间是不是到了,到了以后蜂鸣器响,然后判断蜂鸣器响的次数,这样没进一次中断检测一下蜂鸣器并耗不了多少时间的,
    响三次需要翻转电平六次,这样变量等于六的时候蜂鸣器不响,到了一分钟变量置0就可以了!不理解的话晚上给你代码
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 瞎折腾 发表于 2016-10-26 12:28
    我想你应该这样实现,把蜂鸣器的响的时间做一个基数,然后一分钟等于1/基数,这样就是你中断的时间,你在定 ...

    你好,我还是不太理解这个意思,之前我有想过用翻转电平的方法,但是不知道要怎么实现,如果可以的话教一下我。谢谢!
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 本帖最后由 MOP 于 2016-10-26 15:43 编辑

    嗨,最簡單的方式可參考我的文章//www.icxbk.com/community/forum.php?mod=viewthread&tid=67282&extra=
    概念是一樣的,使用到TimeDisplay這個變數翻轉時候觸發一次,即1秒,這觸發是由RTC的ISR來的,只要一個定時器就可完成不中斷時鐘和持續N秒的蜂鳴器鳴叫

    所以您要改的話,一樣有關I/O的最好還是宣告成volatile,再來因為您要蜂鳴器鳴叫也是以秒為最小單位(假設),所以一樣ˋ只要一個定時器
    volatile uchar num;
    您的Code Interrupt中遞增的是num變數

    void T0_Time()  interrupt 1
    {
      TH0=(65536-50000)/256;
      TL0=(65536-50000)%256;
      num++;
    }
    所以只要保留這個Interrupt,要實現您的功能,參考我的文章以後,增加以下
    uchar beeper = 0; //global
    uchar started=0; //global
    
    #define BEEPER(x) //要控制的GPIO Output Pin,假設0輸出低電位,1輸出高電位
    #define ALARM_TIME 3
    
    void alarm(void)
    {
    
      if(MIN>0 && val==0) // When booting up, the beeper didn't need to beep.
      {
          if(!started)
           started=1;
      }
    
      if(started && val==0)
      {
        if(!beeper)
          beeper=1;
      }
      
        if(beeper)
      {
        if(val說明也可參考我的文章,您只要實現BEEPER函式即可,這裡我用Macro,您可以自己定義哪個腳位跟實現輸出,另外變數名稱最好有意義跟小寫,#define才大寫,培養好的寫程式習慣很重要:)

    最後加入您的While loop即可
       while(1)
       {
                 SFM();
                 display3(shi,ge);
              display2(f_shi,f_ge);
              display1(s_shi,s_ge);
              alarm();
       }



    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 本帖最后由 Suwian 于 2016-10-26 21:28 编辑

    MOP 发表于 2016-10-26 21:21
    嗯 不懂得可以再發問
    这样修改后蜂鸣器没有声音是为什么?
    #include
    #define uchar unsigned char
    #define uint unsigned int
    #define BEEPER(x) //要控制的GPIO Output Pin,假設0輸出低電位,1輸出高電位
    #define ALARM_TIME 3
    sbit dula=P2^6;
    sbit wela=P2^7;
    sbit fm = P2^3;
    uchar beeper = 0; //global
    uchar started=0; //global
    volatile uchar shi,ge,f_shi,f_ge,s_shi,s_ge,num,num1,num2,val;
    uchar CLK,MIN;
    uchar code table[]={

    0x3F, //"0"
    0x06, //"1"
    0x5B, //"2"
    0x4F, //"3"
    0x66, //"4"
    0x6D, //"5"
    0x7D, //"6"
    0x07, //"7"
    0x7F, //"8"
    0x6F //"9"


    };


    void delay(uint xms)
    {
    uint i,j;
    for(i=xms;i>0;i--)
    for(j=110;j>0;j--);

    }

    void display1(uchar shi,uchar ge)
    {

    P0=0xfe;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0xfd;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void display2(uchar shi,uchar ge)
    {

    P0=0xf7;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0xef;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void display3(uchar shi,uchar ge)
    {

    P0=0xbf;
    wela=1;
    wela=0;
    P0=table[shi];
    dula=1;
    dula=0;
    delay(3);


    P0=0x7f;
    wela=1;
    wela=0;
    P0=table[ge];
    dula=1;
    dula=0;
    delay(3);



    }
    void SFM()
    {
    if(num==20)
    {
    num=0;
    val++;

    if(val==60)
    {
    val=0;
    MIN++;

    if(MIN==60)
    {
    MIN=0;

    CLK++;
    if(CLK==1)
    CLK=0;
    }
    }
    shi = val/10;
    ge = val%10;
    f_shi = MIN/10;
    f_ge = MIN%10;
    s_shi = CLK/10;
    s_ge = CLK%10;
    }

    }

    void alarm(void)
    {

    if(MIN>0 && val==0) // When booting up, the beeper didn't need to beep.
    {
    if(!started)
    started=1;
    }

    if(started && val==0)
    {
    if(!beeper)
    beeper=1;
    }

    if(beeper)
    {
    if(val BEEPER(1);
    else
    {
    BEEPER(0);
    beeper=0;
    }
    }

    }

    void main()
    {
    TMOD=0x01;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    // TH1=(65536-50000)/256;
    //TL1=(65536-50000)%256;
    EA=1;
    ET0=1;
    // ET1=1;
    // TR1=1;
    TR0=1;
    while(1)
    {
    SFM();
    display3(shi,ge);
    display2(f_shi,f_ge);
    display1(s_shi,s_ge);
    alarm();
    }


    }


    void T0_Time() interrupt 1
    {
    TH0=(65536-50000)/256;
    TL0=(65536-50000)%256;
    num++;

    }
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • Suwian 发表于 2016-10-26 13:18
    你好,我还是不太理解这个意思,之前我有想过用翻转电平的方法,但是不知道要怎么实现,如果可以的话教一 ...
    如果是十六位重装可以定时5毫秒,一秒就是二百次,这个定时也就是你蜂鸣器要一次响5毫秒
    u8 fmq;
    进入一秒的时候
    fmq=0;
    在中断的最后加上
    if (fmq<7)
    {fm=~fm;
    }
    else
    {fmq=7;//这是为了怕你定时短的话,fmq会最后自动加到255后归0.
    }
    这样每秒就会fmq=0一次,fm的电平就会翻转,每次定时器进入中断主要fmq的值小于7,电平就会翻转一次,六次以后就不翻转了!
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 本帖最后由 MOP 于 2016-10-26 22:13 编辑

    Suwian 发表于 2016-10-26 21:27
    这样修改后蜂鸣器没有声音是为什么?
    #include
    #define uchar unsigned char
    噗,我文章有提醒您要自己定義Beeper的PIN腳位設置成GPIO輸出,因為我看你的Code似乎沒看到Beeper的定義腳位,記得要設置成Push-pull Output

    假設Beeper接在P30腳位
    
    那麼
    sbit  P30 = P3^0;
    
    #define BEEPER(X) ((X)? P30=1:P30=0)
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

  • 瞎折腾 发表于 2016-10-26 21:55
    如果是十六位重装可以定时5毫秒,一秒就是二百次,这个定时也就是你蜂鸣器要一次响5毫秒
    u8 fmq;
    进入一 ...

    你好,这样蜂鸣器发声的频率会不会太快啊,我之前试过现象是一下次就没了,
    • 发布于2016-10-26
    • 举报
    • 评论 0
    • 0
    • 0

相关问题

问题达人换一批

如何让其他延时程序进行时不影响数码管动态扫描