基于51单片机的高精度时钟设计

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 基本要求
  • 设计思路
  • 代码
  • 最终效果


基本要求

使用定时器/计数器实现电子钟,用LED数码管显示时、分、秒,24小时制,数码管上电初始显示为“12.00.00”,到24小时清零,然后反复,晶振11.0592MHz。理论误差小于0.1秒/天

扩展要求:简单的可调电子钟。增加“时增加”、“分增加”2个按键,按下“时增加”按键,时显示加1,加满24归零,按下“分增加”按键时,分显示加1,加满60归零。


设计思路

开启定时器中断,在定时器中断函数中设置时间变量,用于在main函数中计算小时, 分钟,秒。这里我采用的是定时器0的工作方式一,因为从定时,计数器产生中断请求到响应中断,需要3~8个机器周期。定时中断子程序中的数据人栈和重装定时,计数器的初值还需要占用数个机器周期。此外,从中断入口转到中断子程序也要占用一定的 机器周期。所以要在定时器中断中进行误差补偿,我开发板中用的是11.0592M的晶振, 那么一个机器周期为(1/11.0592M)*12,定时50ms为(50*10^-3)/机器周期=46080。可以 将TH0和TL0从产生溢出到被重新赋值的已有的计数值读出,并补偿到计数值初值中去,可以消除定时/计数器的定时误差。

先在定时器中断中禁止所有中断请求,关闭T0,即EA=0,TR0=0,将TL0中已计数 值写入修正变量fixtime,并加上修正操作所需的机器周期,经过仿真调试大概为10 个机器周期,即0x0A,所以fixtime=TL0+0x0A,再将fixtime赋给TL0,因为 (65536-46080)%256=0,所以新的TL0=0+fixtime,因为(65536-46080)/256=76=0x4C,且在 修正TL0时可能产生进位,要补偿到TH0,所以TH0=0x4C+(char)CY,CY为PSW寄存器中的进位标志位,之后再开启所有中断请求,开启T0,即EA=1,TR0=1。这样就完成了整个定时器误差补偿的过程。

利用数码管的动态扫描方式,将计算得出的时间分别给到给数码管显示数组中的常量表达式中,让数码管动态显示时间。

利用两个按键改变小时和分钟的数值,那么按键应进行消抖处理,且不能用while语句 进行按键释放处理,那样可能会导致数码管闪动。可以先定义一个有返回值的按键扫描 函数Key_Scan( ),让它返回按键值1或2,无按键按下则返回0。再定义一个按键处理 函数KEY_Handle( ),在函数中进行位运算,key_value用于记录按键 值,key_up用于记 录按键释放,key_down用于记录哪个按键按下,key_old用于记录上次的按键值,此函数可以实现“记忆”功能,即如果按键一直按着,也不会出现多次触发的现象,也解决了用while语句检测按键释放而导致数码管闪动的问题。再将此函数放入定时器1的中断处理函数中,进行每50ms一次的按键扫描,定时器1同样也进行误差补偿处理。

代码

代码如下:

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
    
sbit dula = P2^6;
sbit wela = P2^7;
sbit key1 = P3^4;
sbit key2 = P3^5;

uchar fixtime;    

uint count_miao,count_fen0,count_fen1,count_shi,num_miao,num_fen,num_shi; 

uint ge,shi,bai,qian,wan,shiwan;

uchar key_value,key_up,key_down,key_old;

float number,uwTick,uwTick_KEY;

uchar table[] =
{
    0x3f,0x06,0x5b,0x4f,
    0x66,0x6d,0x7d,0x07,
    0x7f,0x6f,0x77,0x7c,
    0x39,0x5e,0x79,0x71
};


uchar table_dot[]=
{
    0xbf,0x86,0xdb,0xcf,
    0xe6,0xed,0xfd,0x87,
    0xff,0xef,0xf7,0xfc,
    0xb9,0xde,0xf9,0xf1
};


void delay(unsigned int x)
{
    unsigned int i,j;
    for(i=1;i>0;i--)
        for(j=x;j>0;j--);
}


void clean()
{
    wela = 1;
    P0 = 0xff;
    wela = 0;
    
    dula = 1;
    P0 = 0x00;
    dula = 0;
}


void dula_open()
{
    dula = 1;
    dula = 0;
    P0 = 0xff;
}

void wela_open()
{
    wela = 1;
    wela = 0;
    delay(1);
    clean();
}

void display(uint shiwan,uint wan,uint qian,uint bai,uint shi,uint ge)
{
    P0 = table[shi];
    dula_open();
    
    P0 = 0xef;
    wela_open();
    
    P0 = table[ge];
    dula_open();
    
    P0 = 0xdf;
    wela_open();
    
    P0 = table[qian];
    dula_open();
    
    P0 = 0xfb;
    wela_open();
    
    P0 = table_dot[bai];
    dula_open();
    
    P0 = 0xf7;
    wela_open();

    P0 = table[shiwan];
    dula_open();
    
    P0 = 0xfe;
    wela_open();
    
    
    P0 = table_dot[wan];
    dula_open();
    
    P0 = 0xfd;
    wela_open();    
}


uchar key_scan()
{
    uchar key = 0;
    if(key1 == 0)
    {
        return key = 1;
    }
    
    if(key2 == 0)
    {
        return key = 2;
    }
    
    return key;
}



void key_handle()
{
    key_value = key_scan();
    key_down  = key_value & (key_value ^ key_old);
    key_up    = ~key_value & (key_value ^ key_old);
    key_old   = key_value;

    if(key_down == 1)
    {
            num_shi++;
            if(num_shi == 24)num_shi = 0;

    }
    
    if(key_down == 2)
    {
        if(num_fen == 59)
        {
            num_fen = 0;
            num_shi++;
            if(num_shi == 24)num_shi=0;
        }
        else
            num_fen++;
    }
}



void T0_Handle_Program()
{
    if(count_miao == 20)
    {
        count_miao = 0;
        num_miao++;
        if(num_miao == 60)num_miao = 0;
    }

    
    if(count_fen0 == 1200)
    {
        count_fen0 = 0;
        num_fen++;
        if(num_fen == 60)
        {
            num_fen=0;
            num_shi++;
            if(num_shi == 24)num_shi=0;
        }
        if(count_fen1 == 72000)
        {
            num_fen=0;
        }
    }
    
    if(count_shi == 72000)
    {
        count_shi = 0;
        num_shi++;
        if(num_shi == 24)num_shi = 0;        
    }

}

void main()
{
    TMOD = 0x11;
    TH0  = (65536-46080)/256;
    TL0  = (65536-46080)%256;
    TH1  = (65536-46080)/256;
    TL1  = (65536-46080)%256;

    EA   = 1;
    ET0  = 1;
    ET1  = 1;
    TR0  = 1;
    TR1  = 1;
    
    num_shi = 12;
    while(1)
    {        
        
        shiwan = num_shi/10;
        wan        = num_shi%10;
        qian = num_fen/10;
        bai  = num_fen%10;
        shi = num_miao/10;
        ge  = num_miao%10;

        display(shiwan,wan,qian,bai,shi,ge);

    }

}


void T0_Handle() interrupt 1
{
    EA  = 0;
    TR0 = 0;
    fixtime = TL0+0x0A;
    TL0 = fixtime;
    TH0 = 0x4C+(char)CY;
    EA = 1;
    TR0 = 1;
    count_fen0++;
    count_fen1++;
    count_shi++;
    count_miao++;
    
    T0_Handle_Program();
}

void T1_Handle() interrupt 3
{
    EA  = 0;
    TR1 = 0;
    fixtime = TL1+0x0A;
    TL1 = fixtime;
    TH1 = 0x4C+(char)CY;
    EA = 1;
    TR1 = 1;
    key_handle();
    
}


 

最终效果

误差:

可以看到在调试中,1分钟内的误差为0,理论误差满足设计要求。

效果:

 

 

 

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
基于51单片机的电子时钟设计 *** 山东工商学院 264005 摘 要:本文介绍了基于51单片机的电子时钟设计,从硬件和软件两个方面给出了具体实 现过程。该时钟设计采用功能分块的思想方法,将硬件电路划分为开关电路,显示驱 动电路和数码管电路等若干独立模块,而软件的实现则由闹钟的声音程序、时间显示程 序、日期显示程序,秒表显示程序,时间调整程序、闹钟调整程序、定时调整程序,延 时程序等组成。文中给出了各个模块的电路图,并用Proteus的ISIS软件对电子时钟系统 的各个功能进行了仿真,并给出了相应的仿真结果图像。 关键词:单片机;电子时钟;键盘控制 Electronic Clock Design Based on 51 Single-chip *** Shandong Institute of Business and Technology , 264005 Abstract: This paper introduces the electronic clock design based on 51 single-chip microcomputer, and it provides us specific implementation process from aspects of hardware and software. This clock is designed by the method of function blocks. In hardware, it's circuit is divided into switch block, display drive block and digital control block. However, the software consist of the program of alarm clock, time display, date display, stopwatch display, time adjust, timing adjustment, the alarm clock adjustment, time delay and so on. Circuit diagrams of each module is also given and the corresponding simulation image of this clock produced by software of Proteus is also showed in this paper. Key words: single chip microcomputer; electronic clock; Keyboard control 1. 引言 1957年,Ventura发明了世界上第一个电子表,从而奠定了电子时钟的基础,电子时钟 开始迅速发展起来。现代的电子时钟是基于单片机的一种计时工具,采用延时程序产生 一定的时间中断,用于一秒的定义,通过计数方式进行满六十秒分钟进一,满六十分小 时进一,满二十四小时小时清零。从而达到计时的功能,是人民日常生活补课缺少的工 具。现在高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟、石英钟、石 英表都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调试,数 字式电子钟用集成电路计时时,译码代替机械式传动,用LED显示器代替指针显示进而显 示时间,减小了计时误差,这种表具有时、分、秒显示时间的功能,还可以进行时和分 的校对,片选的灵活性好。 二,时钟的基本原理分析 利用单片机定时器完成计时功能,定时器0计时中断程序每隔0.01s中断一次并当作一 个计数,设定定时1秒的中断计数初值为100,每中断一次中断计数初值减1,当减到0时 ,则表示1s到了,秒变量加1,同理再判断是否1min钟到了,再判断是否1h到了。 为了将时间在LED数码管上显示,可采用静态显示法和动态显示法,由于静态显示法 需要译码器,数据锁存器等较多硬件,可采用动态显示法实现LED显示,通过对每位数码 管的依次扫描,使对应数码管亮,同时向该数码管送对应的字码,使其显示数字。由于 数码管扫描周期很短,由于人眼的视觉暂留效应,使数码管看起来总是亮的,从而实现 了各种显示。 三,时钟设计分析 针对要实现的功能,采用AT89S51单片机进行设计,AT89S51 单片机是一款低功耗,高性能CMOS8位单片机,片内含4KB在线可编程(ISP)的可反复擦 写1000次的Flash只读程序存储器,器件采用高密度、非易失性存储技术制造,兼容标准 MCS- 51指令系统及80C51引脚结构。这样,既能做到经济合理又能实现预期的功能。 在程序方面,采用分块设计的方法,这样既减小了编程

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值