还是时钟问题,把时钟程序分开成3个文件了

[复制链接]
5749|53
 楼主| 雷影少年 发表于 2012-7-5 12:19 | 显示全部楼层
再次感谢版主
 楼主| 雷影少年 发表于 2012-7-5 12:20 | 显示全部楼层
void get_clock(u8 sec,min,hour)
在这里只转换一次点阵即可
另外你这个写法也...
void get_clock(u8 sec, u8  min, u8  hour)
sedatefire 发表于 2012-7-5 12:03

这里不错代码运行效率又有提高了
sedatefire 发表于 2012-7-5 17:44 | 显示全部楼层
本帖最后由 sedatefire 于 2012-7-6 09:46 编辑

void get_clock(u8 sec, u8  min, u8  hour)
{
     u8  buf[8+1];
     u8 i;
     sprintf(buf, "%02u\x0A%02u\x0A%02u",  \
                            (uint)hour,  (uint)min, (uint)sec);
     for (i=0; i<8; i++)
     {
          dot = seg[ buf & 0x0F ];
     }
}
sedatefire 发表于 2012-7-5 17:44 | 显示全部楼层
本帖最后由 sedatefire 于 2012-7-5 17:46 编辑

void display_polling5ms(void)
{
       static  u8 i = 0;
       P0 =0xff;
       P2 =  wei;
       P0 =  dot; /* 存放的直接是点阵 */
       i = (i+1)&0x07;
}
结合上面的get_clock,这样就比较符合自然的思想

没有冗余的动作,点阵该转换时就只转一次
显示就专门只管显示即可

 楼主| 雷影少年 发表于 2012-7-5 21:40 | 显示全部楼层
void get_clock(u8 sec, u8  min, u8  hour)
{
     u8  buf[8+1];
     u8 i;
     sprintf(buf, "%02u\x0A%02u\x0A%02u",  \
                            (uint)hour,  (uint)min, (uint)sec);
     for (i=0; i ...
sedatefire 发表于 2012-7-5 17:44

为什么要用整型,用字符型不是更好些吗?这里有什么说法?
sedatefire 发表于 2012-7-6 09:45 | 显示全部楼层
为什么要用整型,用字符型不是更好些吗?这里有什么说法?
雷影少年 发表于 2012-7-5 21:40

c51的%u要求必须强制转换成整型的,否则就是乱码
sedatefire 发表于 2012-7-6 09:46 | 显示全部楼层
当然%c应该就不需要这样搞了
不过我貌似没用过,没经验
sedatefire 发表于 2012-7-6 09:47 | 显示全部楼层
奇怪,我发现如果编辑旧的帖子
[i]这个老是显示不出来,好奇怪
   for (i=0; i<8; i++)
     {
          dot[i] = seg[ buf & 0x0F ];
     }
sedatefire 发表于 2012-7-6 09:52 | 显示全部楼层
综上所诉,主函数的写法,思路就很清晰了,而且显示效果刚刚的
/**/
int  main(void)
{
      system_init();
      while (1)
      {
              if (read_and_clear_5ms_flag())
              {
                     clock_update();    /* 详见上一个帖子 */
                     display_polling5ms();
              }
      }
      return 0;
}
sedatefire 发表于 2012-7-6 09:58 | 显示全部楼层
另外有一疑问
#inclued"time.c"与#include"time.h"有什么区别?
选用的规则是什么?
雷影少年 发表于 2012-7-4 22:24

这个我都不知道如何回答你
前者仅仅是简单的文件划分而已,后者实现模块真正的独立
将来,你可以把timer.c  timer.h单独拿来重复使用。

使用后者,
1.你可以任意修改timer.c里面的代码,变量名,函数算法等等,而不会影响到main.c档
2.你可以单独查看timer.c的编译汇编档,而不是得到一个杂糅在一起的乱七八糟的main汇编档。
3.使用后者,编译速度会变快,编译器可以只编译被修改过的.c档
你这种写法,任意.c档的修改,都会造成全部重新编译。
4.你这样写,无所谓变量作用域,main.c同样可以访问timer.c的static全局变量。
起不到封装的效果。
5.......
 楼主| 雷影少年 发表于 2012-7-6 10:43 | 显示全部楼层
当然%c应该就不需要这样搞了
不过我貌似没用过,没经验
sedatefire 发表于 2012-7-6 09:46

哦~
我写下感受感受
 楼主| 雷影少年 发表于 2012-7-6 10:46 | 显示全部楼层
综上所诉,主函数的写法,思路就很清晰了,而且显示效果刚刚的
/**/
int  main(void)
{
      system_init();
      while (1)
      {
              if (read_and_clear_5ms_flag())
              {
             ...
sedatefire 发表于 2012-7-6 09:52

“return 0;”是做什么用的,主函数进入大循环后一个是无限循环下去的啊,怎么运行到“ return 0;”这一行?
如果运行不到为什么还要返回值?直接定义void类型不可以吗?
 楼主| 雷影少年 发表于 2012-7-6 10:48 | 显示全部楼层
这个我都不知道如何回答你
前者仅仅是简单的文件划分而已,后者实现模块真正的独立
将来,你可以把timer.c  timer.h单独拿来重复使用。

使用后者,
1.你可以任意修改timer.c里面的代码,变量名,函数算法等等,而 ...
sedatefire 发表于 2012-7-6 09:58

好吧~
我也看的有点晕~
估计以后程序写多了,有直接的体会后才能明白这些~
 楼主| 雷影少年 发表于 2012-7-6 14:07 | 显示全部楼层
本帖最后由 雷影少年 于 2012-7-6 14:13 编辑

我又修改了下程序
源程序如下:
  1. main.c文件
  2. /*数字时钟程序*/
  3. #include<reg51.h>
  4. #include"display.c" //显示子程序
  5. #include"time.c" //时钟更新子程序
  6. #define count 3686
  7. u8 flag_5ms=0;

  8. void main(void)
  9. {
  10. EA =1; //开中断
  11. ET0 =1;
  12. TMOD =0x01;
  13. TH0 =-(count/256);
  14. TL0 =-(count%256);
  15. TR0 =1;
  16. time();
  17. while (1)
  18. {
  19. static u8 flag_1s=0;
  20. if (flag_5ms)
  21. {
  22. flag_5ms=0;
  23. display(); //每4ms调用一次显示子程序
  24. if(++flag_1s==250) //每秒更新一次时间
  25. {
  26. flag_1s=0;
  27. time();
  28. }
  29. }
  30. }
  31. }
  32. void time50() interrupt 1 //每4ms中断一次
  33. {
  34. TH0=-(count/256);
  35. TL0=-(count%256);
  36. flag_4ms=1;
  37. }

  38. display.c文件
  39. /*时钟显示子模块*/
  40. typedef unsigned char u8 ;
  41. /*初始化数组 时间显示
  42. 选择数码管位(从左至右)
  43. 数码管显示缓冲*/
  44. u8 code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
  45. u8 code wei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
  46. u8 seg1[]={0,1,2,3,4,5,6,7};


  47. /*将当前时间放入缓冲区*/
  48. void get_clock(u8 sec,min,hour)
  49. {
  50. seg1[7] =sec%10;
  51. seg1[6] =sec/10;
  52. seg1[5]=10;
  53. seg1[4] =min%10;
  54. seg1[3] =min/10;
  55. seg1[2]=10;
  56. seg1[1] =hour%10;
  57. seg1[0] =hour/10;
  58. }
  59. /*显示子程序*/

  60. void display() // 动态显示
  61. {
  62. static u8 i=0;
  63. P0 =0xff;
  64. P2 =wei;
  65. P0 =seg[seg1];
  66. i=(i+1)&0x07;
  67. // delay(10);
  68. }


  69. time.c文件
  70. /*时间更新模块*/
  71. static u8 sec =50; //装载时钟秒初始值
  72. static u8 min =59; //装载分初始值
  73. static u8 hour =23; //装载时初始值
  74. void time(void)
  75. {

  76. if ( ++sec>=60) //秒更新
  77. {
  78. sec=0;
  79. if (++min>=60) //分更新
  80. {
  81. min =0;
  82. if (++hour>=23) //时更新
  83. hour =0;
  84. }
  85. }
  86. get_clock(sec,min,hour); //更新缓冲区数据
  87. }
因为是8位数码管,5ms的中断延时闪烁的很厉害,改成了4ms虽然还是有点闪,但是还能用
关于get_clock函数我没有更改,因为如果调用sprintf函数的话要加头文件stdio.h,程序会不会变得更麻烦了?
 楼主| 雷影少年 发表于 2012-7-6 14:15 | 显示全部楼层
哈哈~
我也会插入代码啦~
sedatefire 发表于 2012-7-13 14:59 | 显示全部楼层
其实,还有许多可以抠的细节之处
比如,计数器的精度
你在中断中这样写,是会有精度误差的,你自己先想看看,原因何在?
void time50() interrupt 1 //每4ms中断一次
{

TH0=-(count/256);

TL0=-(count%256);

flag_4ms=1;

}
sedatefire 发表于 2012-7-13 15:07 | 显示全部楼层
再比如,
if (++hour>=23) //时更新
hour =0;

1.你这个逻辑上写错了,要用>号
2. 我以前之所以写成下面这样,是为了程序的可读性
if (++hour>=24)
或者
if (++min>=60)
3.之所以要求哪怕是只有一句指令也要{}包起来,
是因为以后的代码维护,当你要添加代码do_something_2 时,你会随意添加而忘了加{},如下
if (xxx)
    do_something_1
    do_something_2 /* 此处将造成隐性bug*/
do_otherthing
所以要养成良好的习惯
写成
if (xxx)
{
    do_something_1
}
else
{
     do_otherthing
}
sedatefire 发表于 2012-7-13 15:10 | 显示全部楼层
实际上,我在工作中,哪怕没有do_otherthing的需要
我也会写成这样
if (xxx)
{
    do_something_1
}
else
{
}
或者这样
if (xxx)
{
    do_something_1
}
/* else{} */
一来自己在程序编写过程中强迫自己充分考虑各种情况。
二来告诉程序的阅读者,else的情况我已经充分考虑过了,不必怀疑我漏掉了
sedatefire 发表于 2012-7-13 15:10 | 显示全部楼层
再比如,
if (++hour>=23) //时更新
hour =0;

1.你这个逻辑上写错了,要用>号
2. 我以前之所以写成下面这样,是为了程序的可读性,写59,23对于阅读者来讲,会愣几秒钟才反应过来你的意图。
if (++hour>=24)
或者
if (++min>=60)
3.之所以要求哪怕是只有一句指令也要{}包起 ...
sedatefire 发表于 2012-7-13 15:07
sedatefire 发表于 2012-7-13 15:11 | 显示全部楼层
2. 我以前之所以写成下面这样,是为了程序的可读性,写59,23对于阅读者来讲,会愣几秒钟才反应过来你的意图。
if (++hour>=24)
或者
if (++min>=60)
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部