矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
楼主: wey05

帮助新手学习单片机数码管电子钟:原理,c程序详解

  [复制链接]
发表于 2011-7-12 22:27:05 | 显示全部楼层
for example, the above _7seg files are written for common anode displays.

to run the code on a common cathode display, you need to make the following changes:
  1. #define _7SEG_ON(segs)                {_7SEG_PORT= (segs);}                        //turn on segments, active high
  2. #define _7SEG_OFF(segs)                {_7SEG_PORT=~(segs);}                        //turn off segments

  3. ...
  4. #define DIG_OFF(digs)                {DIG_PORT= (digs);}                                //turn off digs, active low
  5. #define DIG_ON(digs)                {DIG_PORT=~(digs);}                                //turn on digs
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2011-7-12 23:37:37 | 显示全部楼层
不错,有点复杂但通用性强,谢谢!
回复 支持 反对

使用道具 举报

发表于 2011-7-13 02:37:30 | 显示全部楼层
本帖最后由 millwood 于 2011-7-13 02:42 编辑

in the above example, we used a 7segment led display.

what if you want to use a lcd display?

here is the code.
  1. #include <regx51.h>                                                        //we use keil c51
  2. #include "gpio.h"
  3. #include "tmr0.h"                                                        //we use tmr0
  4. #include "rtc1.h"                                                        //we use tmr1
  5. #include "_7seg_lcd.h"                                                //7 segment lcd, up to 4 char

  6. //hardware configuration
  7. //end hardware configuration

  8. void rtc2vRAM(void) {
  9.         vRAM[0]=_rtc1.sec %10;                                        //second
  10.         vRAM[1]=_rtc1.sec / 10;

  11.         vRAM[2]=_rtc1.min % 10;                                        //minutes
  12.         vRAM[3]=_rtc1.min / 10;
  13. }


  14. void mcu_init(void) {
  15. }

  16. int main(void) {
  17.         mcu_init();                                                                //reset the mcu

  18.         _7seg_init();                                                        //reset the 7segment display
  19.        
  20.         tmr0_init(1, TMR_10ms);                                        //set tmr0 to trigger periodically
  21.         tmr0_act(_7seg_display);                                //show the display

  22.         rtc1_init(RTC_500ms);                                        //tmr1 to act like a rtc
  23.         rtc1_act(rtc2vRAM);                                                //install rtc timer

  24.         ei();                                                                        //enable global interrupt
  25.         while (1) {
  26.         }
  27. }


复制代码
look at how similar it is to the led version?

to the application code, it shouldn't matter how the actual display is done - as long as it is done.

that's the beautify of modular programming: you get to benefit from your prior investment in code.
53. c51 rtc lcd.PNG
回复 支持 反对

使用道具 举报

发表于 2011-7-13 19:39:31 | 显示全部楼层
目前还在研究中 谢谢!
回复 支持 反对

使用道具 举报

发表于 2011-7-14 03:20:44 | 显示全部楼层
有点复杂但通用性强


that's the point.

take the rtc module for example. to use it in your code, you need to do the following:

1) include "rtc0.h" in your application code;
2) call rtc0_init() to initialize the rtc so that it triggers periodically.
3) if you want the rtc to perform a job periodically, call rtc0_act() to install your own handler so that it will be called by rtc periodically.

to do that, you don't need to know how rtc0 does its job at all.

the same goes for the tmr or 7segment display modules: they have been purposefully packaged to shield the end users from the inner details.
回复 支持 反对

使用道具 举报

     
发表于 2011-7-14 10:58:09 | 显示全部楼层
如何设置时间?
回复 支持 反对

使用道具 举报

发表于 2011-7-23 08:16:53 | 显示全部楼层
请教两位:
如何让设置时间的时候闪动,比如我现在设置分钟,让分钟一闪一闪的,我现在不闪动调节。
回复 支持 反对

使用道具 举报

发表于 2011-7-25 05:59:25 | 显示全部楼层
如何让设置时间的时候闪动,


fairly easy: when .half_sec is 1/0, display the said segment; otherwise, display a blank (which you can define in the seg font table.
回复 支持 反对

使用道具 举报

     
发表于 2011-7-26 10:45:58 | 显示全部楼层
millwood   很讨厌!
回复 支持 反对

使用道具 举报

     
发表于 2011-7-26 10:48:20 | 显示全部楼层
喧宾夺主啊
回复 支持 反对

使用道具 举报

     
发表于 2011-7-26 11:05:59 | 显示全部楼层
LZ老师是在讲教程,不是在讨论吧,millwood 应该自己发个帖为好,这样不尊重本人哦,还用英文回帖,能看懂中文,还是用中文回好吧
回复 支持 反对

使用道具 举报

发表于 2011-7-28 10:17:50 | 显示全部楼层
本帖最后由 清风车影18 于 2011-7-28 10:19 编辑

回复 152# millwood


    谢谢你!根据你的提示。我已经制作成功。在分别调节时间和闹钟的分时秒的时候,相应调节的内容闪动。代码如下:
定时器2的中断服务程序
TF2=0;                          
count++;
if(count==8) sechalf=1;  // 这个是半秒标志。中国英文写。sec秒的意思,half是半的意思。
  if(count==16)                  // T2定时器的预装载值为0x0BDC,溢出16次就是1秒钟。
   {count=0;
    sechalf=0;                     //当一秒的时候归零。 这样sechalf的值就是0或1.
    sec++;

然后在显示函数中:部分代码
if(disp>5&&disp<8)   //这个是数码管显示的第6,7位,就是显示小时。
  {
    if(fount==2)       //这个是功能按键标志位,当fount=0,表示调节秒fount=1调节分,=2调节小时,一直到等于8调节年(我做成万年历了。)
         {
           if(sechalf==1)
           P0=tab[11];
           else P0=tab[weima[disp]];
         }
          else P0=tab[weima[disp]];
  }

然后在增加和减下按键内,相应是设置 :
if(fount==2)        //功能2 调小时
   {
     if(kjia==0)  
      {         delay1(1);
              if(kjia==0)
              {
                   while(!kjia);
               hour++;
                   if(hour==24) hour=0;
                   }
      }
       
          if(kjian==0)
       {   delay1(1);
               if(kjian==0)
                      {
            while(!kjian);
                hour--;
                    if(hour==-1) hour=23;
                          }
      }
        }

以上代码完全通过。我实际焊接的板上运行。
另外我利用了定时器2,精度很高。我和我的CDMA的手机比较,(cdma的时间是台上统一的)一天24小时基本上慢3秒。
我用软件的方法可以在菜单中设置时间精度,从每天1.5秒到35秒之间可以调节(快慢都可以调)

现在唯一不满意的就是闹钟,以及闹钟取消,尽管现在也可以用没有任何问题,但是感觉程序有点乱。
/****************闹铃程序*************/
  void naoling()
   {
        if(ring==0)   //等于0 允许闹铃,1不允许。当取消按键按下的时候,值变为1.在min!=armmin的时候,这个值变为0
    {
          if(min==armmin&&hour==armhour)
             {          if(sechalf==1)        buzzer=1;
                         else           buzzer=0;               
             }
         else           buzzer=1;
                   
    }
   if(min!=armmin)
   {
    ring=0;
   }
  
   if(hour>7&&hour<22)           //整点报时
   {if(min==0&&sec==0)
        { buzzer=0;
          delay1(1);
          buzzer=1;
        }
        }
  }

不知道两位对这个有什么高见

另外非常感谢两位对我的帮助。我自己感觉长进很多!
坛子大了,什么鸟都有,不要太在意别人说什么。
回复 支持 反对

使用道具 举报

发表于 2011-7-28 20:26:04 | 显示全部楼层
i'm glad that you made it work.

as to your alarm function: i am assuming that naoling() is called frequently.

1) buzzer goes on / off every half second if time is up (alarm hour/min=actual hour/min);
2) from 800 - 2100, the alarm sounds on the hour for SEC_MINIMUM seconds;

so something like this may work:

void naoling(void) {
  if ((alarmhour == hour) && (alarmmin == min))
    buzzer = (ring)?0:sechalf; // only sound buzzer if alarm is enabled (ring=0)
  if ((hour>7) && (hour<22)) {
    if ((min==0) && (sec < SEC_MINIMUM)) buzzer=sechalf; //buzzer sounds for half a second and then off
  } else buzzer = 0;  //turn buzzer off
}

you can define SEC_MINIMUM to be the duration of 整点报时
回复 支持 反对

使用道具 举报

发表于 2011-7-28 20:52:25 | 显示全部楼层
回复 157# millwood


  谢谢 刚看到你的回复。我在仔细琢磨一下。
回复 支持 反对

使用道具 举报

发表于 2011-8-2 09:00:37 | 显示全部楼层
这两天陆续增加了闹钟整点报时功能,其中整点报时是几点响几声。
增加了 万年历闰月功能。
增加了存贮芯片,将设定的闹钟和最近的日期可以自动保存。在断电后在开机只需要重新调整时间。
现在想增加闹钟选择功能,比如礼拜一到礼拜五闹钟启动。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

蒙公网安备 15040402000005号

GMT+8, 2024-5-2 23:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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