论坛风格切换切换到宽版
  • 3606阅读
  • 9回复

初学51,搞了个电报报时的时钟 [复制链接]

上一主题 下一主题
离线bd9cr
 
发帖
1202
只看楼主 倒序阅读 0楼 发表于: 2007-09-27
p10按键报时,p11调节小时,p12调节分钟,p13+p10键盘锁。
带正点报时。全部用蜂鸣器输出cw提示。
led一秒闪烁一次。
#include<at89x51.h>
unsigned char a;//分的10位
unsigned int q;//for循环
unsigned char r=0;//毫秒
unsigned char s=0;//秒
unsigned char m=0;//分
unsigned char h=8;//时
void timer0_int(void)interrupt 1
{
th0=0x3c;
tl0=0xb0;
r++;
if(r==10)
{s++;r=0;p2_1=~p2_1;
  if(s==60){m++;s=0;
      if(m==60){h++;m=0;
            if(h==24){h=0;
                  }//小时if
              }//fenzhong if
          }//miao if
}//haomiao if.
     
}//中断结束

//发达的子程序
void da()
{
p2_3=1;
for(q=0;q<18000;q++);
p2_3=0;
for(q=0;q<6000;q++);
}

//发嘀的子程序
void di()
{
p2_3=1;
for(q=0;q<6000;q++);
p2_3=0;
for(q=0;q<6000;q++);
}

void talk()//cw报时子程序
{
a=h/10;//xiashi的十位
switch(a)
        {
                          case 0:da();da();da();da();da();break;
                             case 1:di();da();da();da();da();break;
                             case 2:di();di();da();da();da();break;
                             case 3:di();di();di();da();da();break;
                             case 4:di();di();di();di();da();break;
                             case 5:di();di();di();di();di();break;
                             case 6:da();di();di();di();di();break;
                             case 7:da();da();di();di();di();break;
                             case 8:da();da();da();di();di();break;
            case 9:da();da();da();da();di();break;
                        }
for(q=0;q<33000;q++);
a=h%10;//xiaoshi的ge位
switch(a)
        {
                          case 0:da();da();da();da();da();break;
                             case 1:di();da();da();da();da();break;
                             case 2:di();di();da();da();da();break;
                             case 3:di();di();di();da();da();break;
                             case 4:di();di();di();di();da();break;
                             case 5:di();di();di();di();di();break;
                             case 6:da();di();di();di();di();break;
                             case 7:da();da();di();di();di();break;
                             case 8:da();da();da();di();di();break;
            case 9:da();da();da();da();di();break;
                        }
for(q=0;q<33000;q++);
a=m/10;//分的十位
switch(a)
        {
                          case 0:da();da();da();da();da();break;
                             case 1:di();da();da();da();da();break;
                             case 2:di();di();da();da();da();break;
                             case 3:di();di();di();da();da();break;
                             case 4:di();di();di();di();da();break;
                             case 5:di();di();di();di();di();break;
                             case 6:da();di();di();di();di();break;
                             case 7:da();da();di();di();di();break;
                             case 8:da();da();da();di();di();break;
            case 9:da();da();da();da();di();break;
                        }
for(q=0;q<33000;q++);
a=m%10;
    switch(a)
        {
                          case 0:da();da();da();da();da();break;
            case 1:di();da();da();da();da();break;
                             case 2:di();di();da();da();da();break;
                             case 3:di();di();di();da();da();break;
                             case 4:di();di();di();di();da();break;
                             case 5:di();di();di();di();di();break;
                             case 6:da();di();di();di();di();break;
                             case 7:da();da();di();di();di();break;
                             case 8:da();da();da();di();di();break;
            case 9:da();da();da();da();di();break;
                        }    
for(q=0;q<33000;q++);
}

//以下是主程序
void main()
{
tmod=0x01;
th0=0x3c;
tl0=0xb0;//50000,乘2u秒=0.1秒
ea=1;
et0=1;
tr0=1;
p2=0x00;
while(1)
  {
    if(m==0&&s==0)//正点报时
    {
    talk();
    }//正点报时
   
    if(p1_0==0)//按键报时
    {
    talk();
    }
    if(p1_1==0)//调整小时
    {
    while(p1_1==0)
        {
        h++;
        da();
        for(q=0;q<18000;q++);
        if(h==24)h=0;
        }
    talk();
    }
    if(p1_2==0)//调整分钟
    {
        while(p1_2==0)
          {
          m++;s=0;r=0;
        da();
        for(q=0;q<18000;q++);
        if(m==60)m=0;
          }    
      talk();
    }  
    while(p1_3==0)//同时按p13,p10键盘锁,静音
      {
                  if(p1_0==0)
                    {
        da();da();da();
                        for(q=0;q<22000;q++);
                        di();di();da();di();
                       for(q=0;q<22000;q++);
          di();di();da();di();//发off
          while(1)
                        {
            if(p1_3==0&&p1_0==0)break;//同时按p13,p10推出键盘锁,静音
                                   }
        da();da(); da();
                    for(q=0;q<22000;q++);
        da();di();
                        }
                  }
      }//while1结束
}//主程序结宿
离线paging
发帖
1377
只看该作者 1楼 发表于: 2007-09-27
同学习!!!

收录
离线bd9cr
发帖
1202
只看该作者 2楼 发表于: 2007-09-27
上传hex文件,
已经调试通,工作正常
附件: CLOCK.rar (0 K) 下载次数:85
离线szcharle
发帖
13335
只看该作者 3楼 发表于: 2007-09-27
初学就这个水平 楼主牛人!
离线BD0AAI
发帖
3050
只看该作者 4楼 发表于: 2007-09-27
加个ds1302多好呀
离线BG4UVR
发帖
11288
只看该作者 5楼 发表于: 2007-09-28
创意相当不错,支持~

另外建议:
三极管换成pnp的,这样在初始化状态,蜂鸣器里就不通直流了。另外led需要串个电阻,不然电流太大,可能让mcu和led都很受伤。

发cw的方法有些复杂,用了比较多的代码空间。可以把0-9的cw做一个10个元素的数组,用个函数发,会省事很多。可以参考一下:http://www.hellocq.net/forum/showthread.php?t=153790

蜂鸣器的发音,可以利用另一个定时器来完成。
离线bd9cr
发帖
1202
只看该作者 6楼 发表于: 2007-09-28
真是初学,从刚接触到现在有一个学期。

回六楼:::::::
我是一个很懒惰的人,51的输出电流很小我试过输出电流可以直接驱动led还不算很亮,也可以直接驱动三极管的基极,这样可以省了几个限流电阻。
但是灌入电流就要加限流电阻了。不知到高手们是什么看法。
初始化之后我是让p2为0的,这样灯和蜂鸣器都不工作的。但是复位的时候,他们会亮的,作为复位提示,也不错。
bg4uvr,我看过你搞的avr的程序的确很nb,我只是刚刚学点avr,我看过你的发cw的方法是很合理很老道的,我只是初学用了switch感觉自己很好实现。我会尝试学习你的方法,学习一些你的思路。
不过51的rom 4k,比你喜爱的tiny大多了^_^,我搞的小东西每次都用不到一半的rom。
希望大家共同探讨共同进步
离线bd9cr
发帖
1202
只看该作者 7楼 发表于: 2007-09-28
'
加个ds1302多好呀
'
我正在研究这个小东西,可真的很麻烦啊。
我现在在看别人的程序,时序的东西真让人头痛。感觉用起来不是很方便吧?调节时间要很麻烦吧?
不过这个小家火的确有很大的优势就是省电,估计用南伏电池能用好几年,单片机做时钟的耗电还是很大的。
我已经想过用单片机控制1302。平时把51关掉,只要1302工作。想报时或者显示的时候再给51供电。这样在省电上才有优势,才能达到电子表的水平,否则耗电太大了。
可惜我的1302已经买来,正在研究如何用他
离线BG4UVR
发帖
11288
只看该作者 8楼 发表于: 2007-09-28
'
真是初学,从刚接触到现在有一个学期。
回六楼:::::::
我是一个很懒惰的人,51的输出电流很小我试过输出电流可以直接驱动led还不算很亮,也可以直接驱动三极管的基极,这样可以省了几个限流电阻。
但是灌入电流就要加限流电阻了。不知到高手们是什么看法。
初始化之后我是让p2为0的,这样灯和蜂鸣器都不工作的。但是复位的时候,他们会亮的,作为复位提示,也不错。
bg4uvr,我看过你搞的avr的程序的确很nb,我只是刚刚学点avr,我看过你的发cw的方法是很合理很老道的,我只是初学用了switch感觉自己很好实现。我会尝试学习你的方法,学习一些你的思路。
不过51的rom 4k,比你喜爱的tiny大多了^_^,我搞的小东西每次都用不到一半的rom。
希望大家共同探讨共同进步
'

仔细想了一下,你驱动led的方法很巧妙,我原来想错了。

我也只是正在学习单片机中,代码中经常发现n多的错误,我已经习惯了

看另一个帖子,发现你也喜欢玩avr,希望大家能共同学习提高
离线BD0AAI
发帖
3050
只看该作者 9楼 发表于: 2007-09-28
'
我正在研究这个小东西,可真的很麻烦啊。
我现在在看别人的程序,时序的东西真让人头痛。感觉用起来不是很方便吧?调节时间要很麻烦吧?
不过这个小家火的确有很大的优势就是省电,估计用南伏电池能用好几年,单片机做时钟的耗电还是很大的。
我已经想过用单片机控制1302。平时把51关掉,只要1302工作。想报时或者显示的时候再给51供电。这样在省电上才有优势,才能达到电子表的水平,否则耗电太大了。
可惜我的1302已经买来,正在研究如何用他
'


不难, 网上可以搜到源程序,加上1302以后,还可以显示日期和星期,如果有备用电池(钮扣就够了,因为有涓流充电功能),闰月自动调整,cpu只管显示和设置就行了。还有几个字节的存储区,可以把闹铃写进去