51单片机万年历课程设计报告

时间:2024.4.13

一、设计任务:

1、设计任务:设计并制作一个数字钟。

2、设计要求:

? 显示年月日时分秒及星期信息

? 具有可调整日期和时间功能

? 增加闰年计算功能

? 显示部分由LCD1602完成

二、方案论证:

1.显示部分:

显示部分是本次设计的重要部分,一般有以下两种方案:

方案一:

采用LED显示,分静态显示和动态显示。对于静态显示方式,所需的译码驱动装置很多,引线多而复杂,且可靠性也较低。而对于动态显示方式,虽可以避免静态显示的问题,但设计上如果处理不当,易造成亮度低,有闪烁等问题。 方案二:

采用LCD显示。LCD液晶显示具有丰富多样性、灵活性、电路简单、易于控制而且功耗小等优点,对于信息量多的系统,是比较适合的。

鉴于上述原因,我们采用方案二。

2.数字时钟:

数字时钟是本设计的核心的部分。根据需要可采用以下两种方案实现: 方案一:

方案完全用软件实现数字时钟。原理为:在单片机内部存储器设三个字节分

1 / 15

别存放时钟的时、分、秒信息。利用定时器与软件结合实现1秒定时中断,每产生一次中断,存储器内相应的秒值加1;若秒值达到60,则将其清零,并将相应的分字节值加1;若分值达到60,则清零分字节,并将时字节值加1;若时值达到24,则将时字节清零。该方案具有硬件电路简单的特点,但当单片机不上电,程序将不执行。而且由于每次执行程序时,定时器都要重新赋初值,所以该时钟精度不高。

方案二:

方案采用Dallas公司的专用时钟芯片DS1302。该芯片内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。当电网电压不足或突然掉电时,可使系统自动转换到内部锂电池供电系统。而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随时提供正确的时间。

基于时钟芯片的上述优点,本设计采用方案二完成数字时钟的功能。

三、总体方案:

本设计采用STC89C52RC单片机作为本系统的控制模块。单片机可把由DS1302、LCD液晶显示模块中的数据利用软件来进行处理,从而把数据传输到显示模块,实现日历和修改的显示。以LCD液晶显示器为显示模块,把单片机传来的数据显示出来,并且显示多样化。在显示电路中,主要靠按键来实现日期的修改和选择。

四、系统硬件设计:

2 / 15

1. STC89C52RC单片机最小系统:

最小系统包括晶体振荡电路、复位开关和电源部分。图1为STC89C52RC单片机的最小系统。

图1单片机最小系统

2.时钟模块:

时钟模块采用DS1302芯片,DS1302是DALLAS公司推出的涓流充电时钟芯片内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作可通过AM/PM指示决定采用24或12小时格式DS1302与单片机之间能简单地采用同步串行的方式进行通信仅需用到三个口线:

RST复位、I/O数据线、SCLK串行时钟。时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信。DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW,其接线电路如图2所示:

51单片机万年历课程设计报告

51单片机万年历课程设计报告

3 / 15

图2时钟模块

3. LCD液晶显示模块:

LCD液晶显示模块采用LCD1602型号,具有很低的功耗,正常工作时电流仅2.0mA/5.0V。通过编程实现自动关闭屏幕能够更有效的降低功耗。LCD1602分两行显示,每行可显示多达16个字符。LCD1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,通过内部指令可实现对其显示多样的控制,并且还能利用空余的空间自定义字符。其接线如图3所示:

图3LCD液晶显示

五、整体电路:

1.电路如下图:

51单片机万年历课程设计报告

4 / 15

图4 整体电路

2.Altium Designer布线图

图5 Altium Designer布线图

3.手动布线PCB图

51单片机万年历课程设计报告

51单片机万年历课程设计报告

5 / 15

图6PCB图

六、数字时钟使用说明:

1) 调整时间设定:在时间显示界面中按K1键后,进入时间调整,选择需要修改的或设定的时间。按K2键对应内容加1, K3键减1,K4键确定时间设定并退出设置。

2) 调整屏幕显示/背光亮度:调整左上方的蓝色变阻器可调整LCD显示灰度LCD背光亮度。

3) 复位键(K5):按下该键系统复位,系统从头开始执行程序。如遇故障可按下该键进行系统复位。复位不会造成时间、生日和闹铃等信息的丢失。

七、心得体会:

1.将理论教学与实践相结合,使我对于单片机的实际应用有了较深刻的认识。

51单片机万年历课程设计报告

6 / 15

2.让我熟悉电子系统设计的全过程,提高了我对设计课题的分析能力、编程能力及解决实际问题的综合能力。

3.对于Protues软件有了更加深入的了解,仿真这方面有很大的缺点,程序时序不对软件直接忽略了,因此在这方面花了好多时间进行调试。

同时在与老师和同学的交流过程中,互动学习,将知识融会贯通。通过自己的努力,做出了一个万年历,对以后的学习是一个莫大的鼓舞,激起了我的学习兴趣和开发创新思维。

八、程序及解释:

#include <reg52.h>

#include <intrins.h>

#include <string.h>

7 / 15

#define uint unsigned int

#define uchar unsigned char

unsigned char code displaywelcome[]={" Welcome To My Lcd Timer"};//欢迎界面 unsigned char code displaywish[]={"通信102闭光俭"}; //欢迎界面

sbit IO= P2^3; //DS1302数据线

//DS130时钟线 sbit SCLK = P2^4;

sbit RST = P2^5; //DS1302复位线

sbit RS = P2^0;

sbit RW = P2^1;

sbit EN = P2^2;

sbit K1=P3^4;

sbit K2=P3^5;

sbit K3=P3^6;

sbit K4=P3^7;

uchartCount=0;

ucharMonthsDays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};

uchar *WEEK[]={"SUN","MON","TUS","WEN","THU","FRI","SAT"};

uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00 "}; //显示格式

uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};

ucharDateTime[7]; //所读取的日期时间 //LCD数据/命令选择端 //LCD读/写控制 //LCD使能端 //选择 //加 //减 //确定

char Adjust_Index=-1; //当前调节的时间对象:,,分,是,日,月,年(1,2,3,4,6) ucharChange_Flag[]= "-MHDM-Y"; //(分,时,日,月,年)(不调节秒与周)

8 / 15

void DelayMS(uintms) //延时程序

{ uchari;

while(ms--){for(i=0;i<120;i++);}}

void Write_A_Byte_TO_DS1302(uchar x)//向DS1302写入一字节 {

uchari; SCLK=0; for(i=0;i<8;i++){ IO=x&0x01; //每一位与1与存入IO中 SCLK=1;SCLK=0; //一个高脉冲将数据送入液晶控制器 }} x>>=1; // 右移

uchar Get_A_Byte_FROM_DS1302()//从DS1302读取一字节 {

uchari,b=0x00; for(i=0;i<8;i++){ b |= _crol_((uchar)IO,i); SCLK=1;SCLK=0; //每一个高脉冲读取一位数据 } return b/16*10+b%16; //返回BCD码}

ucharRead_Data(ucharaddr)//从DS1302指定位置读数据

{ uchardat;

RST = 0;SCLK=0;RST=1; //RST高电平时读/写 Write_A_Byte_TO_DS1302(addr); //先写入地址 dat = Get_A_Byte_FROM_DS1302(); SCLK=1;RST=0; return dat;}

void Write_DS1302(ucharaddr,uchardat)//向DS1302某地址写入数据

9 / 15

{ RST=0;SCLK=0;RST=1;

Write_A_Byte_TO_DS1302(addr); Write_A_Byte_TO_DS1302(dat); SCLK=1;RST=0; //高脉冲写入数据}

void SET_DS1302()//设置时间

{

uchari; //写控制字,取消写保护 Write_DS1302(0x8E,0x00); for(i=1;i<7;i++) { //分时日月年依次写入 Write_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));//分的起始地址

} 10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递增2

Write_DS1302(0x8E,0x80); //加保护}

void GetTime()//读取当前日期时间

{uchari;

for(i=0;i<7;i++){ DateTime[i]=Read_Data(0X81+2*i);}}

ucharRead_LCD_State()//读LCD状态

{

uchar state; RS=0;RW=1;EN=1; DelayMS(1); state=P0; //输出:D0~D7=状态字 //从P0口读LCD状态 EN = 0;DelayMS(1); return state;}

void LCD_Busy_Wait()//忙等待

{ while((Read_LCD_State()&0x80)==0x80);

void Write_LCD_Data(uchardat)//向LCD写数据

{ LCD_Busy_Wait(); RS=1;EN=0;RW=0;

10 / 15

DelayMS(5);} //写数据,EN为高脉冲,

P0=dat;EN=1;DelayMS(1);EN=0; }

void Write_LCD_Command(ucharcmd)//写LCD指令

{ LCD_Busy_Wait();

P0=cmd;EN=1;DelayMS(1);EN=0; } RS=0;EN=0; RW=0; //写指令,EN高脉冲,输出:D0~D7=数

void Init_LCD()//LCD初始化

{

Write_LCD_Command(0x38); //设置16*2显示,5*7点阵,8位数据接口 DelayMS(1); DelayMS(1); DelayMS(1); DelayMS(1); } Write_LCD_Command(0x01); //显示清零,数据指针清零 Write_LCD_Command(0x06); //写一个字符后地址指针自动加1 Write_LCD_Command(0x0c); //设置开显示,不显示光标

void Set_LCD_POS(uchar p)//设置液晶显示位置

{ Write_LCD_Command(p|0x80);//相当于在0x80基础上加入位置量 } void displaystar(void) //显示欢迎界面

{

unsigned char i,j; Set_LCD_POS(0x0f); while(displaywelcome[i]!='\0') { Write_LCD_Data(displaywelcome[i]); i++; DelayMS(1);} i=0; Set_LCD_POS(0x4f); while(displaywish[i]!='\0') { Write_LCD_Data(displaywish[i]);

while(j--)

11 / 15 i++; DelayMS(1);} j=40;

{ Write_LCD_Command(0x18);//循环左移 DelayMS(200);}

Write_LCD_Command(0x01); DelayMS(1);}

void Display_LCD_String(ucharp,uchar *s)//----在LCD上显示字符串---------//

{

uchari; Set_LCD_POS(p); for(i=0;i<16;i++) {Write_LCD_Data(s[i]); //在固定位置显示时间日期 DelayMS(1);}} void Format_DateTime(uchard,uchar *a)//日期与时间值转换为数字字符

{ a[0]=d/10+'0';a[1]=d%10+'0';}

ucharisLeapYear(uint y)//判断是否为闰年

{ return (y%4==0&&y%100!=0)||(y%400==0);}

//求自2000.1.1开始的任何一天是星期几

//函数没有通过,求出总天数后再求星期几

//因为求总天数可能会超出uint的范围

voidRefreshWeekDay()

{

uinti,d,w=5; //已知1999.12.31是周五 for(i=2000;i<2000+DateTime[6];i++) { d=isLeapYear(i)?366:365; w=(w+d)%7;} d=0; } d+=DateTime[3]; for(i=1;i<DateTime[4];i++) { d+=MonthsDays[i];

//保存星期,0~6表示星期日,星期一,二,...,六,为了与DS1302的星期格式匹配,返回值需要加1

DateTime[5]=(w+d)%7+1;}

void DateTime_Adjust(char x)//年月日时分++/--

12 / 15

{

{ switch(Adjust_Index) case 6: //年00-99 if(x==1&&DateTime[6]<99) DateTime[6]++; if(x==-1&&DateTime[6]>0) DateTime[6]--; MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28;//获取2月天数 //如果年份变化后当前月份的天数大于上限则设为上限// if(DateTime[3]>MonthsDays[DateTime[4]]) { DateTime[3]=MonthsDays[DateTime[4]];} break; RefreshWeekDay(); //刷新星期 case 4: //月01-12if(x==1&&DateTime[4]<12) DateTime[4]++;} { if(DateTime[4]>12) DateTime[4]=0;

if(x==-1&&DateTime[4]>1) DateTime[4]--; if(DateTime[4]<0) DateTime[4]=12;

{ MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28; if(DateTime[3]>MonthsDays[DateTime[4]]) RefreshWeekDay(); break; DateTime[3]=MonthsDays[DateTime[4]];} case 3: //日00-28、29、30、31,调节之前首先根据年份得出该年中断二月天数 MonthsDays[2]=isLeapYear(2000+DateTime[6])?29:28; //根据当前月份决定调节日期的上限 if(x==1&&DateTime[3]<MonthsDays[DateTime[4]]) DateTime[3]++; if(x==-1&&DateTime[3]>0) DateTime[3]--; RefreshWeekDay(); break; case 2: //时 if(x==1&&DateTime[2]<23) DateTime[2]++;

13 / 15

if(x==-1&&DateTime[2]>0) DateTime[2]--; //分 break; case 1: if(x==1&&DateTime[1]<59) DateTime[1]++; if(x==-1&&DateTime[1]>0) DateTime[1]--; break;}} void T0_INT() interrupt 1//定时器0每秒刷新LCD显示

{

TH0=-50000/256; TL0=-50000%256; //按指定格式生成待显示的日期时间串// Format_DateTime(DateTime[6],LCD_DSY_BUFFER1+5); Format_DateTime(DateTime[4],LCD_DSY_BUFFER1+8); Format_DateTime(DateTime[3],LCD_DSY_BUFFER1+11); strcpy(LCD_DSY_BUFFER1+13,WEEK[DateTime[5]-1]);//星期 Format_DateTime(DateTime[2],LCD_DSY_BUFFER2+5);//时分秒 Format_DateTime(DateTime[1],LCD_DSY_BUFFER2+8); Format_DateTime(DateTime[0],LCD_DSY_BUFFER2+11); Display_LCD_String(0x00,LCD_DSY_BUFFER1);//显示年月日,星期,时分秒 Display_LCD_String(0x40,LCD_DSY_BUFFER2);} if(++tCount !=2) return; tCount=0;

void EX_INT0() interrupt 0//键盘中断(INT0)

{

{ { if(K1==0) //选择调整对象(Y M D H M) if(K1==0){ DelayMS(10); while(K1==0); Adjust_Index=7;} Adjust_Index--; if(Adjust_Index==-1||Adjust_Index==1) if(Adjust_Index==5) Adjust_Index=4;

14 / 15

LCD_DSY_BUFFER2[13]='['; LCD_DSY_BUFFER2[14]=Change_Flag[Adjust_Index]; //显示调节对象 LCD_DSY_BUFFER2[15]=']';}} //加 if(K2==0) DateTime_Adjust(1);} else if(K2==0) { while(K2==0); DelayMS(10); //减 else if(K3==0) { DelayMS(10);//while(K3==0); //确定 if(K3==0) DateTime_Adjust(-1);} else if(K4==0) { while(K4==0); DelayMS(10); if(K4==0){ SET_DS1302(); //将调整后的时间写入DS1302 LCD_DSY_BUFFER2[14]=' '; Adjust_Index=-1;}}} LCD_DSY_BUFFER2[13]=' '; LCD_DSY_BUFFER2[15]=' ';

void main()

{

Init_LCD(); //液晶初始化 displaystar( ); IE=0x83; //允许INT0,T0中断,EA=1,,ET0=1,EX0=1 IP=0x01; //设置外部中断0为高级中断 IT0=0x01; //外部中断0为电平触发,低电平有效 TMOD=0x01; //设置定时器T0工作方式为方式1, TH0=-50000/256; TR0=1; while(1) //装入初始值,定时1秒 TL0=-50000%256; //启动定时器 GetTime();

{if(Adjust_Index==-1) GetTime();//如果未执行调整操作则正常读取当前时间 }}

15 / 15

更多相关推荐:
基于51单片机课程设计报告

课题:基于51单片机的数字温度计设计专业:电气工程及其自动化班级:4学号:***设计日期:20XX/6/3成绩:重庆大学城市科技学院电气学院基于51单片机数字温度计设计报告一、设计目的作用本设计是一款简单实用的…

51单片机课程设计实验报告

51单片机课程设计报告学院:专业班级:姓名:指导教师:设计时间:51单片机课程设计一、设计任务与要求1.任务:制作并调试51单片机学习板2.要求:(1)了解并能识别学习板上的各种元器件,会读元器件标示;(2)会…

51单片机电子时钟课程设计报告

JINGCHUUNIVERSITYOFTECHNOLOGY单片机原理及应用课程设计报告题目电子时钟专业电气工程及其自动化班级20xx级电工2班学号20xx401020xx2姓名王贞指导教师邹云峰提交日期20xx...

51单片机课程设计报告

重庆科技学院学生实习实训总结报告学院电气与信息工程学院专业班级XXXXXX学生姓名XXX学号20xxXXXXXX实习实训地点逸夫科技楼I512报告题目单片机万年历系统设报告报告日期20xx年9月13日指导教师评...

51单片机课程设计报告。

成绩单片机原理及应用课程设计课程名ltlt单片机原理及应用gtgt学部专业学号姓名指导教师日期20xx年06月一设计任务与要求1任务制作并调试51单片机学习板2要求1了解并能识别学习板上的各种元器件会读元器件标...

51单片机课程设计实例

51单片机实做课课程设计报告51单片机设计实例二总原理图及元器件清单21总原理图151单片机实做课课程设计报告22显示部分23声音部分251单片机实做课课程设计报告24按键部分25继电器351单片机实做课课程设...

郭琛的51单片机课程设计报告

51单片机课程设计报告专业班级通信1001姓名指导教师徐敏设计时间20xx613目录1设计任务及要求2总原理图及元器件清单3设计思路4软硬件调试5实验心得51单片机课程设计一设计任务与要求1任务制作并调试51单...

单片机课程设计报告(系统设计部分)

自动化学院网络工程系网络信息08级班单片机课程设计报告指导教师何小敏李传芳姓名学号系统设计部分四单片机应用系统设计数字电子时钟1系统功能介绍该设计以51单片机为核心附加了必要的外围电路构成了一个简单的数字电子钟...

《单片机原理及应用》课程设计报告

吉林建筑工程学院电气与电子信息工程学院单片机原理及应用课程设计报告设计题目电子计时器综合系统设计专业班级电子信息科学与技术092学生姓名学号指导教师设计时间20xx82720xx97目录第1章绪论111课程设计...

(模板)51单片机课程结课设计报告

单片机技术课程结课设计报告题目电子时钟专业班级学号姓名指导教师张琦单片机技术课程结课设计报告第一部分设计任务和要求11设计内容利用STC89C51单片机和LCD1602电子显示屏实现电子时钟可由按键进行调时和1...

基于51单片机洗衣机课程设计报告

单片机原理及系统课程设计专业自动控制班级控1102姓名学号指导教师兰州交通大学自动化与电气工程学院20xx年1月13日单片机原理及系统课程设计报告基于51单片机的洗衣机设计1设计目的要求及原理11设计目的由单片...

基于51单片机音乐播放器课程设计报告

课程设计课程设计名称单片机课程设计专业班级电科0901学生姓名学号20xx48360118指导教师课程设计时间20xx92020xx928电子信息科学与技术专业课程设计任务书说明本表由指导教师填写由教研室主任审...

51单片机课程设计报告(36篇)