要求:
1、数字钟:时、分,小时用二十四进制显示,分钟用六十进制显示。
2、显示采用动态数码管显示方式
3、动态时显示六位:时 分 秒 用按键可切换显示年月日
4、具有清零的功能,且能够对小时、分钟进行调整(校时)。
5、具有整点、半点报时功能,整点用声音次数报时,半点特殊声音报时。
获取该 程序+protues 的方式:
1、CSDN下载:
https://download.csdn.net/download/qq_38351824/11274668
2、关注微信公众号下载:
① 关注微信公众号:Tech云
②
3、可以关注点赞并在下方评论,我给你邮箱发过去。
一、Protues仿真图:
二、程序源码:
因为注释非常的全,这里就不再进行讲解了。
/*******************************************************************************
================================================================================
【平 台】STC89C51_sumjess平台
【编 写】sumjess
【E-mail 】1371129880@qq.com
【软件版本】V2.0
【最后更新】2019年06月10日
【相关信息参考下列地址】
【网 站】
https://blog.csdn.net/qq_38351824
http://www.51hei.com/bbs/mcu-2-1.html
---------------------------------------------------------------------------------
【dev.env.】MDK4.02及以上版本
【Target 】STC89C51
第一次修订:2019/05/09
第二次修订:2019/05/21
第三次修订:2019/06/10
【problem 】
(1)库内补充的不全面;
(2)库内解释部分不全面;
(3)库内还存在一定的bug;
【direction】
下一步的目标就是把库继续集成!
【explain 】
为了方便使用,我也自己写了很多的库,和优化了算法和表示方式!
【warning】
目前程序中暂无错误 !
---------------------------------------------------------------------------------
没有完美的代码,只有不断的奉献,大家一起努力;
赠人玫瑰手留余香,欢迎大家反馈bug!
================================================================================
********************************************************************************/
#include//52单片机头文件
#include"intrins.h" //循环移位函数头文件
#define uint unsigned int // 宏定义
#define uchar unsigned char
#define NOT_Break 25 //任意赋值避开条件
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0XBF,0xff}; //共阳极数码管编码0-9和“—”
uchar val[8]={2,3,10,5,9,10,5,5};
sbit key0 = P0^0; //清零
sbit key1 = P0^1; //时间---年月日转换
sbit BEEP = P3^7; //蜂鸣器
uchar wei=0X01,duan=0;
void smg()//数码管扫描送显示函数
{
P1=wei; // 选择要点亮的数码管是哪一个
P2=table[val[duan]]; // 给改数码管送显示数据
wei=_crol_(wei,1); // 移位,为点亮下一个数码管做准备
duan++;
if(duan>7)duan=0;
}
void delay(uint z) //1毫秒
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void time0init() // 定时器0初始化函数
{
TMOD=0x01;//设置定时器0为工作方式1(M1M0为01)
TH0=(65536-2000)/256;//装初值12M晶振定时2ms数为2000
TL0=(65536-2000)%256;
EA=1;//开总中断
ET0=1;//开定时器0中断
TR0=1;//启动定时器0
}
uint num=0,keytime=0,time;//时间更新 1s,20ms扫描一次按键, 控制修改项闪烁
void time0() interrupt 1
{
TH0=(65536-2000)/256;//装初值12M晶振定时2ms数为2000
TL0=(65536-2000)%256;
keytime++;//20ms扫描一次按键
time++;//控制修改项闪烁
num++;//时间更新 1s
smg();
}
uchar key()
{
static uchar kzt=0; //推动循环,每次执行一次case
uchar sb=NOT_Break; //任意赋值避开条件
switch(kzt) //按顺序依次执行
{
//------------case 0:------------//
case 0: //第一步
P3=0xff; //P3做读入状态时,应该要先写1的,才能正确读入数据
//按照课本原文 作输入时:必须先将1写入口锁存器,使场效应管截止,该口线同时被内部上拉电阻拉成高电平,同时也能被外部输入源拉成低电平,即外部输入1时,该口线为高电平,输入0时,该口线为低电平
if(P3!=0xff) //如果有按键按下
{
kzt=1; //向下执行第二步
return NOT_Break; //返回一个无关的值,用来跳出此次循环
}
break; //如果没有按键按下,直接跳出
//------------case 1:------------//
case 1: //第二步
P3=0xff; //P3做读入状态时,应该要先写1的,才能正确读入数据
//按照课本原文 作输入时:必须先将1写入口锁存器,使场效应管截止,该口线同时被内部上拉电阻拉成高电平,同时也能被外部输入源拉成低电平,即外部输入1时,该口线为高电平,输入0时,该口线为低电平
if(P3!=0xff) //有按键按下
{
switch(P3)
{
case 0xfe: //第一个按键按下
sb=0;
break; //直接跳出
case 0xfd: //第二个按键按下
sb=1;
break; //直接跳出
case 0xfb: //第三个按键按下
sb=2;
break; //直接跳出
case 0xf7: //第四个按键按下
sb=3;
break; //直接跳出
}
kzt=2; //如果无按键按下 向下执行第三步
return sb; //返回sb的值
}
else //如果无按键按下 回到第一步
{
kzt=0;
return NOT_Break; //返回一个无关的值,用来跳出此次循环
}
break;
//------------case 2:------------//
case 2: //第三步
P3=0xff; //P3做读入状态时,应该要先写1的,才能正确读入数据
//按照课本原文 作输入时:必须先将1写入口锁存器,使场效应管截止,该口线同时被内部上拉电阻拉成高电平,同时也能被外部输入源拉成低电平,即外部输入1时,该口线为高电平,输入0时,该口线为低电平
if(P3==0xff) //如果没有按键按下
{
kzt=0; //如果无按键按下 回到第一步
return NOT_Break;
}
break; //如果有按键按下 直接跳出
}
return NOT_Break;
}
void main()
{
char shi=23,fen=59,miao=55,qh=0; //初始化时分秒 状态标志位(0:正常,1:改变秒钟,2:改变分钟,3:改变时钟)
char flag=0; //标志位---年月日&&时分秒
char keycode=NOT_Break; //键值
P0=0xff;
P1=0xff;
P2=0xff;
P3=0xff;
delay(10); //保证上面三条指令顺利完成
time0init(); //定时器0初始化函数
while(1)
{
if(key0==0) //清零按键按下
{
shi=0;fen=0;miao=0; //时分秒清零
qh=0; //开始显示
}
if(key1==0) //年月日&&时分秒按键按下
{
while(!key1); //等待放开按键
if(flag==0) flag=1; //年月日&&时分秒
else flag=0;
qh=0; //开始显示
}
if(keytime>9) //2ms*10=20ms
{
keytime=0; //计数清零
keycode=key(); //检测是否有按键按下
}
//---时间更新---//
if((num>=500)&&(qh==0)) //时间更新 2ms*500=1s
{
num=0; //计数清零
miao++; //秒数加1
if(miao>59) //如果miao等于60
{
miao=0; //miao赋值为0
fen++; //分钟加1
if(fen>59) //如果fen等于60
{
fen=0; //fen赋值为0
shi++; //小时加1
if(shi>23) shi=0;//如果shi等于24 shi赋值为0
}
}
}
///
//---按键检测---///
///---第一个按键按下---///
if(keycode==0) //第一个按键按下选择
{
qh++; //状态标志位(0:正常,1:改变秒钟,2:改变分钟,3:改变时钟)
if(qh>3) qh=1; //如果qh等于4,qh赋值为1
keycode=NOT_Break; //任意赋值避开条件
}
///---第二个按键按下---///
if(keycode==1) //第二个按键按下 加
{
if(qh==1)
{
miao++;
if(miao>59) miao=0;//如果miao等于60 miao赋值为0
}
if(qh==2)
{
fen++;
if(fen>59) fen=0; //如果fen等于60 fen赋值为0
}
if(qh==3)
{
shi++;
if(shi>23)shi=0; //如果shi等于24 shi赋值为0
}
keycode=NOT_Break; //任意赋值避开条件
}
///---第三个按键按下---///
if(keycode==2) //第三个按键按下 减
{
if(qh==1)
{
miao--;
if(miao<0) miao=59;//如果miao等于-1 miao赋值为59
}
if(qh==2)
{
fen--;
if(fen<0) fen=59; //如果fen等于-1 fen赋值为59
}
if(qh==3)
{
shi--;
if(shi<0) shi=23; //如果shi等于-1 shi赋值为23
}
keycode=NOT_Break; //任意赋值避开条件
}
///---第四个按键按下---///
if(keycode==3) //第四个按键按下 确定
{
qh=0;
keycode=NOT_Break; //任意赋值避开条件
}
///
///---显示函数---///
switch(qh) //按键按下后立即显示
{
//正常显示
case 0:
if(flag==1) //显示日期 年月日
{
val[0]=2;
val[1]=0;
val[2]=1;
val[3]=9;
val[4]=0;
val[5]=7;
val[6]=0;
val[7]=4;
}
else
{
val[0]=shi/10; //显示时间 时分秒
val[1]=shi%10;
val[2]=10;
val[3]=fen/10;
val[4]=fen%10;
if(fen==30) { BEEP=0;delay(200);BEEP=1; }
else if(fen==0) { BEEP=0;delay(100);BEEP=1;}
val[5]=10;
val[6]=miao/10;
val[7]=miao%10;
}
break;
//秒钟修改后显示 其中秒钟部分在闪烁
case 1:
if(time<250) //2ms*250=0.5s
{
val[0]=shi/10;
val[1]=shi%10;
val[3]=fen/10;
val[4]=fen%10;
val[6]=miao/10;
val[7]=miao%10;
}
else if(time<500) //2ms*500=1s
{
val[0]=shi/10;
val[1]=shi%10;
val[3]=fen/10;
val[4]=fen%10;
val[6]=11;
val[7]=11;
}
else if(time>500) //2ms*500=1s
{
time=0;
}
break;
//分钟修改后显示 其中分钟部分在闪烁
case 2:
if(time<250)
{
val[0]=shi/10;
val[1]=shi%10;
val[3]=fen/10;
val[4]=fen%10;
val[6]=miao/10;
val[7]=miao%10;
}
else if(time<500)
{
val[0]=shi/10;
val[1]=shi%10;
val[3]=11;
val[4]=11;
val[6]=miao/10;
val[7]=miao%10;
}
else if(time>500)
{
time=0;
}
break;
//时钟修改后显示 其中时钟部分在闪烁
case 3:
if(time<250)
{
val[0]=shi/10;
val[1]=shi%10;
val[3]=fen/10;
val[4]=fen%10;
val[6]=miao/10;
val[7]=miao%10;
}
else if(time<500)
{
val[0]=11;
val[1]=11;
val[3]=fen/10;
val[4]=fen%10;
val[6]=miao/10;
val[7]=miao%10;
}
else if(time>500)
{
time=0;
}
break;
}
///
}
}