为毛做的时钟走得比较慢,求解释!

2019-07-16 00:11发布

本帖最后由 月影狼迹 于 2013-6-9 14:15 编辑

初学者。用16F877A写的,能显示2001~2099年任意时间、日期和星期。用Protues仿真时,时间走的比电脑时钟慢。求大神分析一下!

#include <pic.h>
__CONFIG(0x3F39);
#define RS RC0
#define RW RC1
#define E  RC2
#define T1_50MS 15536
#define key1 RB0
#define key2 RB1
#define key3 RB2
#define key4 RB3

const char table0[]={'0','1','2','3','4','5','6','7','8','9',' '};               //显示查表表格
const char table1[]={'/',':',' '};
const char table2[]={'S','U','N','M','O','N','T','U','E','W','E','D','T','H','U','F','R','I','S','A','T'};

char num=0,num0=0,num1=0; //定时器计数变量
int sec=0,min=0,hour=0,Years=2000; //时分秒计数变量
char day=1,weekday=0,mon=1,year=1;  //年月日计数变量
char num5=0,num6=0,num7=0; //按键延时计数变量                                                                 
char count1,count2=0,count3=0,count4=0; //按键状态变量
char count5=0,count6=0,count7=0;
char hh=0,hl=0,mh=0,ml=0,sh=0,sl=0,dd;  //时分秒年月日高低位分解寄存
char nh=0,nl=1,yh=0,yl=1,rh=0,rl=1;
char tmp,tmp_days;  //星期几计算中间变量
/******************************************************************/
/*                    函数声明                                    */
/******************************************************************/
void delayms(unsigned int ms)          //ms延时子程序
{
  unsigned int x,y;
  for (x=ms;x>0;x--)
    for (y=110;y>0;y--);
}
/******************************************************************/
void delayus(char us)          //us延时子程序
{
  char x;
  
  x=us;
  while(x>0)
  {
       x--;
       NOP();NOP();NOP();NOP();        
     }
}
/****************************************************************/
void write_com(char com)     //LCD写命令子程序
{
  RS=0;NOP();
  RW=0;NOP();
  PORTD=com;
  delayms(1);
  E=1;
  delayms(1);
  E=0;
}
/****************************************************************/
void write_data(char d)    //LCD写数据子程序
{
  RS=1;NOP();
  RW=0;NOP();
  PORTD=d;
  delayms(1);
  E=1;
  delayms(1);
  E=0;NOP();
  RS=0;
}
/*********************************************************************/
void init()                //初始化子程序
{
     TRISB=0b11111111;
     TRISC=0b00000000;
     TRISD=0b00000000;
     
     TMR0=(65536-50000)/256;
     OPtiON=0b10000111;
     INTCON=0b10100000;
        
     RS=1;NOP();
  RW=0;NOP();
  E=0;
  delayms(20);
  write_com(0b00110000);
  delayms(1);
  write_com(0b00110000);
  delayus(10);
  write_com(0b00110000);
  delayus(10);
  write_com(0b00110000);
  write_com(0b00111000);
  write_com(0b00001100);
  write_com(0b00000001);
  delayms(2);
  write_com(0b00000110);
}
/*********************************************************************/
void display()              //扫描显示子程序
{
  write_com(0x80+0x00);
  delayus(10);
  write_data(table0[2]);
  delayus(10);
  write_data(table0[0]);
  delayus(10);
  write_data(table0[nh]);
  delayus(10);
  write_data(table0[nl]);
  delayus(10);
  write_data(table1[0]);
  delayus(10);
  write_data(table0[yh]);
  delayus(10);
  write_data(table0[yl]);
  delayus(10);
  write_data(table1[0]);
  delayus(10);
  write_data(table0[rh]);
  delayus(10);
  write_data(table0[rl]);
  delayus(10);
     write_com(0x80+0x0c);
     delayus(10);
  for(num=(3*weekday);num<(3*weekday+3);num++)
    write_data(table2[num]);
  write_com(0x80+0x40);
  delayus(10);
  write_data(table0[hh]);
  delayus(10);
  write_data(table0[hl]);
  delayus(10);
  write_data(table1[1]);
  delayus(10);
  write_data(table0[mh]);
  delayus(10);
  write_data(table0[ml]);
  delayus(10);
  write_data(table1[dd]);
  delayus(10);
  write_data(table0[sh]);
  delayus(10);
  write_data(table0[sl]);
  delayus(10);
}
/*********************************************************************/
void keyscan()  
{
    if(key1==0)           //key1为选择按键
    {
      num0++;
      if(num0>5)         //50ms延时确认
        num0=6;
      if(num0==2)
      {
        count1++;         //count1==1,选择调整时针   ount1==4,选择调整当前年
        if(count1==7)     //count1==2,选择调整分针   ount1==5,选择调整当前月
          count1=0;       //count1==3,选择调整秒针   ount1==6,选择调整当前日
      }
    }
    else
      num0=0;
    if(key2==0)          //key2为时分秒年月日加1按键
    {
      num5++;
      if(num5>5)
        num5=6;
      if(num5==2)
      {
        if(count1==1)
        {
          hour++;
          if(hour==24)
            hour=0;
        }
        if(count1==2)
        {
          min++;
          if(min==60)
            min=0;
        }
        if(count1==3)
        {
          sec++;
          if(sec==60)
            sec=0;
        }
      if(count1==4)
        {
          year++;
          if(year==100)
            year=1;
        }
  if(count1==5)
        {
          mon++;
          if(mon==13)
            mon=1;
        }
  if(count1==6)
        {
    Years=year+2000;
          switch (mon)
    {
   case 2:
     {
       day++;
       if(Years%4==0)
    {
      if(day==30)
            day=1;
    }
                else
    {
               if(day==29)
            day=1;
    }
     }
     break;
   case 1: case 3: case 5: case 7:
   case 8: case 10: case 12:
     {
       day++;
             if(day==32)
          day=1;
     }
     break;
   case 4: case 6: case 9: case 11:
     {
       day++;
             if(day==31)
          day=1;
     }
     break;
    }
        }
      }
    }
    else
   num5=0;
    if(key3==0)   //key3为时分秒年月日减1按键
    {
      num6++;
      if(num6>5)
        num6=6;
      if(num6==2)
      {
        if(count1==1)
        {
          hour--;
          if(hour== -1)
            hour=23;
        }
        if(count1==2)
        {
          min--;
          if(min== -1)
            min=59;
        }
        if(count1==3)
        {
          sec--;
          if(sec== -1)
            sec=59;
        }
     if(count1==4)
        {
          year--;
          if(year==0)
            year=99;
        }
  if(count1==5)
        {
          mon--;
          if(mon==0)
            mon=12;
        }
  if(count1==6)
        {
    Years=year+2000;
          switch (mon)
    {
   case 2:
     {
       day--;
       if(Years%4==0)
    {
      if(day==0)
            day=29;
    }
                else
    {
               if(day==0)
            day=28;
    }
     }
     break;
   case 1: case 3: case 5: case 7:
   case 8: case 10: case 12:
     {
       day--;
             if(day==0)
          day=31;
     }
     break;
   case 4: case 6: case 9: case 11:
     {
       day--;
             if(day==0)
          day=30;
     }
     break;
    }
        }
   }
    }
    else
   num6=0;
if(key4==0)        //key4为确认按键
    {
      num7++;
      if(num7>5)
       num7=6;
      if(num7==2)
        count1=0;
    }
else
      num7=0;
}
/*********************************************************************/
void timer()
{
     if(num1<10)
     dd=1;
     else
     dd=2;
      if(num1>=20)              //中断20次,时间计满1s
      {
        num1=0;
        sec++;                  //秒针加1
        if(sec>=60)             //计满60秒,秒针归零
         {
          sec=0;
          min++;
         }                      //分针加1
        sh=sec/10;              //秒针高低位分解
        sl=sec%10;
        if(min>=60)             //计满60分,分针归零
        {  
          min=0;
          hour++;
        }                       //时针加1
        mh=min/10;              //分针高低位分解
        ml=min%10;
        if(hour>=24)            //计满24小时,时针归零
        {  
          hour=0;
       day++;
        }                  //日期加1
        hh=hour/10;             //时针高低位分解
        hl=hour%10;
        switch(mon)
     {
          case 1: case 3: case 5: case 7:
          case 8: case 10: case 12:
      {
          if(day>31)
              {                   //月大日期计满31天,日期归1
       day=1;
       mon++;
              }                 //月份加1
     rh=day/10;        //日期高低位分解
     rl=day%10;
      }
      break;
    case 4: case 6: case 9: case 11: //月小日期计满30天,日期归1
      {
        if(day>30)
     {
                day=1;
       mon++;
              }                            //月份加1
     rh=day/10;                   //日期高低位分解
     rl=day%10;
      }
      break;
    case 2:
      {
              Years=year+2000;
        if(Years%4==0)
     {
         if(day>29)              //润年二月日期计满29天,日期归1
      {
                    day=1;
        mon++;
                  }                  //月份加1
        rh=day/10;              //日期高低位分解
      rl=day%10;
        }
     else
     {
               if(day>28)              //平年二月日期计满29天,日期归1
      {  
                    day=1;
        mon++;
                  }                       //月份加1
      rh=day/10;              //日期高低位分解
         rl=day%10;
     }
      }
      break;
     }
     if(mon>12)
        {                        //月份计满12,月份归1
       mon=1;
       year++;
        }                                 //年份加1
     yh=mon/10;                        //月份高低位分解
     yl=mon%10;
     if(year>99)                       //年份计满99,年份归1
       year=1;
     nh=year/10;                       //年份高低位分解
     nl=year%10;
      }
}
/*********************************************************************/
void time_change()
{
    if(count1==1)                         //等于1表示有调整时针请求
    {
      dd=1;
      if(count2>=20)                      //时针500ms闪烁
     count2=0;
   if(count2<10)
   {
        hh=10;
        hl=10;
   }
   else
   {
     hh=hour/10;
        hl=hour%10;
   }
    }
      if(count1==2)                         //等于2表示有调整分针请求
      {
        hh=hour/10;                         //时秒针年月日正常显示
        hl=hour%10;
        dd=1;
     if(count3>=20)
       count3=0;
     if(count3<10)                       //分针500ms闪烁
     {
          mh=10;
          ml=10;
     }
     else
     {
       mh=min/10;
          ml=min%10;
     }
      }
      if(count1==3)                         //等于3表示有调整秒针请求
      {
        mh=min/10;
        ml=min%10;
        dd=1;
     if(count4>=20)
       count4=0;
     if(count4<10)                       //秒针500ms闪烁
     {
          sh=10;
          sl=10;
     }
     else
     {
       sh=sec/10;
          sl=sec%10;
     }
      }
   
      if(count1==4)                         //等于4表示有调整年份请求
      {
     sh=sec/10;
     sl=sec%10;
        dd=1;
     if(count5>=20)
       count5=0;
     if(count5<10)                       //年份500ms闪烁
     {
          nh=10;
          nl=10;
     }
     else
     {
       nh=year/10;
          nl=year%10;
     }
      }
   
      if(count1==5)                         //等于5表示有调整月份请求
      {
     nh=year/10;
     nl=year%10;
        dd=1;
     if(count6>=20)
       count6=0;
     if(count6<10)                       //月份500ms闪烁
     {
          yh=10;
          yl=10;
     }
     else
     {
       yh=mon/10;
          yl=mon%10;
     }
      }
   
      if(count1==6)                         //等于6表示有调整日期请求
      {
     yh=mon/10;
     yl=mon%10;
        dd=1;
     if(count7>=20)
       count7=0;
     if(count7<10)                       //日期500ms闪烁
     {
          rh=10;
          rl=10;
     }
     else
     {
       rh=day/10;
          rl=day%10;
     }
      }
}
/*********************************************************************/
void weekdays(char day,char mon,char year)
{
      Years=year+2000;
      tmp=(Years-1)/4+1;                  //计算当前年1月1日为星期几?  
   tmp=(Years-tmp)+tmp*2;
      weekday=(tmp+5)%7;
           
      tmp_days=0;
      for(tmp=1;tmp<mon;tmp++)
      {
        if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)
          tmp_days=tmp_days+31;
        else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)
       tmp_days=tmp_days+30;
        else if(tmp==2)
       { if(Years%4==0)
      tmp_days=tmp_days+29;
            else         
   tmp_days=tmp_days+28;
          }
    }
       tmp_days=tmp_days+day-1;   
    weekday=(weekday+tmp_days%7)%7+1;  //计算当前日期为星期几?
    if(weekday==7)
      weekday=0;
}
/*********************************************************************/
void main(void)         //主程序
{
  init();
  while(1)
  {
      display();
      timer();
      time_change();
         keyscan();
         weekdays(day,mon,year);   
  }
}
/*********************************************************************/
/*********************************************************************/
void interrupt T0(void)
{
  if(T0IF==1)
  {  
    T0IF=0;
    TMR0=(65536-50000)/256;
   
    if(count1==0)               //等于0表示没有时间调整按键请求,正常走时
      num1++;
    if(count1==1)                         //等于1表示有调整时针请求
      count2++;
    if(count1==2)                         //等于2表示有调整分针请求
      count3++;
    if(count1==3)                         //等于3表示有调整秒针请求
      count4++;
   
    if(count1==4)                         //等于4表示有调整年份请求
      count5++;
         
    if(count1==5)                         //等于5表示有调整月份请求
      count6++;
   
    if(count1==6)                         //等于6表示有调整日期请求
      count7++;
  }
}
EXAMPLE1.rar 下载积分: 积分 -1 分
106.88 KB, 下载次数: 2, 下载积分: 积分 -1 分
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
文敏
1楼-- · 2019-07-16 03:39
 精彩回答 2  元偷偷看……
月影狼迹
2楼-- · 2019-07-16 05:18
文敏 发表于 2013-6-8 10:44
计数频率低.这个是要算过才可用的

我有经过计算的,预分频比1:256,TMR0=(256*256-50000)/256。50ms计一次,计20次为1s。
请指出哪里计算错误,谢谢!

一周热门 更多>