找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2793|回复: 15
打印 上一主题 下一主题
收起左侧

单片机秒表程序显示问题

[复制链接]
跳转到指定楼层
楼主
220黑币
程序要求按 A 键再按 B 键后,显示两键按下之间的时间 t(t <60s),单位为 ms。时间 t 用五位十进制整数显示,由一位数码管从最高位开始逐位显示一遍。可是我的程序在按键之后显示的数字好像和时间不对应,请问大佬们这是哪里出错了?另外还要求转成BCD码后译码显示输出,这个应该怎么改?
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
uint m=0;
sbit A1=P3^4;
sbit A2=P3^5;
uint count,t;
uchar d,e,f;
uchar code table[]={0x14,0xde,0x38,0x1a,0xd2,0x13,0x11,0x9e,0x10,0x12};
uchar code cnt[]={10000,1000,100,10,1};
void delay(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=67;c>0;c--)
        for(b=124;b>0;b--)
            for(a=167;a>0;a--);
}

void start()
{
        TMOD=0x01; //T0 使用工作方式 1
        TH0=(65536-1000)/256; //1ms 定时
        TL0=(65536-1000)%256;
        EA=1;
        ET0=1;
        TR0=0;
}
void time0(void) interrupt 1 //T0 中断服务子程序
{
        TH0=(65536-1000)/256;
        TL0=(65536-1000)%256;
        count++;
        if(count>=1)
        {count=0;
         t++;
         if(t>=60000)
         {t=0;}
        }
}


void display(uint t)  //显示子程序,从第一位开始逐位显示
{
         uint k=0,v;
         for(;k<5;k++)
         {
                 v=t/cnt[k]%10 ;
                 P0=table[v];
                delay();
            {for(f=23;f>0;f--)
                for(e=152;e>0;e--)
                    for(d=70;d>0;d--)
                                P0=0xFF;
                }
         }

}
void main(void)
{        start();
while(1)
{
        P0=0xb7;
        P3=0x30;
        if(P3!=0x30)
        {if(A1==0)                          //按键扫描
                {TR0=1;}
         if(A2==0)
                 {
                        TR0=0;
                        while(!A2);
                        while(P3==0x30)
                        {
                                display(t);
                        }
                }
        
        }               
}
}

捕获.PNG (103.72 KB, 下载次数: 78)

捕获.PNG

图片.png (36.73 KB, 下载次数: 76)

图片.png

最佳答案

查看完整内容

完全下图做时间电路和程序,共阳数码管,可以实现楼主想要的功能。 A、B 键互锁,不需要消抖,用闪烁表示换显示位,否则相邻数字相同无法分辨。小数点前为妙,小数点后为毫秒。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2020-7-13 21:19 | 只看该作者
完全下图做时间电路和程序,共阳数码管,可以实现楼主想要的功能。 A、B 键互锁,不需要消抖,用闪烁表示换显示位,否则相邻数字相同无法分辨。小数点前为妙,小数点后为毫秒。


  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit A1=P3^4;
  5. sbit A2=P3^5;
  6. uint m=0;
  7. uint count,t;
  8. uchar code table[]={//共阳数码管"0~f .-"
  9.         0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  10.         0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f};
  11. uchar cnt[6]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0};//小数缓存
  12. bit flag=0;
  13. bit sign=0;
  14. bit init=0;

  15. void start()
  16. {
  17.         TMOD=0x01; //T0 使用工作方式 1
  18.         TH0=(65536-1000)/256; //1ms 定时
  19.         TL0=(65536-1000)%256;
  20.         EA=1;
  21.         ET0=1;
  22.         TR0=1;
  23. }

  24. void display()  //显示子程序,从第一位开始逐位显示't 00秒 000毫秒'
  25. {
  26.         static uint j=0;
  27.         if(sign)
  28.                 P0=0xbf;//等待计数时显示'-'
  29.         else
  30.         {       
  31.                 if(j<=900)
  32.                         P0=cnt[m];
  33.                 else if(init==1)
  34.                         P0=0xff;//闪烁表示换位显示
  35.                 j++;
  36.                 if(j>=1000)
  37.                 {
  38.                         j=0;
  39.                         m++;
  40.                         m%=6;
  41.                 }
  42.         }
  43. }
  44. void main(void)
  45. {
  46.         start();
  47.         P0=0xc0;//初始显示0
  48.         while(1)
  49.         {
  50.                 if(A1==0 && flag==0) //按键扫描
  51.                 {
  52.                         flag=1;
  53.                         count=0;                               
  54.                         t=0;
  55.                         sign=1;
  56.                         init=1;
  57.                 }
  58.                 if(A2==0 && flag==1)
  59.                 {
  60.                         sign=0;
  61.                         flag=0;
  62.                         cnt[0]=0x87;
  63.                         cnt[1]=table[t/10];
  64.                         cnt[2]=table[t%10]&0x7f;//加秒点
  65.                         cnt[3]=table[count/100];
  66.                         cnt[4]=table[count/10%10];
  67.                         cnt[5]=table[count%10];
  68.                         m=0;
  69.                 }
  70.         }
  71. }

  72. void time0(void) interrupt 1 //T0 中断服务子程序
  73. {
  74.         TH0=(65536-1000)/256;
  75.         TL0=(65536-1000)%256;
  76.         if(sign)
  77.         {
  78.                 count++;
  79.                 if(count>=1000)
  80.                 {
  81.                         count=0;
  82.                         t++;
  83.                         if(t>=60)
  84.                         {
  85.                                 t=0;
  86.                         }
  87.                 }
  88.         }
  89.         display();
  90. }
复制代码



回复

使用道具 举报

板凳
ID:789121 发表于 2020-7-13 23:12 | 只看该作者
要不要把源文件发上来测试一下
回复

使用道具 举报

地板
ID:451718 发表于 2020-7-14 16:33 | 只看该作者
1,为什么要在没有时间定标的主循环中去控制定时器?  时钟就一直让它走,只去采集和记录就好了吗。 你乱控制主定时的TR0,  时间不乱才怪。
2,   count++;
        if(count>=1)
        {count=0;
         t++;
这段是干啥?     实在无法理解。
3,   8段数码管输出的不是BCD码。是你那个table[]数组对应的控制值,而且这个值分阴码和阳码,根据你P0口的线序不同,这个控制值也会不同。(为什么要线序不同? 等你自己布线经验多一点就明白了)  你这个显示子程序,有点花。  不太容易懂的,也不利于你弄明白LED的显示原理。想弄明白,还是找教程看吧,论坛上就有的。
回复

使用道具 举报

5#
ID:797796 发表于 2020-7-14 16:41 | 只看该作者
wulin 发表于 2020-7-14 12:31
完全下图做时间电路和程序,共阳数码管,可以实现楼主想要的功能。 A、B 键互锁,不需要消抖,用闪烁表示换 ...

感谢大佬!!另外框图要求转成BCD码后译码显示输出,你这个显示子程序是不是也算是符合呢?
回复

使用道具 举报

6#
ID:797796 发表于 2020-7-14 16:45 | 只看该作者
本帖最后由 Irvingzong 于 2020-7-14 16:48 编辑
robinsonlin 发表于 2020-7-14 16:33
1,为什么要在没有时间定标的主循环中去控制定时器?  时钟就一直让它走,只去采集和记录就好了吗。 你乱控 ...

噢噢好的,师傅要求转成BCD码后译码用十进制显示输出,这个是怎么理解呢?我感觉没有用到BCD码呀
回复

使用道具 举报

7#
ID:213173 发表于 2020-7-14 20:42 | 只看该作者
Irvingzong 发表于 2020-7-14 16:41
感谢大佬!!另外框图要求转成BCD码后译码显示输出,你这个显示子程序是不是也算是符合呢?

不同的显示设备需要不同的驱动码,LED数码管用的是16进制笔段码。如果非得转成BCD码后再转成笔段码就是自找麻烦了。不过楼主用一个数码管显示5位数也属特殊用法,未见有在实际运用中出现过。
回复

使用道具 举报

8#
ID:213173 发表于 2020-7-14 21:17 | 只看该作者
Irvingzong 发表于 2020-7-14 16:41
感谢大佬!!另外框图要求转成BCD码后译码显示输出,你这个显示子程序是不是也算是符合呢?

改成5或6位数码管显示较为合理


  1. #include<reg51.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit A1=P3^4;
  5. sbit A2=P3^5;
  6. uint m=0;
  7. uint count,t;
  8. uchar code table[]={//共阳数码管"0~f .-"
  9.         0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  10.         0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf,0x7f};
  11. uchar cnt[6]={0x87,0xc0,0xc0,0xc0,0xc0,0xc0};//显示缓存
  12. bit flag=0;//键态标志
  13. bit sign=0;//计时启动标志

  14. void start()
  15. {
  16.         TMOD=0x01; //T0 使用工作方式 1
  17.         TH0=(65536-1000)/256; //1ms 定时
  18.         TL0=(65536-1000)%256;
  19.         EA=1;
  20.         ET0=1;
  21.         TR0=1;
  22. }

  23. void display()  //显示子程序,从第一位开始逐位显示't 00秒 000毫秒'
  24. {
  25.         P2&=0xc0;//位码清0消隐
  26.         P0=cnt[m];//送段码
  27.         P2|=0x01<<m;//送位码
  28.         m++;
  29.         m%=6;
  30. }
  31. void main(void)
  32. {
  33.         start();
  34.         while(1)
  35.         {
  36.                 if(A1==0 && flag==0) //按键扫描
  37.                 {
  38.                         flag=1;
  39.                         count=0;                               
  40.                         t=0;
  41.                         sign=1;
  42.                 }
  43.                 if(A2==0 && flag==1)
  44.                 {
  45.                         flag=0;
  46.                         sign=0;
  47.                 }
  48.         }
  49. }

  50. void time0(void) interrupt 1 //T0 中断服务子程序
  51. {
  52.         TH0=(65536-1000)/256;
  53.         TL0=(65536-1000)%256;
  54.         if(sign)
  55.         {
  56.                 count++;
  57.                 if(count>=1000)
  58.                 {
  59.                         count=0;
  60.                         t++;
  61.                         if(t>=60)
  62.                         {
  63.                                 t=0;
  64.                         }
  65.                 }
  66.         }
  67.         cnt[1]=table[t/10];
  68.         cnt[2]=table[t%10]&0x7f;//加秒点
  69.         cnt[3]=table[count/100];
  70.         cnt[4]=table[count/10%10];
  71.         cnt[5]=table[count%10];
  72.         display();
  73. }
复制代码



回复

使用道具 举报

9#
ID:235954 发表于 2020-7-14 22:40 | 只看该作者
闪烁点可以用GP来制作,也可以用LED来闪烁,这就是基本的定时器应用
回复

使用道具 举报

10#
ID:451718 发表于 2020-7-15 16:16 | 只看该作者
Irvingzong 发表于 2020-7-14 16:45
噢噢好的,师傅要求转成BCD码后译码用十进制显示输出,这个是怎么理解呢?我感觉没有用到BCD码呀

转BCD码是软件层面的要求,可能是用来直接匹配到哪个模块,就可以直接驱动LED8段数码管了。  我跟你讲的是硬件层面的做法,直接用单片机的端口加三极管来驱动LED8段数码管的方法。
回复

使用道具 举报

11#
ID:451718 发表于 2020-7-15 16:21 | 只看该作者
Irvingzong 发表于 2020-7-14 16:41
感谢大佬!!另外框图要求转成BCD码后译码显示输出,你这个显示子程序是不是也算是符合呢?

手把手教你学51单片机-C语言版 PDF电子书下载
http://www.51hei.com/bbs/dpj-48477-1.html
(出处: 单片机论坛)
有C语言基础, 花3天时间看看就能弄明白了
回复

使用道具 举报

12#
ID:797796 发表于 2020-7-15 18:01 | 只看该作者
wulin 发表于 2020-7-14 21:17
改成5或6位数码管显示较为合理

谢谢,不过设计要求用一位数码管,可是你第一个程序的display()函数我不是很能理解,能再解释一下吗
回复

使用道具 举报

13#
ID:797796 发表于 2020-7-16 10:23 | 只看该作者
robinsonlin 发表于 2020-7-15 16:21
手把手教你学51单片机-C语言版 PDF电子书下载
http://www.51hei.com/bbs/dpj-48477-1.html
(出处: 单片 ...

大佬们帮我看下,设计框图规定了显示子程序,所以我把上面大佬的程序display()函数改了一下,可是运行时数据又乱了,请问是按照楼顶的框图应该怎么改?
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit A1=P3^4;
sbit A2=P3^5;
uint m=0;
uint count,t,d,e,f;
uchar code table[]={0x14,0xde,0x38,0x1a,0xd2,0x13,0x11,0x9e,0x10,0x12};
uchar cnt[6]={0};//小数缓存
bit flag=0;
bit init=0;

void delay(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=67;c>0;c--)
        for(b=124;b>0;b--)
            for(a=167;a>0;a--);
}

void start()
{
        TMOD=0x01; //T0 使用工作方式 1
        TH0=(65536-1000)/256; //1ms 定时
        TL0=(65536-1000)%256;
        EA=1;
        ET0=1;
            TR0=1;
}

void display()  //显示子程序,从第一位开始逐位显示't 00秒 000毫秒'
{
        uint j;
        if(flag)
                P0=0xbf;//等待计数时显示'-'
        else
        {        
                                if(init==1)
                                for(j=5;j>=0;j--)
                                {P0=cnt[j];
                                delay();
                                }
        }
}
void main(void)
{
        start();
        P0=0xb7;//上电提示符
        while(1)
        {
                if(A1==0 && flag==0) //按键扫描
                {
                        flag=1;
                        count=0;                                
                        t=0;
                        init=1;                                               
                }
                if(A2==0 && flag==1)
                {
                                                while(!A2);
                        flag=0;
                        cnt[5]=0xbf;
                        cnt[4]=table[t/10];
                        cnt[3]=table[t%10];//加秒点
                        cnt[2]=table[count/100];
                        cnt[1]=table[count/10%10];
                        cnt[0]=table[count%10];
                        m=0;
                }
        }
}

void time0(void) interrupt 1 //T0 中断服务子程序
{
        TH0=(65536-1000)/256;
        TL0=(65536-1000)%256;
        if(flag)
        {
                count++;
                if(count>=1000)
                {
                        count=0;
                        t++;
                        if(t>=60)
                        {
                                t=0;
                        }
                }
        }
        display();
}
回复

使用道具 举报

14#
ID:451718 发表于 2020-7-20 15:49 | 只看该作者
Irvingzong 发表于 2020-7-16 10:23
大佬们帮我看下,设计框图规定了显示子程序,所以我把上面大佬的程序display()函数改了一下,可是运行时 ...

楼上给你的display()函数是驱动8段数码管的程序, 而你的要求好像只是驱动某个BCD值模块的。 都不是一样的目标对象,你如何能改好。 我们做产品的,很少再用模块去辅助驱动8段数码管的,关于BCD值的模块,没有研究过,也没有现成的环境做试验,这里不好给你提供帮助。 但是,最终是驱动8段数码管,所以,以下程序备注很经典,你仔细读懂就会了。
void display()  //显示子程序,从第一位开始逐位显示't 00秒 000毫秒'
{
        P2&=0xc0;//位码清0消隐
        P0=cnt[m];//送段码
        P2|=0x01<<m;//送位码
        m++;
        m%=6;
}
步骤大概就是1,消隐; 2,送段码; 3,送位码; 4,改变循环值; 5,检查限定最大循环值。
回复

使用道具 举报

15#
ID:451718 发表于 2020-7-20 16:03 | 只看该作者
刚刚又看了一下你自己改的程序。 看来你还是没有深刻理解单片机工作方法,特别定时器这块。 你的display()函数里面有 delay(),这个delay()是多长时间?  定时器周期又是多久? 请仔细思考这个问题!!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表