基于51单片机电子钟闹钟数码管显示12-24时制切换( proteus仿真+程序+设计报告+讲解视频)
仿真图proteus8.17(有低版本)
程序编译器:keil 4/keil 5
编程语言:C语言
设计编号:P22
1主要功能:
1、用 7 段数码管作为显示设备,设计时钟功能;
2、可以分别调校小时、分钟和秒,复位后时间为00:00:00,并可设置为24 或 12 小时格式;
3、可以有其他扩展功能。
扩展功能:
具有闹钟功能,可以通过按键设定闹钟时间,默认闹钟时间是00:01;
12/24小时制有对应的指示灯,上午下午具有指示灯显示。
主要硬件 51单片机 DS1302 数码管 独立按键 LED
(目前仅完全适配普中51-实验板234,其他普中开发板型号需要接线)
需注意仿真中51单片机芯片是兼容的,AT89C51,AT89C52是51单片机的具体型号,内核是一样的。相同的原理图里,无论stc还是at都一样,引脚功能都是一样的,程序是兼容的,芯片可以替换为STC89C52/STC89C51/AT89C52/AT89C51等51单片机芯片。
资料下载链接:
P系列单片机设计下载链接(复制到浏览器打开)
https://docs.qq.com/doc/DS2pPenNRaHB6SlR1
以下为本设计资料展示图:
2.实物图:
显示的时间是09:01:13
普中实验板上的指示灯说明
3.仿真设计
打开仿真工程,双击proteus中的单片机,选择hex文件路径,然后开始仿真。开始仿真后数码管显示时间00:00:00。时间逐秒递增。
显示时间的情况下,按下设置键进入设置模式,时钟闪烁表示当前正在设置时钟,再按下设置键进入分钟设置模式,分钟闪烁,再按下设置键进入秒钟设置模式,秒钟闪烁。设置完秒钟再按设置退出设置模式,数码管正常显示。
未进入设置状态下,按键+作为切换按键,切换显示12/24小时制。12小时制下具有灯光指示是上午还是下午,以此实现AM/PM只是。
按下功能切换按键显示闹钟时间。闹钟时间显示下按下设置键进入闹钟设置模式,时钟闪烁表示当前正在设置闹钟时钟,再按下设置键进入闹钟分钟设置模式,闹钟分钟闪烁,再按下设置键进入闹钟秒钟设置模式,闹钟秒钟闪烁。设置完秒钟再按设置退出设置模式,数码管正常显示闹钟时间。
闹钟时间到,蜂鸣器闹铃,蜂鸣器响持续6s。
4.程序代码
使用keil4或者keil5编译,代码有注释,可以结合视频理解代码含义。
#include "reg51.h" //此文件中定义了单片机的一些特殊功能寄存器#include"ds1302.h"typedef unsigned int u16; //对数据类型进行声明定义typedef unsigned char u8;sbit beep=P2^5;//蜂鸣器 sbit led_clock=P2^0;sbit led_data=P2^1;sbit led_alarm=P2^6;sbit key1=P3^0;//功能切换.时间/闹钟sbit key2=P3^1;//选择时、分、秒(按第4次确认)sbit key3=P3^2;//加sbit key4=P3^3;//减 完整代码见文章下载链接sbit smg1=P2^2; //74LS138sbit smg2=P2^3;sbit smg3=P2^4;u8 mode=0;//模式。0时间1闹钟u8 cixu=0;//设置模式。1时2分3秒u16 time=0;//计时变量,1su8 beep_flag=0,beep_flag0=0;//蜂鸣器标志u8 shi0=0,fen0=1,miao0=0;//闹钟u8 code smgduan0[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//显示0~9,无小数点u8 code smgduan1[11]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x40};//显示0~9,有小数点u8 flag=0;void delay(u16 i)//延时{while(i--);}void display1()//显示时间{ if((cixu==3)&& flag) { } else { P0=0;smg3=0;smg2=0;smg1=0;P0=smgduan0[ds1302_time[0]%10];delay(50); //当前显示是时钟 P0=0;smg3=0;smg2=0;smg1=1;P0=smgduan0[ds1302_time[0]/10];delay(50); } P0=0;smg3=0;smg2=1;smg1=0;P0=0x40;delay(50); if((cixu==2)&& flag) { } else { P0=0;smg3=0;smg2=1;smg1=1;P0=smgduan0[ds1302_time[1]%10];delay(50); //当前显示是分钟 P0=0;smg3=1;smg2=0;smg1=0;P0=smgduan0[ds1302_time[1]/10];delay(50); } P0=0;smg3=1;smg2=0;smg1=1;P0=0x40;delay(50); if((cixu==1)&& flag) { } else { P0=0;smg3=1;smg2=1;smg1=0;P0=smgduan0[ds1302_time[2]%10];delay(50); //当前显示是秒钟 P0=0;smg3=1;smg2=1;smg1=1;P0=smgduan0[ds1302_time[2]/10];delay(50); }}void display2()//显示日期{if((cixu==1)&& flag) { }else { P0=0;smg3=1;smg2=1;smg1=1;P0=smgduan0[2];delay(50); P0=0;smg3=1;smg2=1;smg1=0;P0=smgduan0[0];delay(50); P0=0;smg3=1;smg2=0;smg1=1;P0=smgduan0[ds1302_time[6]/10];delay(50);// P0=0;smg3=1;smg2=0;smg1=0;P0=smgduan1[ds1302_time[6]%10];delay(50); }if((cixu==2)&& flag) { }else { P0=0;smg3=0;smg2=1;smg1=1;P0=smgduan0[ds1302_time[4]/10];delay(50); //当前显示是月份 P0=0;smg3=0;smg2=1;smg1=0;P0=smgduan1[ds1302_time[4]%10];delay(50); }if((cixu==3)&& flag) { }else { P0=0;smg3=0;smg2=0;smg1=1;P0=smgduan0[ds1302_time[3]/10];delay(50); //当前显示是日期 P0=0;smg3=0;smg2=0;smg1=0;P0=smgduan0[ds1302_time[3]%10];delay(50); }}void display3()//显示闹钟{if((cixu==1)&& flag) { }else { P0=0;smg3=1;smg2=1;smg1=1;P0=smgduan0[shi0/10];delay(50); //当前显示是时钟 P0=0;smg3=1;smg2=1;smg1=0;P0=smgduan0[shi0%10];delay(50); }if((cixu==2)&& flag) { }else { P0=0;smg3=1;smg2=0;smg1=0;P0=smgduan0[fen0/10];delay(50); //当前显示是分钟 P0=0;smg3=0;smg2=1;smg1=1;P0=smgduan0[fen0%10];delay(50); }if((cixu==3)&& flag) { }else { P0=0;smg3=0;smg2=0;smg1=1;P0=smgduan0[miao0/10];delay(50); //当前显示是秒钟 P0=0;smg3=0;smg2=0;smg1=0;P0=smgduan0[miao0%10];delay(50); }}/******************************************************************************** 函 数 名 : Timer0Init* 函数功能 : 定时器0初始化* 输 入 : 无* 输 出 : 无*******************************************************************************/void Timer0Init(){ TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。 TH0=0Xfc; //给定时器赋初值,定时1ms TL0=0X18; ET0=1;//打开定时器0中断允许 EA=1;//打开总中断 TR0=1;//打开定时器 }/******************************************************************************** 函 数 名 : MonthDays* 函数功能 : 得到当月的天数* 输 入 : 年月日* 输 出 : 月份天数*******************************************************************************/int MonthDays(int year, int month) { //区分闰年大小月 int days; if (month == 2) { // 二月份 if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { // 闰年2月29天,其他年份28天 days = 29; } else { days = 28; } } else if (month == 4 || month == 6 || month == 9 || month == 11) { // 四、六、九、十一月份各30天 days = 30; } else { // 其他月份各31天 days = 31; } return days; } /******************************************************************************** 函 数 名 : main* 函数功能 : 主函数* 输 入 : 无* 输 出 : 无*******************************************************************************/void main(){ uchar k=0; Ds1302Init(); Timer0Init(); //定时器0初始化 beep=0; mode=0; while(1) { if(mode==0){ display1();//显示时间 led_clock=0; //对应的灯亮 led_data=1; led_alarm=1; } if(mode==1){ display2();//显示日期 led_clock=1; //对应的灯亮 led_data=0; led_alarm=1; } if(mode==2){ display3();//显示闹钟 led_clock=1; //对应的灯亮 led_data=1; led_alarm=0; } if(!key1 &&(k!=1)) //功能切换 { k=1;cixu=0; if(mode<2) mode++; else mode=0; } if(!key2 &&(k!=2))//选择 { if(cixu<3) cixu++; else cixu=0; k=2; } if(!key3 &&(k!=3)) //加 { k=3; if(mode==0)//时间 { switch(cixu) { case 1: if(ds1302_time[2]<23) ds1302_time[2]++; Ds1302Init(); break; case 2: if(ds1302_time[1]<59) ds1302_time[1]++; Ds1302Init(); break; case 3: if(ds1302_time[0]<59) ds1302_time[0]++; Ds1302Init(); } } if(mode==1)//日期 { switch(cixu) { case 1: if(ds1302_time[6]<50) ds1302_time[6]++; Ds1302Init(); break; case 2: if(ds1302_time[4]<12) ds1302_time[4]++; Ds1302Init(); break; case 3: if(ds1302_time[3]<MonthDays((ds1302_time[6]+2000),ds1302_time[4])) ds1302_time[3]++; Ds1302Init(); } } if(mode==2)//闹钟 { switch(cixu) { case 1: if(shi0<23){ shi0++; }else{ shi0=0; } break; case 2: if(fen0<59){ fen0++; }else{ fen0=0; } break; case 3: if(miao0<59){ miao0++; }else{ miao0=0; } } } } if(!key4 &&(k!=4)) //减 { k=4; if(mode==0)//时间 { switch(cixu) { case 1: if(ds1302_time[2]>0) ds1302_time[2]--; Ds1302Init(); break; case 2: if(ds1302_time[1]>0) ds1302_time[1]--; Ds1302Init(); break; case 3: if(ds1302_time[0]>0) ds1302_time[0]--; Ds1302Init(); } } if(mode==1)//日期 { switch(cixu) { case 1: if(ds1302_time[6]>0) ds1302_time[6]--; Ds1302Init(); break; case 2: if(ds1302_time[4]>0) ds1302_time[4]--; Ds1302Init(); break; case 3: if(ds1302_time[3]>0) ds1302_time[3]--; Ds1302Init(); } } if(mode==2)//闹钟 { switch(cixu) { case 1: if(shi0>0){ shi0--; }else{ shi0=23; } break; case 2: if(fen0>0){ fen0--; }else{ fen0=59; } break; case 3: if(miao0>0){ miao0--; }else{ miao0=59; } } } }// if(!key5) //停止响铃// {// beep_flag=0;// } if(key1 && key2 && key3 && key4)//按键清零 k=0; if((ds1302_time[2]==shi0)&&(ds1302_time[1]==fen0)&&(ds1302_time[0]<15))//判断响铃 { beep_flag=1; }else{ beep_flag=0; } } }
5.设计报告
6138字设计报告,内容包括硬件设计、软件设计、软硬件框图、调试、结论等
6.设计资料内容清单&&下载链接
资料设计资料包括仿真,程序代码、讲解视频、功能要求、设计报告、软硬件设计框图等。
0、常见使用问题及解决方法–必读!!!!
1、程序
2、proteus仿真
3、功能要求
4、软硬件流程图
5、开题报告
6、设计报告
7、烧录工具
8、讲解视频
9、实物图
Altium Designer 安装破解
KEIL+proteus 单片机仿真设计教程
KEIL安装破解
Proteus元器件查找
Proteus安装
Proteus简易使用教程
单片机学习资料
相关数据手册
答辩技巧
设计报告常用描述
鼠标双击打开查找嘉盛单片机51 STM32单片机课程毕业设计.url
8272