您好,欢迎来到抵帆知识网。
搜索
您的当前位置:首页单片机实现多功能数字钟

单片机实现多功能数字钟

来源:抵帆知识网
以下是我的一个工程实践1的小制作,一起和大家分享

主要参考两本书来做

觉得这两本书是单片机入门的不错的书-推荐一下 《单片机典型模块设计实例导航》-人民邮电出版社 《单片机应用系统开发实例导航》-人民邮电出版社

一:电路原理和器件选择

制作电路:单片机(ATS52)实现多功能数字钟

性能指标:该数字钟实现时钟运行,调整,倒计时,秒表功能,且精确度经调试一天的误差在2S内。

实现原理:利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。

电路主要模块及原理图: 1. 数码显示硬件驱动

2.单片机最小系统:

3.LED及单片机电源原理图

4.外部控制状态输入模块原理图

主要元器件选择:

单片机:ATS52采用市场上比较常用的ATS52,这里采用ATS52而不是ATS51是为了最大限度减小误差,因为要实现多功能(例如秒表,时钟,倒计时)为了相互之间不干扰而要用到3个定时/计数器,而51系列只有2个,而52系列有3个,故采用52系列

三极管:用来进行数码管显示的位选,这里采用PNP管 数码管:采用共阳级四位数码管 晶振:采用的是11.0592MHZ的晶振

电源部分:采用5V电压供电,采用的是L7805稳压芯片供电(加滤波) 电阻:大部分时限流电阻,阻值为4.7K或10K,1K

端口分配及连接:

P0:LED数码管显示内容通过P1口从单片机传送到数码管 P2.4-P2.7:数码管位选控制端口

P2.0-P2.3:分别连接开关K0,K1,K2,K3通过不同的组合实现外部控制程序状态 P1.0:蜂鸣器,倒计时完毕产生鸣响

P1.2-P1.5:四个发光二极管,显示当前时钟状态

完整的源程序如下:

附程序源代码及注释

#include #include

#define uint unsigned int #define uchar unsigned char

/*定义P2口各管脚*/ sbit K0=P2^2; sbit K1=P2^1; sbit K2=P2^0; sbit K3=P2^3;

sbit D0=P2^4; sbit D1=P2^5; sbit D2=P2^6; sbit D3=P2^7;

/*定义P1口各管脚*/ sbit beep=P1^0; sbit L0=P1^5; sbit L1=P1^4;

sbit L2=P1^3; sbit L3=P1^2;

uchar data BUFFER[4]={0,0,0,0}; //显示缓冲区(依次从低位到高位,共四位数码管) uchar data CLOCK[4]={0,0,0,0}; //存放时钟时间(依次是百分秒,秒,分,时) uchar data SECOND[3]={0,0,0}; //存放秒表时间(依次时百分秒,秒,分)

uchar data SEVER[4]={0,0,0,0}; //存放倒计时时间(依次是百分秒,秒,分,时)

/*定义程序运行状态*/ uchar data STATE=0; /*STATE=0;时钟运行*/ /*STATE=1;时钟分调整*/

/*STATE=2;未定义状态,可添加*/ /*STATE=3;时钟时调整*/ /*STATE=4;倒计时分调整*/ /*STATE=5;倒计时时调整*/ /*STATE=6;秒表*/

/*STATE=7;倒计时运行*/

/*定义辅助计时全局变量*/ uchar m=60;

/*共阳数码管显示\"0\"-\"9\

uchar code TABLE[]={0xC0,0xf9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98,0xbf};

/*自定义子函数*/

void display(); //显示函数

void delay(); //显示延时函数

void intsvr(); //调整时间时加1子函数 void delay10ms(); //延时函数

/*主函数体*/

void main(void) {

EA=1;ET0=1; //开总中断源,开T0中断

TMOD=0x61; //T1方式2计数,T0方式1计时 TH0=-9460/256;TL0=-9460%256; //初始化计数器初值 TH1=0xff;TL1=0xff; T2CON=0;TH2=-9452/256;TL2=-9452%256;

K0=1;K1=1;K2=1; //初始化控制状态位 STATE=P2&0x07;

for(;;) {

switch(STATE) {

case 1: //时钟分调整程序 {

TR0=0;ET0=0;EX0=0;TR2=0; //关闭定时器,时钟停止运行,同时关闭外中断IT0 L3=0;L1=0;L2=0;L0=1;

intsvr(); //调用加1函数

BUFFER[0]=CLOCK[2]%10; //数码管显示分钟个位 BUFFER[1]=CLOCK[2]/10; //数码管显示分钟十位 BUFFER[2]=10; //显示\"-\" BUFFER[3]=10; //显示\"-\" }break;

case 3: //时钟时调整程序 {

TR0=0;ET0=0;EX0=0;TR2=0; //关闭定时器,时钟停止运行

L3=0;L1=0;L2=0;L0=1;

intsvr(); //调用加1函数

BUFFER[0]=CLOCK[2]%10; //数码管显示分钟个位 BUFFER[1]=CLOCK[2]/10; //数码管显示分钟十位 BUFFER[2]=CLOCK[3]%10; //数码管显示时钟个位 BUFFER[3]=CLOCK[3]/10; //数码管显示时钟十位 }break;

case 4: //倒计时分钟调整程序 {

TR0=1;ET0=1;EX0=0;TR2=0; //保持T0正常运行,即时钟正常运行,同时关闭外中断IT0 L3=0;L2=0;L1=0;

intsvr(); //调用加1函数 BUFFER[0]=SEVER[2]%10; //数码管显示分钟个位 BUFFER[1]=SEVER[2]/10; //数码管显示分钟十位 BUFFER[2]=10; //显示\"-\" BUFFER[3]=10; //显示\"-\"

SECOND[1]=0; //秒表初始化为0 SECOND[2]=0; }break;

case 5: //倒计时时钟调整程序 {

TR0=1;ET0=1;EX0=0;TR2=0; //保持T0正常运行,即时钟正常运行,同时关闭外中断IT0 L3=0;L2=0;L1=0;

intsvr(); //调用加1子函数 BUFFER[0]=SEVER[2]%10; //数码管显示分钟个位 BUFFER[1]=SEVER[2]/10; //数码管显示分钟十位 BUFFER[2]=SEVER[3]%10; //数码管显示时钟个位 BUFFER[3]=SEVER[3]/10; //数码管显示时钟十位

SECOND[1]=0; //秒表初始化为0 SECOND[2]=0; }break;

case 6: {

TR0=1;ET0=1;EX0=1;ET2=1;//保持T0正常运行,即时钟正常运行,同时开外中断IT0

BUFFER[0]=SECOND[1]%10; //数码管显示秒表秒个位 BUFFER[1]=SECOND[1]/10; //数码管显示秒表秒十位 BUFFER[2]=SECOND[2]%10; //数码管显示秒表分个位 BUFFER[3]=SECOND[2]/10; //数码管显示秒表分十位 }break;

case 7: { TR0=1;ET0=1;EX0=0;ET2=1; //倒计时运行,同时时钟也正常运行,关闭外中断T0 if((SEVER[2]==0)&&(SEVER[3]==0)) //当预置时间(分,时)变为0时,计时完毕 {

beep=!beep; //蜂鸣器响 BUFFER[0]=10; //显示\"-\" BUFFER[1]=10; BUFFER[2]=10; BUFFER[3]=10;

TR2=0; //关闭T2 } else {

TR2=1; //开启T2 }

SECOND[1]=0; //秒表时间初始化 SECOND[2]=0; }break;

default: {

ET0=1;TR0=1;EX0=0; //开启T0,时钟运行,关闭外中断 L1=1;L3=1;L2=1;

BUFFER[0]=CLOCK[2]%10; // BUFFER[1]=CLOCK[2]/10; // BUFFER[2]=CLOCK[3]%10; // BUFFER[3]=CLOCK[3]/10; // } }

K0=1;K1=1;K2=1; // display(); // STATE=P2&0x07; // } }

/*T0中断服务*/

void time0(void) interrupt 1 using 1 //T0{

TH0=-9460/256; // TL0=-9460%256;

CLOCK[0]=CLOCK[0]+1; // if(CLOCK[0]==50) //0.5 {

L0=!L0; //L0数码管显示分钟个位 数码管显示分钟十位 数码管显示时钟个位 数码管显示时钟十位 重新预置状态位 调用显示函数

通过P2口提取当前状态 中断函数 计时器放入预置时间,大概10毫秒一次中断加1 秒到 取反

}

if(CLOCK[0]==100) //1秒到 {

L0=!L0; //L0取反 CLOCK[0]=0; //百分位清0 CLOCK[1]=CLOCK[1]+1; //秒位加1 if(CLOCK[1]==60) //1分钟到 {

CLOCK[1]=0; // CLOCK[2]=CLOCK[2]+1; // if(CLOCK[2]==60) //1 {

CLOCK[2]=0; // CLOCK[3]=CLOCK[3]+1; // if(CLOCK[3]==24) //24 {

CLOCK[3]=0; // } } } } }

/*外中断IT0中断服务子函数*/

void intsrl(void) interrupt 0 using 1 //{

TR2=1; // if((K3==0)&&(SECOND[1]>=3)) //K3 {

TR2=0;ET2=0; //秒位清0 分位加1 小时到 分位清0 时位加1 小时到 时位清0 外中断IT0中断请求 开定时器T2

再按下时且计时大过3时关闭T2

} }

/*定时器T2中断服务子函数*/

void time1(void) interrupt 5 using 3 //定时器T2中断请求 {

TF2=0;

TH2=-9452/256; // TL2=-9452%256;

if(STATE==6) // {

SECOND[0]=SECOND[0]+1; // if(SECOND[0]==100) //1 {

SECOND[0]=0; // SECOND[1]=SECOND[1]+1; // if(SECOND[1]==60) // {

SECOND[1]=0; // SECOND[2]=SECOND[2]+1; // if(SECOND[2]==60) // {

SECOND[2]=0; // } } } }

if(STATE==7) //放入预置数 秒表 中断一次大概10ms 秒到 百分秒位清0 秒位加1 一分钟到 秒位清0 分位加1 一小时到 时位清0 倒计时

{

if(SEVER[3]==0) //小时位为0 {

if(SEVER[2]==0) //分钟位为0 {

TR2=0; //关闭定时器T2 } else {

SEVER[0]=SEVER[0]+1; // if(SEVER[0]==50) //0.5 {

L1=!L1; //L1 }

if(SEVER[0]==100) //1 {

L1=!L1; //L1 SEVER[0]=0; // SEVER[1]=--m; // if(SEVER[1]==0) // {

m=60; // SEVER[2]=SEVER[2]-1; // } }

BUFFER[0]=SEVER[1]%10; // BUFFER[1]=SEVER[1]/10; // BUFFER[2]=(SEVER[2]-1)%10; // BUFFER[3]=(SEVER[2]-1)/10; // } }

百分秒位加1 秒到 取反 秒到 取反

百分秒位清0 秒位为59 秒位为0 秒位初始化为60 分位减1 数码管显示秒钟个位 数码管显示秒钟十位 数码管显示分钟个位 数码管显示分钟十位

else {

if(SEVER[2]==0) //分钟变为0时 {

SEVER[0]=0; //百分秒清0 SEVER[1]=60; //秒位预置60 SEVER[2]=60; //分位预置60 SEVER[3]=SEVER[3]-1; // } else {

SEVER[0]=SEVER[0]+1; // if(SEVER[0]==50) // {

L1=!L1; //L1 }

if(SEVER[0]==100) //1 {

L1=!L1; //L1 SEVER[0]=0; // SEVER[1]=SEVER[1]+1; // if(SEVER[1]==60) // {

SEVER[1]=0; // SEVER[2]=SEVER[2]-1; // } }

BUFFER[0]=(SEVER[2]-1)%10; // BUFFER[1]=(SEVER[2]-1)/10; // BUFFER[2]=SEVER[3]%10; // BUFFER[3]=SEVER[3]/10; //时位减1 百分秒加1 到0.5秒时 取反 秒到时 取反 百分秒清0 秒位加1 一分钟到 秒位清0 分位减1 数码管显示分钟个位 数码管显示分钟十位 数码管显示时钟个位 数码管显示时钟十位

} } } }

/*加1子函数 */

void intsvr(void) {

switch(STATE) // {

case 1: // {

if(K3==0) // {

delay10ms(); // if(K3==0) {

CLOCK[2]=CLOCK[2]+1; // if(CLOCK[2]==60) // {

CLOCK[2]=0; // } }

while(K3==0); }

}break;

case 3: // {

if(K3==0) //判断当前状态 时钟分调整时 当建按下时 延时,消除按键抖动分位加1 到60时 分位清0 时钟时调整 当键按下时

{

delay10ms(); //延时,消除按键抖动 if(K3==0) {

CLOCK[3]=CLOCK[3]+1; //时位加1 if(CLOCK[3]==24) //24小时到 {

CLOCK[3]=0; // } }

while(K3==0); } }break;

case 4: // {

if(K3==0) // {

delay10ms(); // if(K3==0) {

SEVER[2]=SEVER[2]+1; // if(SEVER[2]==60) // {

SEVER[2]=0; // } }

while(K3==0); } }break;

时位清0 倒计时分调整 当键按下时 延时,消除按键抖动 倒计时分钟加1 到60时 清0 case 5: //倒计时时调整 {

if(K3==0) //当键按下时 {

delay10ms(); //延时,消除按键抖动 if(K3==0) {

SEVER[3]=SEVER[3]+1; //时位加1 if(SEVER[3]==24) //到24时 {

SEVER[3]=0; //时位清0 } }

while(K3==0); } }break; } }

/*数码管动态显示函数*/

void display(void) //动态显示函数 {

uchar disp; //定义数码管的显示位

D0=1; //关D0 D1=1; //关D1 D2=1; //关D2 D3=0; //开D3 disp=BUFFER[0];

P0=TABLE[disp]; //输入要显示数据

delay(); //显示延时函数

D0=1; //关D0 D1=1; //关D1 D2=0; //开D2 D3=1; //关D3 disp=BUFFER[1];

P0=TABLE[disp]; // delay(); //

D0=1; // D1=0; // D2=1; // D3=1; // disp=BUFFER[2];

P0=TABLE[disp]; // delay(); //

D0=0; // D1=1; // D2=1; // D3=1; // disp=BUFFER[3];

P0=TABLE[disp]; // delay(); //}

/*延时函数*/

void delay(void) {

输入要显示的数据 显示延时函数 关D0 开D1 关D2 关D2 输入要显示的数据 显示延时函数 开D0 关D1 关D2 关D3 输入要显示数据 显示延时函数 uchar k;

for(k=0;k<=200;k++); }

void delay10ms(void) {

uchar j,i;

for(j=0;j<=10;j++) for(i=0;i<=200;i++); }

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- dfix.cn 版权所有 湘ICP备2024080961号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务