矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 10867|回复: 21

自动亮度适应自然醒闹铃LED电子钟

[复制链接]
     
发表于 2011-1-24 11:47:44 | 显示全部楼层 |阅读模式
这个是在09年制作完成的,经过近2年的运行,工作稳定,年误差在10秒以内。
此钟的特点是:
1. 时分显示,24/12小时制可选。无日期与年份功能。(就是一个表,不是日历,所以不把那功能加进去了,若是来回跳着显示,看着烦。本人制作的东西,自然要依着个人的喜好走了,这是DIY的好处)。
2. 环境光强感应,自动调整LED显示的亮度(14级亮度),以免白天看不清,晚上太刺眼。(这个原来是准备装在卧室用的,用大LED数码管的原因也在此,在睡眼惺松的时候,小的确实看不清。)
3. 自然醒闹时唤醒功能。采用白光LED逐渐亮起,模拟天亮的过程,实现自然醒,早上醒来感觉精神十足。
4. 闹时按星期设定,可以选择七天全部和一周五天工作日等模式。
5. 一键设定。 模式选择和调整都只用一个按键,长按与短按。长按进入设定或确定设定,短按调整或模式选择。
7. 电池备份供电。3.6V备份电池提供短时(数天)断电走时维持。(此时单片机感应到主电源失电,进入省电运行模式,只计时,不扫描和闹时)
8. 充分利用2051的空闲模式,省电。只要没活干的时候就进入到空闲模式,无浪费的循环等待。
9. 机壳一直没完成,线路板是用废板改造的,很乱。(都不好意思拿出来给大家看了,但只此一台,如果做多了一定会做漂亮的,但我会多DIY一个吗?这个留给大家了)。
上图:下面跟贴再发程序。

[ 本帖最后由 翌阳 于 2011-1-25 11:13 编辑 ]

线路图

线路图
全景.jpg
细节1.jpg
光传感器.jpg
电源部分.jpg
背面连线.jpg

评分

2

查看全部评分

相关帖子

     
 楼主| 发表于 2011-1-24 11:48:12 | 显示全部楼层
  1. #pragma code
  2. #include <stdio.h>
  3. #include <reg51.h>
  4. //#define TIMCNT 1563
  5. //#define TIMCNT 3200
  6. //#define TIMCNT 1200                        //1200 for 7.3728MHz
  7. #define TIMCNT 3000                        //for 18.432MHz
  8. #define DOT 0x80
  9. #define CHAR_c        97
  10. #define CHAR_P        115|0x80
  11. #define CHAR_d   94
  12. #define CHAR_o         92
  13. #define CHAR_f        113
  14. #define CHAR_minus        64
  15. #define KEYDELAY TIMCNT/4
  16. #define KEY RD
  17. code char version[]=" ==<<Clock V1.3 by 翌展 2009.3.10>>==\n";
  18. data unsigned char asctb[]={63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 119, 124, 57, 94, 121, 113};
  19. data unsigned char digbit[]={0xe0,0xd0,0xc8,0xc4};//11100000,11010000,11001000,11000100
  20. data unsigned char light=8,bright,alight=0,alon=32,maxtl[8]={0,0,0,0,0,0,0,0};
  21. //                                                   0,1 2 3 4 5 6 7 8 9 1011 12 13 14 15
  22. data unsigned char gama[]={1,1,2,2,3,3,4,5,6,7,8,10,13,18,24,32,32};


  23. data unsigned char mode=0,alhour=0,almin=0,almode=0,hour=0,min=0,sec=0,week=0,flash=0,se=0;
  24. data unsigned char dispdot=0;  //0: none  1:flash  2:always
  25. data unsigned char P1bit=0x3;
  26. data unsigned int timcnt=TIMCNT;
  27. data unsigned char dbuf[4]={0xff,0xff,0xff,0xff},pbuf1[4]={0xfc,0xfc,0xfc,0xfc},pbuf3[4]={0xe3,0xd3,0xcb,0xc7};
  28. bit modi=0,h12=0,lkey=0,rkey=0,dot=0,alarm=0,alarm_on=0,power=1,dot2=0,active=0;
  29. void inittimer0(void)
  30. {
  31.     TMOD&=0xf0;
  32.     TMOD|=0x02;
  33.     TH0=0;
  34.     TL0=0;
  35.     TR0=1;
  36.     ET0=1;
  37.     EA=1;
  38. }
  39. void timer0(void) interrupt 1
  40. {
  41.     timcnt--;
  42.     if(timcnt==0)
  43.     {
  44.         if(!modi)sec++;     
  45.         if(sec>119)sec=0;
  46.         dot=!dot;
  47.         timcnt=TIMCNT;
  48.     }
  49. }
  50. void display_almode(void)
  51. {
  52.         switch(almode){
  53.                 case 0:                                //off
  54.                                 dbuf[0]=0;
  55.                                 dbuf[1]=CHAR_o;
  56.                                 dbuf[2]=CHAR_f;
  57.                                 dbuf[3]=CHAR_f;
  58.                         break;
  59.                 case 1:                                //p.d.
  60.                                 dbuf[0]=0;
  61.                                 dbuf[1]=CHAR_P;
  62.                                 dbuf[2]=0;
  63.                                 dbuf[3]=CHAR_d|DOT;
  64.                         break;
  65.                 case 2:                                //1-5
  66.                                 dbuf[0]=CHAR_d;
  67.                                 dbuf[1]=asctb[1];
  68.                                 dbuf[2]=CHAR_minus;
  69.                                 dbuf[3]=asctb[5];
  70.                         break;
  71.         }
  72. }
  73. void display_hm(unsigned char h,unsigned char m,bit b)       
  74. {
  75.             dbuf[1]=asctb[h%10];
  76.                     h/=10;
  77.                     if(b && !h)dbuf[0]=0;else dbuf[0]=asctb[h];
  78.             dbuf[2]=asctb[m/10];
  79.             dbuf[3]=asctb[m%10];
  80. }

  81. void display(void)
  82. {
  83.     static unsigned char pid=0;
  84.     unsigned char c,h;
  85.     flash=0;dispdot=1;
  86.     switch(mode)
  87.     {
  88.         case 0:                                        //12 hour
  89.                 h=hour%12;if(h==0)h=12;
  90.                 display_hm(h,min,1);
  91.                     if(hour<12)dbuf[0]|=DOT;
  92.                     break;
  93.         case 1:                                        //24 hour
  94.                         display_hm(hour,min,1);
  95.             break;
  96.         case 2:                                        //second
  97.                 display_hm(min,sec>>1,0);
  98.                 dispdot=2;
  99.                 break;
  100.         case 3:                                        //h setup
  101.                     display_hm(hour,min,1);
  102.                     flash=1;
  103.                 break;
  104.         case 4:                                        //m setup
  105.                 display_hm(hour,min,1);
  106.                 flash=2;
  107.                 if(modi)dispdot=2;
  108.                 break;
  109.         case 5:                                        //week setup
  110.             dbuf[0]=0;
  111.                     dbuf[1]=asctb[week];
  112.             dbuf[2]=CHAR_d;
  113.             dbuf[3]=0;
  114.             flash=1;
  115.             dispdot=0;
  116.                         break;                                                       
  117.         case 6:                                        //s setup
  118.                 display_hm(min,sec>>1,0);
  119.             dispdot=2;
  120.             flash=2;
  121.                 break;
  122.         case 7:                                //week
  123.                 dbuf[0]=0;
  124.                 dbuf[1]=asctb[week];
  125.                 dbuf[2]=CHAR_d;                                //'d'
  126.                 dbuf[3]=0;
  127.             dispdot=0;
  128.                 break;
  129.                 case 8:                                                                //alarm
  130.                         if((sec & 6)==6){
  131.                                 display_almode();
  132.                     dispdot=0;
  133.                         }else{
  134.                                 display_hm(alhour,almin,1);
  135.                            dispdot=2;
  136.                    }
  137.                         break;       
  138.                 case 9:                                                                //alarm hour setup
  139.                         display_hm(alhour,almin,1);
  140.             dbuf[3]|=DOT;
  141.             flash=1;
  142.             dispdot=2;
  143.                         break;
  144.                 case 10:                                                                //alarm min setup
  145.                         display_hm(alhour,almin,1);
  146.             dbuf[3]|=DOT;
  147.             flash=2;
  148.             dispdot=2;
  149.                         break;
  150.                 case 11:                                                                //alarm mode setup     0:off  1: p.d.  2:1-5
  151.                         display_almode();
  152.                         flash=3;
  153.             dispdot=0;
  154.                         break;
  155.                 case 12:                                                                //display bright senser data
  156.                         dbuf[0]=asctb[light];
  157.                         dbuf[1]=0;
  158.                         dbuf[2]=asctb[bright/10];
  159.                         dbuf[3]=asctb[bright%10];
  160.             dispdot=0;
  161.                         break;
  162.                 case 13:                                                                //display MAX RUN DELAY
  163.                         pid++;if(pid>63)pid=0;
  164.                         c=pid>>3;
  165.                         dbuf[0]=asctb[c];
  166.                         dbuf[1]=CHAR_minus;
  167.                         c=maxtl[c];
  168.                         dbuf[2]=asctb[c>>4];
  169.                         dbuf[3]=asctb[c&0xf];
  170.             dispdot=0;
  171.                         break;
  172.                 case 14:                                                                //min was set and wait for starting
  173.                         display_hm(hour,min,1);
  174.                         dispdot=2;
  175.                         break;
  176.                 case 15:                                                                //LED & alarm light check
  177.                         dbuf[0]=0xff;
  178.                         dbuf[1]=0xff;
  179.                         dbuf[2]=0xff;
  180.                         dbuf[3]=0xff;
  181.                         dispdot=0;
  182.                         pid++;
  183.                         if(pid>63)pid=0;
  184.                         alight=pid>>2;
  185.                         alarm_on=1;
  186.                         break;

  187.     }
  188. }
  189. void display_dot(void)
  190. {
  191.         if(dispdot==1 && dot2 || dispdot==2){dbuf[1]|=DOT;dbuf[2]|=DOT;}
  192. }
  193. void bufferproc(void)
  194. {
  195.         if(almode)dbuf[3]|=DOT;
  196.         if(!dot2){
  197.                 if(flash&1){
  198.                         dbuf[0]&=DOT;dbuf[1]&=DOT;
  199.                 }
  200.                 if(flash&2){
  201.                         dbuf[2]&=DOT;dbuf[3]&=DOT;
  202.                 }
  203.         }
  204.                 pbuf1[0]=dbuf[0]&0xfc;
  205.                 pbuf3[0]=dbuf[0]&3|digbit[0];
  206.                 pbuf1[1]=dbuf[1]&0xfc;
  207.                 pbuf3[1]=dbuf[1]&3|digbit[1];
  208.                 pbuf1[2]=dbuf[2]&0xfc;
  209.                 pbuf3[2]=dbuf[2]&3|digbit[2];
  210.                 pbuf1[3]=dbuf[3]&0xfc;
  211.                 pbuf3[3]=dbuf[3]&3|digbit[3];
  212. }

  213. bit caltim(void)
  214. {
  215.     if(se!=sec)
  216.     {
  217.         se=sec;
  218.         if(sec==0)
  219.         {
  220.             min++;
  221.             if(min>59)
  222.             {
  223.                 hour++;min=0;
  224.                 if(hour>23)
  225.                 {       
  226.                     hour=0;week++;if(week>6)week=0;
  227.                                 }
  228.             }
  229.         }
  230.         return 1;
  231.      }
  232.      return 0;
  233. }

  234. void LEDscan(void)
  235. {
  236.         static unsigned char dly=8,dig=0;
  237.         dly--;
  238.         if(dly==0){dly=8;P3=0xc0;}  // 11000000
  239.         if(dly==light){
  240.                 dig++;
  241.                 if(dig>3)dig=0;
  242.                 P1=pbuf1[dig]|P1bit;
  243.                 P3=pbuf3[dig];
  244.         }
  245.         if(alarm_on){
  246.                 alon--;                                                                        ///alarm
  247.                 if(alon==0){alon=32;P10=1;P1bit|=1;}
  248.                 if(alon==alight){P10=0;P1bit&=2;}
  249.         }
  250. }
  251. void bright_senser(void)
  252. {
  253.         static unsigned char bcount=63,b2=0;
  254.         if((P1bit&0x2)==0x2){
  255.                 if(!P11 && bcount!=0)bcount--;
  256.                 else{
  257.                         bright=(bright+bcount)>>1;
  258.                         if(b2>bright+4 || b2+4<bright){
  259.                                 light=gama[bright/6]; //0-63 /6 =0-10      //(bright>>3)+1;  //*8/256;
  260.                                 b2=bright;
  261.                         }
  262.                         P1bit&=0x1;
  263.                         P11=0;
  264.                         bcount=10;
  265.                 }
  266.         }else{
  267.                 if(bcount!=0)bcount--;else{
  268.                         P1bit|=0x2;
  269.                         P11=1;
  270.                         bcount=63;
  271.                 }
  272.         }
  273. }
  274. void alarmlight(void)
  275. {
  276.         static unsigned char mina=0,fade=0;
  277. //        static unsigned int fade=0;
  278.         if(almode==0)return;
  279.         if(mina!=min){
  280.                 mina=min;
  281.                 if(!alarm && alhour==hour && almin==min && (almode==1||week>0 && week<6)){
  282.                         alarm=1;alarm_on=1;fade=0;alight=0;
  283.                 }
  284.                 if(alarm){
  285.                         if(fade<46){
  286.                                 if(fade<16)alight=gama[fade];                //0-15
  287.                                 else if(fade<31)alight=32;                        //16-30
  288.                                 else alight=gama[45-fade];                        //31-45
  289.                                 fade++;
  290.                         }else{
  291.                                 alarm=0;alarm_on=0;fade=0;alight=0;P10=1;P1bit|=1;
  292.                         }
  293.                 }
  294.         }
  295. }
  296. void chkpower(void)
  297. {
  298.         if(P1bit&1){
  299.                 power=P10;
  300.                 if(!power){P1=3;P3=0;}
  301.         }
  302. }
  303. void setup(void)
  304. {
  305.         static unsigned int kcode=0;
  306.         unsigned char key=0;
  307.         ///----------------------getkey
  308.         if(!KEY){
  309.                 lkey=1;
  310.                 if(!rkey){
  311.                         kcode++;
  312.                         if(kcode>KEYDELAY*2){key=2;rkey=1;}
  313.                 }
  314.         }else if(lkey){
  315.                 if(kcode<KEYDELAY/20)key=0;
  316.                 else if(!rkey)key=1;
  317.                 lkey=0;
  318.                 rkey=0;
  319.                 kcode=0;
  320.         }
  321.         if(!key)return;

  322.                         //------------------setup
  323.                 if(alarm){alarm=0;alarm_on=0;P1bit|=1;return;}   //turn off alarm
  324.                
  325.                 switch(mode){
  326.                         case 0:                                                                        //12h       
  327.                                 if(key==2)mode=3;
  328.                                 else mode=1;
  329.                                 break;
  330.                         case 1:                                                                        //24h
  331.                                 if(key==2)mode=12;else mode=2;
  332.                                 break;
  333.                         case 2:                                                                         //second                                                                       
  334.                                 if(key==2)mode=6;else mode=7;
  335.                                 break;
  336.                         case 3:                                                                        //hour setup
  337.                                 if(key==2)mode=4;else{
  338.                                         hour++;
  339.                                         if(hour>23)hour=0;
  340.                                 }
  341.                                 break;
  342.                         case 4:                                                                        //minute setup
  343.                                 if(key==2){mode=modi?14:0;}else{
  344.                                         modi=1;
  345.                                         min++;
  346.                                         if(min>59)min=0;
  347.                                 }
  348.                                 break;
  349.                         case 5:                                                                        //week setup
  350.                                 if(key==2){mode=7;}else{
  351.                                         week++;
  352.                                         if(week>6)week=0;
  353.                                 }
  354.                                 break;
  355.                         case 6:                                                                        //second setup
  356.                                 if(key==2){mode=2;}
  357.                                 else{
  358.                                         timcnt=TIMCNT;
  359.                                         if(sec<59)se=0;
  360.                                         sec=0;
  361.                                 }
  362.                                 break;
  363.                         case 7:                                                                //week
  364.                                 if(key==2)mode=5;else mode=8;
  365.                                 break;
  366.                         case 8:                                                                //alarm
  367.                                 if(key==2)mode=9;else mode=0;
  368.                                 break;       
  369.                         case 9:                                                                //alarm hour setup
  370.                                 if(key==2)mode=10;else{
  371.                                         alhour++;
  372.                                         if(alhour>23)alhour=0;
  373.                                 }
  374.                                 break;
  375.                         case 10:                                                                //alarm min setup
  376.                                 if(key==2)mode=11;else{
  377.                                         almin++;
  378.                                         if(almin>59)almin=0;
  379.                                 }
  380.                                 break;
  381.                         case 11:                                                                //alarm mode setup     0:off  1: week  2:1-5
  382.                                 if(key==2)mode=8;else{
  383.                                         almode++;
  384.                                         if(almode>2)almode=0;
  385.                                 }
  386.                                 break;
  387.                         case 12:                                                                //display bright senser data
  388.                                 mode=13;
  389.                                 break;
  390.                         case 13:                                                                //display MAX RUN DELAY
  391.                                 mode=15;
  392.                                 break;
  393.                         case 14:                                                                //min was set and wait for starting
  394.                                 modi=0;
  395.                                 sec=0;se=0;
  396.                                 timcnt=TIMCNT;
  397.                                 mode=0;
  398.                                 break;
  399.                         case 15:
  400.                                 alarm_on=0;P1bit|=1;                                        //alarm light check
  401.                                 mode=1;
  402.                                 break;
  403.                         default:
  404.                                 mode=0;
  405.                                
  406.                 }

  407. }

  408. main()
  409. {
  410.     unsigned char c=0,d=0;
  411.     bit b;
  412.     inittimer0();
  413.     while(1)
  414.     {
  415.         PCON|=1;
  416.                 b=caltim();
  417.                 if(!power){chkpower();continue;}
  418.                 LEDscan();
  419.                 if(b)continue;
  420.             if(d>maxtl[c]){maxtl[c]=d;}
  421.                 c++;
  422.                 switch(c){
  423.                         case 1:
  424.                                 if(dot2!=dot){dot2=dot;active=1;}
  425.                                 chkpower();
  426.                                 break;
  427.                         case 2:
  428.                                 if(active)display();
  429.                                 break;
  430.                         case 3:
  431.                                 if(active)display_dot();
  432.                                 break;
  433.                         case 4:
  434.                                 if(active)bufferproc();
  435.                                 break;
  436.                         case 5:
  437.                                 if(active)alarmlight();
  438.                                 break;
  439.                         case 6:
  440.                                 bright_senser();
  441.                                 break;
  442.                         case 7:
  443.                                 setup();
  444.                                 break;
  445.                         case 8:
  446.                                 active=0;
  447.                                 c=0;
  448.                                 break;
  449.                         default:
  450.                                 c=0;
  451.                 }
  452.             d=TL0;
  453.     }

  454. }
复制代码
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2011-1-24 11:53:01 | 显示全部楼层
程序写得有点怪,朋友们分析分析吧,反正与常规思路不太一样。这个原因也是为了保证计时精度,中断是用定时器自动装载模式的,同时还要保证中断处理程序里的活越少越好,这样在一次中断的时间内就把活干完。但中断会扰乱其它工作,还需要其它的工作也不要被中断所打乱才好,否则会在显示的时候有点点的跳动。主循环也受到中断的影响,主要是利用定时器中断把空闲状态跳出的功能实现的。

再说一点有关闹时的事,其实也可以加进声音的,但考虑两件事:一是实在没有输出端口了,2051本来管脚就不多;二是现在我这儿有个钟控收音机,一直习惯听中央台的播音时醒来,那个自然醒是辅助的,当然定时的时间要提前20分钟到30分钟啊,醒来是需要一定时间的。可别依赖这东西来唤醒你。如果需要,可以自己加个声音的装置,改个程序。

[ 本帖最后由 翌阳 于 2011-1-24 11:57 编辑 ]
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2011-1-24 12:07:37 | 显示全部楼层
这是编译后的HEX和BIN文件。

HEX&BIN.zip

4.09 KB, 下载次数: 1422

回复 支持 反对

使用道具 举报

     
发表于 2011-1-24 12:16:50 | 显示全部楼层
老师这个表真的在桌子上裸了两年啊



那几个照眼睛的LED放哪儿了?

http://web.crystalradio.cn/bbs/thread-60621-1-1.html
http://web.crystalradio.cn/bbs/thread-60122-1-1.html

微调电容的镀膜要当心变黑啊

BTW:您的结石怎么样了?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2011-1-24 12:26:04 | 显示全部楼层
一直没空做机壳。
那个LED弄成了6只了,很亮。就在边上呢,照片没照到。
微调电容是NN年的东西了,已经基本上稳定了。

谢谢您的关心,结石仍然是结石,只要它不堵着就没感觉了。多喝水,少吃草酸多的食物。


制作两周年纪念,又把它晒出来了,等有时间弄个机壳就全部完成了。到时再拿出来晒晒。

[ 本帖最后由 翌阳 于 2011-1-24 12:28 编辑 ]
回复 支持 反对

使用道具 举报

发表于 2011-1-24 15:10:38 | 显示全部楼层
精度相当高了
回复 支持 反对

使用道具 举报

     
发表于 2011-1-25 01:03:28 | 显示全部楼层
做位驱动的那8个三极管极性没有画错吧?

[ 本帖最后由 lxa000 于 2011-1-25 19:35 编辑 ]
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2011-1-25 10:59:31 | 显示全部楼层

回复 8# lxa000 的帖子

做位驱动的那4个画错了。不好意思,一会儿改过来。
回复 支持 反对

使用道具 举报

     
发表于 2011-1-25 15:42:40 | 显示全部楼层
进来学习一下
回复 支持 反对

使用道具 举报

发表于 2011-1-25 23:56:11 | 显示全部楼层
我找遍市场,想要买一个这样的成品,但遍寻不得。不知道能否做得轻薄小巧一些,如果行的话,建议斑竹找个厂子代工一下,批量做一些出来,应该是有市场的
回复 支持 反对

使用道具 举报

     
发表于 2011-1-26 20:36:42 | 显示全部楼层
年误差在10秒以内
这个是不是和用的晶振 精度高有关系?
不好意思 程序神马 还没认真看一遍就先问问
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2011-1-26 21:56:04 | 显示全部楼层

回复 13# xiaomu 的帖子

与晶振的稳定度有关,当然也有不稳定因素,但综合起来,一会变正一会变负,总体的误差就不大了。当然与环境温度也会有关系。
其实最主要的晶振的频率校准过,用标准时间台的频率校准过。
晶体的频率越高,误差会越小。
回复 支持 反对

使用道具 举报

发表于 2012-6-8 21:44:33 | 显示全部楼层
进来学习一下,
回复 支持 反对

使用道具 举报

     
发表于 2012-6-23 15:55:21 | 显示全部楼层
请问楼主.LED数码管是共阳极还是共阴极的?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

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

蒙公网安备 15040402000005号

GMT+8, 2025-5-8 04:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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