矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 9109|回复: 16

修补9年前制作的2051数字钟

[复制链接]
     
发表于 2009-1-22 14:23:56 | 显示全部楼层 |阅读模式
回想起来这个数字钟从诞生之日起已经工作了近9年了,由于采用的是9.6MHz的晶体,走时精度很高,调校好后月误差小于2秒。
这回的故障出在电源上。大约在一年前,我把变压器换成了用节能灯镇流器改制的电子变压器,目的是为了消除工频变压器的哼声。当时改制完成后效果不错。不过到最近一段时间,显示暗淡并闪烁,走时精度也变差了。今天有空打开,测量电源输出电压仅3V多一点,看来电子变压器元件性能有所变化了。正好手头上有一闲置手机充电器,手机早已被不知名的人给拿走了,留下个充电器也无它用。把它改成5V输出,接上显示一下子就正常了。不过发现问题了,年月日走得不正常,星期到是一天不差。检查源程序,已经忘记当年怎么写的了,程序很不规范,能省就省,看得头都有大了。不过还是找到问题了,是闰年闰月判断上有一个大BUG,也不知道当年写这段的时候脑子里想些什么了。改过来,还有一些不顺的地方也改过了。改的过程中还出现溢出错误,再仔细看程序,有一处条件判断不完美所致。改过来。由于原来是24小时制,又增加了一个12小时制显示模式。好了,重新烧录2051,上机运行,正常。
发几个图和源程序。
以前用2051做的电子钟.jpg
坏掉了的自制电子变压器.jpg
换个电源就出显示了.jpg
用个手机充电器当电源.jpg
又对程序做了修补,可以正常走时了.jpg
电子钟和DIY的51仿真机.jpg
仿真机PC端程序.jpg

评分

2

查看全部评分

     
 楼主| 发表于 2009-1-22 14:26:43 | 显示全部楼层
源程序当年写得并不规范,反正是好使了就行了。改了以后仍没大动,也是好使了就行了。

  1. #include <stdio.h>
  2. #include <reg51.h>
  3. #define TIMCNT 3126
  4. #define lowbit(c) (c%10)
  5. #define hibit(c) (c/10)
  6. //#include <sio.c>
  7. code char *version="-=<<Clock V1.2  Written by He Liang 2001.5.4>>=-\n";
  8. //                            0    1   2    3    4     5   6   7     8     9   10  11  12
  9. code unsigned char asctb[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0x2,  0,0x30,0};
  10. //                            0  1  2  3  4  5  6  7  8  9  10 11 12
  11. code unsigned char daypm[]={0xff,31,28,31,30,31,30,31,31,30,31,30,31,0xff};
  12. data unsigned char mode=0,year=0,month=1,day=1,hour=0,min=0,sec=0,week=0,setup=0;
  13. data unsigned char ddlycnt=0;
  14. data unsigned int timcnt=TIMCNT,delaycnt;
  15. idata unsigned char dbuf[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
  16. bit modi=0,flash,date=0,h12=0;
  17. void inittimer0(void)
  18. {
  19.     TMOD&=0xf0;
  20.     TMOD+=0x02;
  21.     TH0=0;
  22.     TL0=0;
  23.     TR0=1;
  24.     ET0=1;
  25.     EA=1;
  26. }
  27. void timer0(void) interrupt 1
  28. {
  29.     static unsigned char k=1;
  30.     static unsigned char dc=0;
  31.     k<<=1;
  32.     dc++;
  33.     if(k==0){k=1;dc=0;}
  34.     P1=0;
  35.     T1=1;
  36.     T1=0;
  37.     P1=~dbuf[dc];
  38.     RD=1;
  39.     RD=0;
  40.     P1=k;
  41.     T1=1;
  42.     T1=0;
  43.     if(delaycnt!=0)delaycnt--;
  44.     timcnt--;
  45.     if(timcnt==0)
  46.     {
  47.         if(!modi)sec++;
  48.         if(sec>59)sec=0;
  49.         timcnt=TIMCNT;
  50.     }
  51. }
  52. void display()
  53. {
  54.     unsigned char c,h;
  55.     h12=0;
  56.     switch(mode)
  57.     {
  58.         case 0:
  59.             date=0;
  60.             break;
  61.         case 1:
  62.             date=0;
  63.             if(setup==0)h12=1;
  64.             break;
  65.         case 2:
  66.             date=1;
  67.             if(setup==0){ddlycnt++;if(ddlycnt>5){ddlycnt=0;mode=0;}}
  68.             break;
  69.         case 3:
  70.             if(setup==0)
  71.             {
  72.                 if(delaycnt==0)
  73.                 {
  74.                     date=!date;
  75.                     if(date)delaycnt=TIMCNT*2;else delaycnt=TIMCNT*5;
  76.                 }
  77.             }
  78.             else
  79.                 date=0;
  80.             break;
  81.     }
  82.     if(date)
  83.     {
  84.             dbuf[0]=asctb[hibit(year)];
  85.             dbuf[1]=asctb[lowbit(year)];
  86.             dbuf[2]=asctb[12];
  87.             dbuf[3]=asctb[hibit(month)];
  88.             dbuf[4]=asctb[lowbit(month)];
  89.             dbuf[5]=asctb[12];
  90.             dbuf[6]=asctb[hibit(day)];
  91.             dbuf[7]=asctb[lowbit(day)];
  92.     }else
  93.     {
  94.             h=hour;
  95.             if(h12){
  96.                 h%=12;
  97.                 if(h==0)h=12;
  98.             }
  99.             c=hibit(h);if(c==0)c=11;
  100.             dbuf[0]=asctb[c];
  101.             dbuf[1]=asctb[lowbit(h)];

  102.             dbuf[2]=asctb[10];
  103.             dbuf[3]=asctb[hibit(min)];
  104.             dbuf[4]=asctb[lowbit(min)];
  105.             dbuf[5]=asctb[10];
  106.             dbuf[6]=asctb[hibit(sec)];
  107.             dbuf[7]=asctb[lowbit(sec)];
  108.     }
  109.     if(!flash && setup>0 && setup <4)
  110.     {
  111.         c=setup-1;
  112.         c=c+c+c;
  113.         dbuf[c]=0;
  114.         dbuf[c+1]=0;
  115.     }
  116.     if(!h12&&(setup!=4||flash))dbuf[week]|=1;
  117. }

  118. void caltim()
  119. {
  120.     static data unsigned char se=0;
  121.     if(sec!=se)
  122.     {
  123.         se=sec;
  124.         if(sec==0)
  125.         {
  126.             min++;
  127.             if(min>59)
  128.             {
  129.                 hour++;min=0;
  130.                 if(hour>23)
  131.                 {        
  132.                     hour=0;week++;if(week>6)week=0;
  133.                     day++;
  134.                     if(day>daypm[month]+((month==2 && (year&3)==0)?1:0))
  135.                     {
  136.                         month++;day=1;
  137.                         if(month>12)
  138.                         {
  139.                             year++;month=1;
  140.                             if(year>99)year=0;
  141.                         }
  142.                     }
  143.                 }
  144.             }
  145.         }
  146.         flash=1;
  147.         display();
  148.     }
  149.     if(setup!=0&&delaycnt==0)
  150.     {
  151.         delaycnt=750;
  152.         flash=!flash;
  153.         display();
  154.     }
  155. }
  156. char _getkey(void)
  157. {
  158.     static unsigned char cnt=254,lastkey=0,repcnt=10,lstk=0;
  159.     unsigned char k;
  160.     INT0=1;INT1=1;
  161.     k=P3;
  162.     k=(~(k>>2))&3;
  163.     if(k!=lstk){lstk=k;cnt=254;}
  164.     if(cnt>0){cnt--;return 0;}
  165.     cnt=254;
  166.     if(k==lastkey)
  167.     {
  168.         repcnt--;
  169.         if(repcnt==0){repcnt=2;return k;}
  170.         else return 0;
  171.     }else
  172.     {
  173.         lastkey=k;
  174.         repcnt=6;
  175.         return k;
  176.     }


  177. }
  178. main()
  179. {
  180.     unsigned char key;
  181.     inittimer0();
  182. //    initsio();
  183.     while(1)
  184.     {
  185.         PCON|=1;
  186.         caltim();
  187.         key=_getkey();
  188.         if(key!=0)
  189.         {
  190.             ddlycnt=0;
  191.             switch(key)
  192.             {
  193.                 case 1:
  194.                     setup++;
  195.                     if(setup>4)setup=0;
  196.                     if(setup!=3)modi=0;
  197.                     delaycnt=0;
  198.                     break;
  199.                 case 2:
  200.                     if(mode==2)
  201.                     {
  202.                         switch(setup)
  203.                         {
  204.                             case 0:
  205.                                 mode++;
  206.                                 if(mode>3)mode=0;
  207.                                 break;
  208.                             case 1:
  209.                                 year++;
  210.                                 if(year>99)year=0;
  211.                                 break;
  212.                             case 2:
  213.                                 month++;
  214.                                 if(month>12)month=1;
  215.                                 break;
  216.                             case 3:
  217.                                 day++;
  218.                                 if(day>daypm[month]+((month==2 && (year&3)==0)?1:0))day=1;
  219.                                 break;
  220.                             case 4:
  221.                                 week++;
  222.                                 if(week>6)week=0;
  223.                                 break;
  224.                         }
  225.                     }else{
  226.                         switch(setup)
  227.                         {
  228.                             case 0:
  229.                                 mode++;
  230.                                 if(mode>3)mode=0;
  231.                                 break;
  232.                             case 1:
  233.                                 hour++;
  234.                                 if(hour>23)hour=0;
  235.                                 break;
  236.                             case 2:
  237.                                 min++;
  238.                                 if(min>59)min=0;
  239.                                 break;
  240.                             case 3:
  241.                                 modi=1;
  242.                                 sec++;
  243.                                 if(sec>59)sec=0;
  244.                                 timcnt=TIMCNT;
  245.                                 break;
  246.                             case 4:
  247.                                 week++;
  248.                                 if(week>6)week=0;
  249.                                 break;
  250.                         }

  251.                     }
  252.                     delaycnt=2400;
  253.                     flash=1;
  254.                     break;
  255.                     
  256.             }
  257.             display();

  258.         }
  259.     }

  260. }

复制代码

[ 本帖最后由 翌阳 于 2009-1-22 14:29 编辑 ]
     
 楼主| 发表于 2009-1-22 14:45:41 | 显示全部楼层
再说明一下:
这个程序要用80C51系列的,带有待机模式的才好用。
关键在这:
PCON|=1;
这之后MCU会进入到暂停状态,程序停止执行,但时钟和计数器仍在运行,如果发生中断,则从待机状态中苏醒过来,程序继续运行。
这样有很多事就不用写在中断里了,可以在主循环中完成。
这个程序把计算显示和键盘处理写在主循环中了,其实也可以把显示扫描也写在主循环中。中断处理程序就更加短小了。不过目前的中断处理已经够短了。这样做不会影响中断的时间精度,也就使走时更加精确。还有一个好处就是,在空闲时间,MCU是进入到待机状态的,有利于减少功耗,在使用后备电池的时候能够维持更长的时间。

还有,电原理图就记不得了,当时也是没有的,如果有需要的朋友我可以再画个,但不好说能够与之匹配。原因是这个时钟是用一些废弃电路板制作的,LED板,主电路板和上面的小电路板都是从某个废弃电路板上切下来的,然后把需要的部分用飞线连上。

[ 本帖最后由 翌阳 于 2009-1-22 14:50 编辑 ]
     
发表于 2009-1-22 15:16:23 | 显示全部楼层

回复 3# 翌阳 的帖子

顶一下,LZ好水平。
发表于 2009-1-22 15:19:32 | 显示全部楼层
51的外围件真多。用m8做的话只需要几根电阻一个晶振。

楼主的钟不错,外观很精致。我就喜欢完成度高的东西~
     
 楼主| 发表于 2009-1-22 15:52:08 | 显示全部楼层

回复 5# 臧工 的帖子

用51做也可以少外围件的电路。差不多一样的。
这个外围件多的原因是:那些外围件是现成了,LED是共阴的,把板子切下来连上线就OK了。
本来8位数显还是准备做个频率计呢,手懒,数字钟成了就不弄频率计了。
发表于 2009-1-22 18:21:17 | 显示全部楼层
源代码“看起来”很长,不知道我手上的89s52装得下一个类似的吗?
     
发表于 2009-1-22 21:24:11 | 显示全部楼层
翌版的作品一定要顶!
我这里怎么就买不到这么漂亮的盒子呢
     
发表于 2009-1-22 21:40:37 | 显示全部楼层
回楼上,89s51就装得下。
     
发表于 2009-1-30 19:00:07 | 显示全部楼层
我最感兴趣的还是楼主最后两张照片上的"ICE51"硬件和软件
     
 楼主| 发表于 2009-1-30 23:48:31 | 显示全部楼层

回复 10# d3b7 的帖子

既然感兴趣,那就拿出来了。
ICE.ZIP里的ICE.PCB是印制板图,ICE.S01是原理图,不过原理图没有画完。
有兴趣就从板图回推吧。
当初的时候就是原理图画个大概,然后直接就画板图了。
还有那个PC端软件,也拿出来。一会儿再把仿真机上的固件也拿出来。

再说明一下,由于是早期制作的东西,板图和原理图都是用一个protel的DOS版本画的。

[ 本帖最后由 翌阳 于 2009-1-30 23:56 编辑 ]

ICE.zip

11.76 KB, 下载次数: 1197

板图和画了一半的原理图

ice51.zip

12.61 KB, 下载次数: 1178

PC终端程序

ice52bios.rar

23.84 KB, 下载次数: 1223

固件及其源程序

     
发表于 2009-2-2 10:01:01 | 显示全部楼层
呵呵, 翌阳版主都帖出来了。
可是,这个玩意儿有些什么用?我还没看明白。这是我感兴趣的原因
发表于 2009-9-16 09:53:04 | 显示全部楼层

太好了

     
发表于 2009-9-16 20:59:11 | 显示全部楼层
楼主有才,想做没时间
看看这几张‘人间大炮’怎样!

[ 本帖最后由 tubeamp 于 2009-9-16 21:11 编辑 ]
     
发表于 2009-9-16 21:12:25 | 显示全部楼层
版主,你这数字钟有闹钟功能吗?
您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-30 07:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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