如何简单用单片机设计数字时钟

2025-10-27 14:07:35

1、      撰写硬件设计方案,利用单片机AT89C51为核心设计的数字时钟是可以正常显示年、月、日、时、分、秒、星期并兼具有实现计时、校时等功能。它的构成模块主要由显示模块,输入模块,控制器模块三部分。其中控制模块的设计思路是采用STC89C52RC单片机STC89C52RC单片机是宏晶科技推出的新一代高速/低功耗/超强抗干扰的单片机,指令代码完全兼容传统8051单片机,12时钟/机器周期和6时钟/机器周期可以任意选择。共有3个16位的定时/计数器,用户应用程序空间为8K字节,片上集成512字节RAM。

       计时模块的设计思路是采用时钟芯片DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。

       显示模块的设计思路是采用LCD1602LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。不同厂家生产的LCD1602芯片可能有所不同,但使用方法都是一样的。为了降低成本,绝大多数制造商都直接将裸片做到板子上。 

2、利用Proteus绘制硬件原理图。

如何简单用单片机设计数字时钟

3、利用Keilc编写软件程序

主程序部分展示

#include<reg51.h>

#include"lcd.h"

#include"ds1302.h"

sbit K1=P2^0;

sbit K2=P2^1;

sbit K3=P2^2;

sbit K4=P2^3;

void Int0Configuration();

void LcdDisplay();

unsigned char SetState,SetPlace;

void Delay10ms(void);   //误差 0us

void Timer0Init();

void key_proy();

void LcdDisplay();

/*******************************************************************************

* 函数名         : main

* 函数功能    : 主函数

* 输入           : 无

* 输出          : 无

*******************************************************************************/

void main()

{

LcdInit();

Ds1302Init();

Timer0Init();  //定时器0初始化

while(1)

{

if(SetState==0)

{

Ds1302ReadTime();             //读取DS1302寄存器中值

}

else

{

  key_proy();                   //读取DS1302寄存器中值

}

LcdDisplay();                  //显示LCD函数

}

}

void key_proy()

{

    unsigned char i;

if(K1==0) //检测按键K1是否按下

{

Delay10ms(); //消除抖动

if(K1==0)

{

SetPlace++;              //

if(SetPlace>=7)

SetPlace=0;

}

while((i<50)&&(K1==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

if(K2==0) //检测按键K2是否按下

{

Delay10ms(); //消除抖动

if(K2==0)

{

TIME[SetPlace]++;

if((TIME[SetPlace]&0x0f)>9) //换成BCD码。

{

TIME[SetPlace]=TIME[SetPlace]+6;

}

if((TIME[SetPlace]>=0x60)&&(SetPlace<2)) //分秒只能到59

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x24)&&(SetPlace==2)) //小时只能到23

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x32)&&(SetPlace==3)) //日只能到31

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x13)&&(SetPlace==4)) //月只能到12

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x7)&&(SetPlace==5)) //周只能到7

{

TIME[SetPlace]=1;

}  

}

while((i<50)&&(K2==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

if(K3==0) //检测按键K3是否按下

{

Delay10ms(); //消除抖动

if(K3==0)

{

TIME[SetPlace]--;

if((TIME[SetPlace]&0x0f)>9) //换成BCD码。

{

TIME[SetPlace]=TIME[SetPlace]+6;

}

if((TIME[SetPlace]>=0x60)&&(SetPlace<2)) //分秒只能到59

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x24)&&(SetPlace==2)) //小时只能到23

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x32)&&(SetPlace==3)) //日只能到31

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x13)&&(SetPlace==4)) //月只能到12

{

TIME[SetPlace]=0;

}

if((TIME[SetPlace]>=0x7)&&(SetPlace==5)) //周只能到7

{

TIME[SetPlace]=1;

}  

}

while((i<50)&&(K3==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

     if(K4==0) //检测按键K4是否按下

{

      Delay10ms(); //消除抖动

if(K4==0)

{

  SetState=~SetState;

  SetPlace=0;

      Ds1302Init();

}

while((i<50)&&(K4==0)) //检测按键是否松开

{

Delay10ms();

i++;

}

i=0;

}

}

/*******************************************************************************

* 函 数 名         : Timer0Init

* 函数功能    : 定时器0初始化

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void Timer0Init()

{

TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

TH0=0XFC; //给定时器赋初值,定时1ms

TL0=0X18;

ET0=1;//打开定时器0中断允许

EA=1;//打开总中断

TR0=1;//打开定时器

}

/*******************************************************************************

* 函数名         : LcdDisplay()

* 函数功能    : 显示函数

* 输入           : 无

* 输出          : 无

*******************************************************************************/

void LcdDisplay()

{

LcdWriteCom(0x80+0X40);

LcdWriteData('0'+TIME[2]/16); //时

LcdWriteData('0'+(TIME[2]&0x0f));  

LcdWriteData('-');

LcdWriteData('0'+TIME[1]/16); //分

LcdWriteData('0'+(TIME[1]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[0]/16); //秒

LcdWriteData('0'+(TIME[0]&0x0f));

LcdWriteCom(0x80);

LcdWriteData('2');

LcdWriteData('0');

LcdWriteData('0'+TIME[6]/16); //年

LcdWriteData('0'+(TIME[6]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[4]/16); //月

LcdWriteData('0'+(TIME[4]&0x0f));

LcdWriteData('-');

LcdWriteData('0'+TIME[3]/16); //日

LcdWriteData('0'+(TIME[3]&0x0f));

LcdWriteCom(0x8D);

LcdWriteData('0'+(TIME[5]&0x07)); //星期  

}

 

/*******************************************************************************

* 函数名         : Delay10ms

* 函数功能    : 延时函数,延时10ms

* 输入           : 无

* 输出          : 无

*******************************************************************************/

void Delay10ms(void)   //误差 0us

{

    unsigned char a,b,c;

    for(c=1;c>0;c--)

        for(b=38;b>0;b--)

            for(a=130;a>0;a--);

}

/*******************************************************************************

* 函 数 名         : void Timer0() interrupt 1

* 函数功能    : 定时器0中断函数

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void Timer0() interrupt 1

{

static unsigned int count;

TH0=0XFC; //给定时器赋初值,定时1ms

TL0=0X18;

count++;

if(count==10)

{

count=0;

  key_proy();

  }

}

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢