标题: 51单片机数码管秒表程序一直有问题,请大佬们帮忙看一下 [打印本页]

作者: TETR    时间: 2018-3-19 00:06
标题: 51单片机数码管秒表程序一直有问题,请大佬们帮忙看一下
这个是一个51单片机的数码管秒表,其中K1按下后开始计数,K2按下后暂停计数,C1、C2是数码管位选,P0为段选,下载进proteus以后数码管只显示00,并没有按秒计数,下面是示意图和程序。谢谢各位了。

  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int

  4. uchar nushi,ge;
  5. uchar counter1=0;
  6. uint temp;
  7. sbit C1=P2^0;
  8. sbit C2=P2^1;
  9. sbit KEY0=P1^0;        
  10. sbit KEY1=P1^1;
  11. unsigned char code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};        //数码管段码
  12. unsigned char num;

  13. void delayms(uint xms) //延时xms
  14. {
  15.         uint i,j;
  16.         for(i=xms;i>0;i--)
  17.                 for(j=110;j>0;j--);
  18. }


  19. void display(uchar shi,uchar ge)//数码管显示
  20. {                        
  21.         
  22.                                 C1=0;
  23.                                 C2=1;
  24.                                 P0=duan[shi];
  25.                                 delayms(50);
  26.         
  27.                                 C1=1;
  28.                                 C2=0;
  29.                                 P0=duan[ge];
  30.                                 delayms(50);
  31.                                 C1=0;
  32.                                 C2=0;
  33.                 }

  34. void Timer1(void) interrupt 1        //数码管计时
  35. {           
  36.         uchar t;
  37.         TR0=0;
  38.         TH0=(65536-45872)/256;
  39.         TL0=(65536-45872)%256;

  40.         t++;
  41.         if(t==20)
  42.                 {
  43.                         t=0;
  44.                         if(num==60)
  45.                                 num=0;
  46.                         if(counter1==1)
  47.                                 num++;
  48.                         else
  49.                                 num=num;
  50.                         
  51.                                 shi=num/10;
  52.                                 ge=num%10;
  53.                 }               
  54.         TR0=1;
  55. }

  56. void init(void)
  57. {
  58.         TMOD=0x21;
  59.         TH0=(65536-45872)/256;
  60.         TL0=(65536-45872)%256;
  61.         EA=1;                //开总中断
  62.         ET0=1;
  63.         TR0=1;
  64.         ET1=1;
  65.         TR1=1;
  66. }
  67.         void main()
  68. {
  69.         init();
  70.                
  71.         while(1)
  72.         {
  73.                 if(KEY0==0)
  74.         {
  75.                 delayms(5);
  76.                 if(KEY0==0)
  77.                 {
  78.                         counter1=1;
  79.                 }
  80.         }
  81.         if(KEY1==0)
  82.         {
  83.                 delayms(5);
  84.                 if(KEY1==0)
  85.                 {
  86.                         counter1=0;
  87.                 }
  88.         }
  89.                 display(shi,ge);
  90.                
  91.          }        
  92. }
复制代码



作者: zl2168    时间: 2018-3-19 08:52
本帖最后由 zl2168 于 2018-3-19 08:59 编辑

实例93  99.9秒秒表
给你介绍一个秒表案例,注意!!网上秒表案例很多,但绝大多数无法证明其正确,我这个案例你可观看操作。

Proteus仿真一下,确认有效。 实例95 99.9秒秒表.rar (38.86 KB, 下载次数: 15)
以上摘自张志良编著《80C51单片机仿真设计实例教程——基于Keil CProteus》清华大学出版社ISBN 978-7-302-41682-1内有常用的单片机应用100案例,用于仿真实验操作,书中电路和程序设计有详细说明,电路与程序真实可靠可信可行,程序语句条条有注解。若需99.99秒,硬件电路增加一位595。软件程序增加0.01s10ms计数器,并修改相应计数显示程序。

作者: TETR    时间: 2018-3-19 10:24
我的程序是自己写的,希望各位能帮助我在这个程序上改进,这对我学习编程会有很大帮助,提前感谢各位
作者: 999333    时间: 2018-3-19 10:27
本帖最后由 999333 于 2018-3-19 10:43 编辑

你太多错误了,我自己改一下,还有你仿真的也有接线错误,另外最好在p0口接上拉电阻

时钟.docx

15.57 KB, 下载次数: 12


作者: TETR    时间: 2018-3-19 10:42
999333 发表于 2018-3-19 10:27
你太多错误了,你自己改一下,就是你仿真的也有接线错误,另外最好p0口接上拉电阻

那个电路图只是示意,我的电路图还有其他部分,都放上来会有点乱,程序我这里编译是没有问题的
作者: ahshmj    时间: 2018-3-19 10:48
shi和ge没有定义吧?定时器1没有用到,就不要运行,也不要开中断。
作者: TETR    时间: 2018-3-19 11:08
ahshmj 发表于 2018-3-19 10:48
shi和ge没有定义吧?定时器1没有用到,就不要运行,也不要开中断。

shi,ge,num是全局变量,可能复制的时候有点问题,num和shi没有分开,但程序里是对的,之后要加串口通信,需要用到定时器1,所以这里开了定时器1
作者: 陈学盟    时间: 2018-3-19 14:34
中断例程中的变量 t 改为全局变量就可以了
作者: 陈学盟    时间: 2018-3-19 14:36
中断例程中的变量t定义为全局变量才能实现计数
作者: 陈学盟    时间: 2018-3-19 14:39
中断例程中的变量t改为全局变量才能计数
作者: 陈学盟    时间: 2018-3-19 14:54
中断例程中的t为本地变量,只有t的初值=19时才可实现计数。但由于t定义为local,实际运行时变量t对应于cpu的寄存器r0~r7之一,如果你的程序中仅有一个中断例程,工作可能正常,如多于1个中断,则必须将t定义为全局变量
作者: zhangxiaozi    时间: 2018-3-19 15:21
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

uchar shi,ge;                //ÃëμÄêÇê®Î»oí¸÷λ
bit start_stop; //Æô¶ˉoíí£Ö1±ê־λ
bit s1_s2;                 //λ1oíλ2Ñ¡Ôñ
uint temp;
sbit C1=P2^0;
sbit C2=P2^1;
sbit KEY0=P1^0; //Æô¶ˉ°′Å¥
sbit KEY1=P1^1; //í£Ö1°′Å¥
unsigned char code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};        //?????
unsigned char num;

void delayms(uint xms) //??xms
{
        uint i,j;
        for(i=0;i<xms;i++)
                                {
                                for(j=0;j<110;j++)
                                {_nop_();}
                                }
}




void Timer1(void) interrupt 1        //?????
{           
        uchar t;
        TR0=0;
        TH0=0xfc;
        TL0=0x66;
       
                                if(s1_s2)
                         {C1=1;C2=0;P0=duan[shi];}
                                else
                                        {C1=0;C2=1;P0=duan[ge];}
                                s1_s2=!s1_s2;
        
                                       
                                if(start_stop)
                                {
                                        if(++t==20)
                                        {
                                                t=0;
                                                if(++num==60) {num=0;}
                                                shi=num/10;
                                                ge=num%10;
                                        }
                                }

               
        TR0=1;
}

void init(void)
{
        TMOD=0x01;
        TH0=0xfc;
        TL0=0x66;
        EA=1;                //????
        ET0=1;
        TR0=1;

}
        void main()
{
        init();
               
        while(1)
        {
                if(KEY0==0)
        {
              delayms(5);
                if(KEY0==0)
                {
                       start_stop=1;
                }
                                                                while(KEY0==0);         //μè′y°′¼üêí·Å
        }
        if(KEY1==0)
        {
                delayms(5);
                if(KEY1==0)
                {
                        start_stop=0;
                }
                                                                while(KEY1==0);                 //μè′y°′¼üêí·Å
        }
               
         }        
}
作者: zhangxiaozi    时间: 2018-3-19 15:22
我帮你修改了一下,用软件仿真是可以的
作者: zhangxiaozi    时间: 2018-3-19 15:25
sbit C1=P2^0;
sbit C2=P2^1;
你把proteus C1和C2改到P2.0和P2.1
如不想改proteus就把程序改成
sbit C1=P3^0;
sbit C2=P3^1;
作者: zhangxiaozi    时间: 2018-3-19 15:27
如果你要定时器1做中断,你必须定义中断函数,暂时做个空函数,不然程序会乱的
作者: TETR    时间: 2018-3-19 18:36
好的,多谢各位,999333的程序是正确的,12楼的程序我还没测。还想继续请教一下,因为我想在这个程序的基础上继续做串口通信,此单片机作为从机,不断向主机发送num的值,目前只是在初始化程序init()里加上开启定时器1的语句ET1=1和TR=1,程序就不能正常运行,这是为什么啊?
作者: ahshmj    时间: 2018-3-19 19:17
TETR 发表于 2018-3-19 11:08
shi,ge,num是全局变量,可能复制的时候有点问题,num和shi没有分开,但程序里是对的,之后要加串口通信, ...

串口通信就更不要开中断了。
作者: TETR    时间: 2018-3-20 00:33
ahshmj 发表于 2018-3-19 19:17
串口通信就更不要开中断了。

计数器和串口都需要中断啊,不开中断要怎么处理呢?




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1