要求:
1、数字钟:时、分,小时用二十四进制显示,分钟用六十进制显示。
2、显示采用动态数码管显示方式
3、动态时显示六位:时 分 秒 用按键可切换显示年月日
4、具有清零的功能,且能够对小时、分钟进行调整(校时)。
5、具有整点、半点报时功能,整点用声音次数报时,半点特殊声音报时。
一、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 #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)
上一篇:课程设计题四:LED彩灯控制器设计
下一篇:课程设计题二:7人多数表决器
推荐阅读最新更新时间:2024-10-09 20:06
设计资源 培训 开发板 精华推荐
- LT1952MPGN-1 36V 至 72V 输入、12V/20A 半稳压总线转换器的典型应用电路
- AM6TW-2409SH35Z 9V 6瓦单输出DC-DC转换器的典型应用
- LT6656AIS6-1.25、1.25V 低功率 ADC 电压基准的典型应用
- 2022合肥地铁线网图
- TWR-S08LL64、MC9S08LL 基于 MC9S08LL64 MCU 的 8 位段式 LCD 塔式系统模块
- AM1D-2409D-RZ ±9V 1 瓦 DC-DC 转换器的典型应用
- LT3971-5、5V 降压转换器的典型应用电路
- 使用带有特殊驱动器的 IGBT 模块降低过冲电压
- 基于Esp32-S的3按键屏幕
- LT1076CT7 抽头电感降压转换器的典型应用