打印

diy(2)简易数字钟

[复制链接]
2759|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
面对你|  楼主 | 2008-11-4 09:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在做单片机系统的项目设计,自己的系统板还在厂家制作,要一段时间才能送来,借用同学的小开发板先写了一个简易数字钟程序!
基本情况如下:
硬件平台:单片机:华邦系列W78E516B40DL
            晶振:12MHZ
            8个二极管
                      四个数码管
                      四个按键
                      一个温度传感器
                      串口通信:MAX232
软件平台:Keil uVision2
开发语言:C语言
程序下载软件:8051IspWriter.exe
程序实现功能:4个数码管依次显示分钟和秒钟,4个按键,按SW1,SW2,SW3,SW4依次实现分钟,秒钟的十位,个位加一!
最终源程序如下:
 #include<reg51.h>
#include<absacc.h>
#define uchar unsigned char
#define uint unsigned int
uchar  *dis_ptr;
uchar data dis_buf[4]={0,0,0,0};//显示缓冲区
uchar data time_buf[2]={0x00,0x00};//显示数据
uchar code seg_tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
    0xf8,0x80,0x90,0xff};//7段共阳极,依次为0-9
uchar code digit_tab[4]={1,2,4,8};//动态显示缓冲区
uint m=0;
uint n=0;
uint key_flag=0;
sbit p24=P2^4;
sbit p25=P2^5;
sbit p26=P2^6;
sbit p27=P2^7;
void init_sys();
void disply_one(void);
void dis_buf_flash(void);
bit key_test(void);
void key(void);
void key_delay();
void main()
{init_sys();
for(;;);}
void init_sys(void)//T0工作于方式2,定时250um,
{
dis_ptr=dis_buf+3;
TH0=6;
TL0=6;
TMOD=2;
IE=0x82;
IP=2;
TR0=1;
}

void disply_one(void)//动态显示1位
{uchar i;
P0=seg_tab[*dis_ptr];
i=dis_ptr-dis_buf;
P2=~digit_tab;
if (dis_ptr>dis_buf)
    dis_ptr--;
else dis_ptr=dis_buf+3;
}


void dis_buf_flash(void)//显示数据送缓冲区
{
dis_buf[0]=time_buf[0]/10;
dis_buf[1]=time_buf[0]%10;
dis_buf[2]=time_buf[1]/10;
dis_buf[3]=time_buf[1]%10;
}


void time0(void) interrupt 1 
{   
            
                  TF0=0;
                   m++;
                   n++;
                   if(key_test()==0)
                        {key_delay();
                        if(key_test()==0)
                        {key_flag=0;}
                        }
                   if ((n>=40)&&(key_flag==0))//10ms扫描键盘
                   {n=0;
                   key_test();//扫描键盘
                   if(key_test()==1){
                      key_delay(); 
                      if(key_test()==1)
                           {key();}
                      
                                     }
                   }
                  if (m>=4000)//1秒处理
                 {    m=0;
                      time_buf[1]+=1;
                       if (time_buf[1]>=60)//1分处理
                       {time_buf[1]=0;
                        time_buf[0]+=1;}
                      if (time_buf[0]>=60)//1时处理
                      {time_buf[0]=0;
                       time_buf[1]=0;}
                       
                   }
        
    dis_buf_flash();
    disply_one(); 
                           
 }
bit key_test(void)//测试键盘有无键按下
{
if ((p24==0)||(p25==0)||(p26==0)||(p27==0))
return ((bit)1);
else return ((bit)0);
}


void key(void)//按键处理
{key_flag=1;
if(p24==0){
   time_buf[0]+=10;}
    else if(p25==0){time_buf[0]+=1;}
        else if(p26==0){time_buf[1]+=10;}
else time_buf[1]+=1;


}
                   

void key_delay()
{uchar i,s;
for(i=10000,s=5;s>=1;i--)
    {s=i;}
}
最终正常显示,按键可调!

中途遇到的问题:
按单键无反映!只有一起按紧SW1和SW2才出现分钟的两位一直向上加,但也不可控制加的大小!
解决1:在按键和释放键的时候加一个去抖动延迟函数
void key_delay()
{uchar i,s;
for(i=10000,s=5;s>=1;i--)
    {s=i;}
结果:

按每个按键都能改变相应的位数的数字,但不可控制。改变太快!

解决2:加一个扫描标志,当检测到有键按下时,停止扫描键盘,当键释放时,继续扫描键盘
这样就能保证按一次键被扫描一次,从而实现加一。

相关帖子

沙发
面对你|  楼主 | 2008-11-4 12:07 | 只看该作者

diy-更改

上述7段数码管为共阴极,注释成了共阳极了!
不好意思!

使用特权

评论回复
板凳
面对你|  楼主 | 2008-11-4 15:56 | 只看该作者

diy(2)错误更改

上述程序语句会让程序能正常执行,显示
但时间误差太大!
达到60:100
分析可能有什么程序断在中断中被延时!
调试后发现问题出在中断中的
                      if(key_test()==0)
                        {key_delay();
                        if(key_test()==0
                          {key_flag=0;}
               }
因为我设置了标志位用来标志有键按下时停止扫描键盘!无键按下时扫描键盘,
这就导致没键按下时,每次都要延迟,一个中断延时一次,1秒下来就误差很多了
解决办法:把上述程序段中的延时程序去了!再经调试,能准确显示了!误差为极小!约为1秒左右!

使用特权

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

本版积分规则

4

主题

7

帖子

0

粉丝