打印

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

[复制链接]
4705|53
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
雷影少年|  楼主 | 2012-7-3 23:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 雷影少年 于 2012-7-4 16:09 编辑

经过各位大神提点,本菜鸟又啃了几天书,今天试着写下外部程序,还是写不好请各位大神指点下

下[code]面是源程序:

/*数字时钟程序*/
#include<reg51.h>
#include"display.c" //显示子程序
#include"time.c" //时钟更新子程序
u8 count;

void main(void)
{
EA =1; //开中断
ET0 =1;
TMOD =0x01;
TH0 =-(50000/256);
TL0 =-(50000%256);
TR0 =1;
while (1)
{
// count=time(count); //调用时中更新子程序
time(count);
delay(10); //延时
}
}
void time50() interrupt 1 //每50ms中断一次
{
TH0=-(50000/256);
TL0=-(50000%256);
count++;
}



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

/*延时子程序*/
void delay(u8 x)
{
u8 a,b;
for (a=x;a>0;a--)
for (b=100;b>0;b--);

}

/*显示子程序*/
void display(u8 sec,min,hour)
{
u8 i;
seg1[7] =sec%10; //将时间放至缓冲区
seg1[6] =sec/10;
seg1[5]=10;
seg1[4] =min%10;
seg1[3] =min/10;
seg1[2]=10;
seg1[1] =hour%10;
seg1[0] =hour/10;
for (i=0;i<8;i++) // 动态显示
{
P0 =0xff;
P2 =wei;
P0 =seg[seg1];
delay(10);
}
}




/*时间更新模块*/
//u8 time(count)
void time(count)
{
static u8 sec =50; //装载时钟秒初始值
static u8 min =59; //装载分初始值
static u8 hour =23; //装载时初始值

if (count==20)
{
count =0;
if ( ++sec>=60) //秒更新
{
sec=0;
if (++min>=60) //分更新
{
min =0;
if (++hour>=23) //时更新
hour =0;
}
}
}
display(sec,min,hour); //调用显示子程序
// return count; //返回count值
}


]count我定义的是全局变量,在调用time子程序的时如果子程序的count发生变化,主程序中的count为什么不变化啊?

如果把//return count这句取消注释,后时钟能够走时、进位,但是速度大约是正常时间的1/15;实在不明白是为什么?

求各位大神指点啊~
[code]

相关帖子

沙发
雷影少年|  楼主 | 2012-7-4 10:57 | 只看该作者
改了下程序问题解决了,尽管不明白是为什么
/*数字时钟程序*/
#include<reg51.h>
#include"display.c"   //显示子程序
#include"time.c"   //时钟更新子程序
#define ms_50 50000
u8 count;
void main(void)
{
EA =1;      //开中断
ET0 =1;
TMOD =0x01;
TH0 =-(ms_50/256);
TL0 =-(ms_50%256);
TR0 =1;
time();
while (1)
{
  if (count==20)   //每秒更新一次时间
  {
   coun t=0;
   time();
  }
  display();      //调用显示子程序
  delay(10);    //延时
}
}
void time50() interrupt 1       //每50ms中断一次
{
TH0=-(ms_50/256);
TL0=-(ms_50%256);
count++;
}



/*时间更新模块*/
void time(void)
{
static u8 sec =50;  //装载时钟秒初始值
static u8 min =59;  //装载分初始值
static u8 hour =23;  //装载时初始值
  if ( ++sec>=60)   //秒更新
  {
   sec=0;
   if (++min>=60)   //分更新
   {
    min =0;
    if (++hour>=23)   //时更新
    hour =0;
   }
  }
   get_clock(sec,min,hour);    //更新缓冲区数据
}



/*时钟显示子模块*/

typedef unsigned char u8 ;
/*初始化数组 时间显示
    选择数码管位(从左至右)
    数码管显示缓冲*/
u8 code seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
u8 code wei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
u8   seg1[]={0,1,2,3,4,5,6,7};
/*延时子程序*/
void delay(u8 x)
{
u8 a,b;
for (a=x;a>0;a--)
  for (b=100;b>0;b--);
}
/*将当前时间放入缓冲区*/
void get_clock(u8 sec,min,hour)
{
seg1[7] =sec%10;   
seg1[6] =sec/10;
seg1[5]=10;
seg1[4] =min%10;
seg1[3] =min/10;
seg1[2]=10;
seg1[1] =hour%10;
seg1[0] =hour/10;
}
/*显示子程序*/
void display()
{ u8 i;
for (i=0;i<8;i++)  // 动态显示
{
  P0 =0xff;
  P2 =wei[i];
  P0 =seg[seg1[i]];
  delay(10);
}
}

使用特权

评论回复
板凳
sedatefire| | 2012-7-4 21:09 | 只看该作者
好吧,准备花些时间直接给你答案啦

使用特权

评论回复
地板
sedatefire| | 2012-7-4 21:12 | 只看该作者
先是timer模块
timer.h
#ifndef __TIMER_H
#define __TIMER_H
/****************************************/
extern void timer_init(void);
extern  uint_fast8_t  read_and_clear_50ms_flag(void);
/****************************************/
#endif

使用特权

评论回复
5
sedatefire| | 2012-7-4 21:19 | 只看该作者
本帖最后由 sedatefire 于 2012-7-5 11:56 编辑

/*
timer.c
*/
#include "includes.h"
/****************************************/
static  uint_fast8_t   flag_5ms = 0;
/****************************************/
extern void timer_init(void)
{
   /*自己填吧*/
}
/****************************************/
extern  uint_fast8_t  read_and_clear_5ms_flag(void)
{
      uint_fast8_t  flag;
      flag = flag_5ms;
      if (flag)
     {
            flag_5ms = 0;
     }
     return flag;
}
/****************************************/
void timer5ms() interrupt 1       //每5ms中断一次
{
     /* 把常量宏大写,另外io翻转测看看5ms准确吗 ?*/
    /* 重置计数器 */

     flag_5ms = 1;
}

使用特权

评论回复
6
sedatefire| | 2012-7-4 21:21 | 只看该作者
#include"display.c"   //显示子程序
#include"time.c"   //时钟更新子程序
这个,虽然有进步,但也不是这样干的
*.c档是单独编译的
然后才由链接器链接在一起

使用特权

评论回复
7
sedatefire| | 2012-7-4 21:27 | 只看该作者
void display()
{ u8 i;
for (i=0;i<8;i++)  // 动态显示
{
  P0 =0xff;
  P2 =wei[i];
  P0 =seg[seg1[i]];
  delay(10);
}
}
这个delay会带来意想不到的问题,
等你判断
while (1)
{
  if (count==20)   //每秒更新一次时间
  {
   coun t=0;
   time();
  }
  display();      //调用显示子程序
  delay(10);    //延时
}
的时候,count可能早就超过20了

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
雷影少年 + 1 我很赞同
8
sedatefire| | 2012-7-4 21:34 | 只看该作者
所以即使你想那样写
也要写成
if (count >= 20)   //每秒更新一次时间
{
    count -= 20;
}

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
雷影少年 + 1 我很赞同
9
sedatefire| | 2012-7-4 21:38 | 只看该作者
不一定要刷屏到完,还要硬延时,每次只刷一个,总时间控制在40ms以内,应该就不会感受到闪烁了
所以如下写法,挂在5ms即可
void display(void)
{
static  u8 i = 0;

  P0 =0xff;
  P2 =wei[i];
  P0 =seg[seg1[i]];
  i = (i+1)&0x07;
}

使用特权

评论回复
10
雷影少年|  楼主 | 2012-7-4 22:22 | 只看该作者
谢谢斑竹的耐心讲解
新手上路各种纠结,正是因为有斑竹这样耐心的前辈,所以才能走的更稳、更远...
看到斑竹的回复不禁感叹自己的确有太多思虑不周的地方
像 :
所以即使你想那样写
也要写成
if (count >= 20) //每秒更新一次时间
{
count -= 20;
}



使用特权

评论回复
11
雷影少年|  楼主 | 2012-7-4 22:22 | 只看该作者
但也有许多不太赞同的地方
比如:
extern uint_fast8_t read_and_clear_50ms_flag(void)
这个函数的函数名也太长了吧~
或许是因为我没编过大型程序的关系吧~
最起码目前的我是不会命名这么长的名字的函数或者变量

使用特权

评论回复
12
雷影少年|  楼主 | 2012-7-4 22:22 | 只看该作者
关于
/* 把常量宏大写,另外io翻转测看看50ms准确吗 ?*/
/* 重置计数器 */

确实忘了把常量宏大写了,因为我的单片机晶振是11.0592MHZ,所以MS_50的值应该是46080,通过调试观察到此时误差是1/1000s

使用特权

评论回复
13
雷影少年|  楼主 | 2012-7-4 22:24 | 只看该作者
另外有一疑问
#inclued"time.c"与#include"time.h"有什么区别?
选用的规则是什么?

使用特权

评论回复
14
雷影少年|  楼主 | 2012-7-4 22:27 | 只看该作者
本帖最后由 雷影少年 于 2012-7-4 22:30 编辑

void display(void)
{
static  u8 i = 0;

  P0 =0xff;
  P2 =wei
;
  P0 =seg[seg1
];
  i = (i+1)&0x07;
}

“ i = (i+1)&0x07;”用的秒啊~

要我写肯定是
if(++i>=8)
i=0;

使用特权

评论回复
15
sedatefire| | 2012-7-5 11:55 | 只看该作者
但也有许多不太赞同的地方
比如:
extern uint_fast8_t read_and_clear_50ms_flag(void)
这个函数的函数名也太长了吧~
或许是因为我没编过大型程序的关系吧~
最起码目前的我是不会命名这么长的名字的函数或者变量
...
雷影少年 发表于 2012-7-4 22:22

函数名长是为了让你看的懂,顾名思义即可

使用特权

评论回复
16
sedatefire| | 2012-7-5 11:57 | 只看该作者
/*
timer.c
*/
#include "includes.h"
/****************************************/
static  uint_fast8_t   flag_5ms = 0;
/****************************************/
extern void timer_init(void)
{
   /*自己 ...
sedatefire 发表于 2012-7-4 21:19

我重新编辑了,改为5ms的

使用特权

评论回复
17
sedatefire| | 2012-7-5 12:01 | 只看该作者
改成5ms事情就很好做了
display写法可以再次升级,不必每次都点阵转换,你这样等于做了重复的工作
void display_polling5ms(void)
{
       static  u8 i = 0;
       P0 =0xff;
       P2 =wei[i];
       P0 =seg1[i]; /* 存放的直接是点阵 */
       i = (i+1)&0x07;
}

使用特权

评论回复
18
sedatefire| | 2012-7-5 12:03 | 只看该作者
void get_clock(u8 sec,min,hour)
在这里只转换一次点阵即可
另外你这个写法也...
void get_clock(u8 sec, u8  min, u8  hour)

使用特权

评论回复
19
sedatefire| | 2012-7-5 12:04 | 只看该作者
void time(count)
{
}
这样编译不过吧  没指明参数类型啊

使用特权

评论回复
20
雷影少年|  楼主 | 2012-7-5 12:11 | 只看该作者
void time(count)
{
}
这样编译不过吧  没指明参数类型啊
sedatefire 发表于 2012-7-5 12:04

嗯~,我调试程序的时候改的,没注意

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:高明的设计不在于是否用了最新的技术,在于是否能用最小的成本做出可靠的东西来。

11

主题

714

帖子

0

粉丝