《基于单片机的电子时钟和显示屏的设计-毕业论文.doc》由会员分享,可在线阅读,更多相关《基于单片机的电子时钟和显示屏的设计-毕业论文.doc(38页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、目录1 方案设计1.1单片机电子时钟的背景11.2电子时钟的意义11.3 电子时钟的工作原理及其具体实现11.4 设计任务22 电路方案设计32.1 模块一电路图32.2 模块二电路图32.3 模块三电路图42.4 总电路图43程序设计53.1 主程序流程图53.2模块一DS1302流程图63.3模块二12864LCD流程图83.4 模块三DS18B20流程图73.5 源程序74 仿真与调试7总结语7参考文献7 1 方案设计1.1单片机电子时钟的背景随着电子技术和计算机技术的迅速发展,单片机已经在工业过程控制、智能仪表、计算机集成控制、人工智能、通信设备的智能化以及家电的智能化等方面得到广泛的
2、应用。以单片机和微控制器为核心仍然是当今实现智能化技术的主流。随着单片机技术广泛地应用与人们生活的各个方面,一些人们经常使用的产品大多数是基于单片机研发的,如电子时钟。钟表从原来的沙漏计时和机械打点塔钟等演变到如今的电池驱动钟、交流钟、指针式石英电子钟表和数字式石英电子钟表,并且钟表的准确度越来越高了。随着人们的时间观念逐渐地增强,时钟在我们人类的世界里扮演着一个非常重要的角色,几乎出现在我们生活的各个角落里,并且人们几乎离不开它了。如今的时钟的功能更加全面,与机械时钟相比具有更高的正确性和直观性,且无机械装置,具有更长的寿命,因此广泛地应用于人类正常生活中,得到人们的关注和研发。1.2电子时
3、钟的意义电子时钟采用数字电路实现对时、分、秒和数字显示的计时装置,广泛使用于个人家庭、车站、机场等公共场所,成为人们日常生活中不可缺少的必需品,给人们的生活、学习、工作、娱乐带来了极大的方便。由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得电子时钟的精度、稳定性大幅度提高。现在的钟表的功能越来越强,具有定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动启闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,因此,研究数字时钟及其扩展,有着重大意义。1.3 电子时钟的工作原理及其具体实现电子时钟的工作原理是采用单片机最小系统,用DS1302时钟芯片和12864LCD液
4、晶显示屏芯片以及DS18B20温度传感器分别进行寄存相关信息、显示年月日时分秒和采取温度,用四个键分别实现选择调整对象为、增加调节对象的数值、减少调节对象的数值和调整确定,采用24小时制、定时器0中断和外部中断0,从而实现可调式中文电子日历、温度及整点报时功能。采用定时器0中断,定时50ms,其中断服务程序的功能是将时间和日期显示到LCD上。每1s时间,刷新液晶显示屏上的秒钟数值;每60s时间,刷新显示屏的分钟数值;每60min时间,刷新显示屏的小时数值;每24h时间,刷新显示屏的日期;星期是通过年月日进行调整;温度是通过温度传感器芯片DS18B20进行调整;时钟每次到整点时,通过蜂鸣器进行整
5、点报时。采用外部中断0实现时钟的调整,将四个键通过“与门”连接单片机P32端口,从而通过键产生外部中断信号。当要调整日期时间的时候,首先要按K1键来选择调整对象,否则按其他键不会进行时间调整,然后可以按K2和K3键对日期时间进行加减调整,最后按K4键可以将改动的日期时间重新显示到LCD上。并且每次按下键后,都会通过蜂鸣器发出按键声音。1.4 设计任务(1)可调式中文电子日历的硬件和软件设计;(2)画出程序流程图;(3)编写代码;(4)程序分析与调试;2 电路方案设计2.1 模块一电路图该模块主要通过DS1302时钟芯片实现计算秒、分、时、星期、日、月、年的信息,且具有闰年补偿的功能,其在pro
6、teus中的电路图如图2.1.1所示。图2.1.1 记录年月日秒分时星期的电路图2.2 模块二电路图该模块主要通过12864LCD实现中文电子日历功能,其在proteus中的电路图如图2.2.1所示图2.2.1 显示时间电路图2.3 模块三电路图该模块主要通过DS18B20温度传感芯片、四个键以及蜂鸣器实现温度采集,时间调节和闹钟等功能。图2.3.1 时间调整电路图2.4 总电路图如图2.4.1所示。图2.4.1 总体硬件电路图3程序设计3.1 主程序流程图图3.1.1 主函数流程图3.2模块一DS1302流程图图3.2.1获取当前时间的流程图图3.2.2 年月日时分秒+/-流程图图3.2.3
7、定时器0的中断服务程序图3.2.4外部中断0服务程序3.3模块二12864LCD流程图图3.3.1 LCD初始化流程图图3.3.2 通用显示函数流程图3.4 模块三DS18B20流程图图3.4 1 读取温度值3.5 源程序#include#include#include#define uchar unsigned char#define uint unsigned intsbit SDA=P10;/*DS1302数据线*/sbit CLK=P11;/*DS1302时钟线*/sbit RST=P12;/*DS1302复位线*/sbit K1=P34; /*选择键*/sbit K2=P35; /*
8、加键*/sbit K3=P36; /*减键*/sbit K4=P37; /*确定键*/sbit SPK=P26;/*子函数定义*/*显示年函数*/extern void LCD_Initialize();/*液晶初始化函数*/*读取温度值*/extern void Read_Temperature();extern void Display_Temperature(); /*显示时间函数*/extern void Display_A_Char_8X16(uchar P,uchar L,ucha*M )reentrant;/*显示年月日,星期,时分秒的固定汉字函数*/extern void Di
9、splay_A_WORD(uchar P,uchar L,uchar *M)reentrant;void Beep();/*启动蜂鸣器函数*/*在调整日期时间时,用该位决定是否反白显示*/extern bit Reverse_Display;extern uchar Display_Digit=0,0,0,0;/*待显示的各温度数位*/extern bit DS18B20_IS_OK=1;/*传感器正常标志*/*全局变量和数组定义*/uchar tCount=0;/*一年中每个月的天数,2月的天数由年份决定*/uchar MonthsDays=0,31,0,31,30,31,30,31,31,
10、30,31,30,31;/*所读取的日期时间*/uchar DateTime7;/*当前调整的时间对象:秒,分,时,日,月,星期,年(0,1,2,3,4,5,6)变量*/*其中星期由年月日调整自动完成*/char Adjust_Index=-1;uchar H_Offset=10,V_Page_Offset=0;/*水平与垂直偏移变量*/*年月日,星期,时分秒汉字点阵16乘16*/uchar code DATE_TIME_WORDS= 0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,
11、 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00, /*年*/ 0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00, 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00, /*月*/ 0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42
12、,0x42,0x42,0xFE,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00, /*日*/ 0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00, 0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00, /*星*/ 0x00,0x0
13、4,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00, 0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00, /*期*/ 0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00, 0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F
14、,0x00,0x00,0x00,0x00, /*时*/ 0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00, 0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00, /*分*/ 0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00, 0x04,0x03,0x00,0xFF,0x0
15、0,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00, /*秒*/ 0x10,0x21,0x86,0x70,0x00,0x7E,0x4A,0x4A,0x4A,0x4A,0x4A,0x7E,0x00,0x00,0x00,0x00, 0x02,0xFE,0x01,0x40,0x7F,0x41,0x41,0x7F,0x41,0x41,0x7F,0x41,0x41,0x7F,0x40,0x00, /*温*/ 0x00,0x00,0xFC,0x04,0x24,0x24,0xFC,0xA5,0xA6,0xA4,0xFC,0x24,0x24,0x2
16、4,0x04,0x00, 0x80,0x60,0x1F,0x80,0x80,0x42,0x46,0x2A,0x12,0x12,0x2A,0x26,0x42,0xC0,0x40,0x00, /*度*/;/*星期几的汉字点阵16乘16*/uchar code WEEKDAY_WORDS= 0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0
17、x00, /*日*/ 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xC0,0x80,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*一*/ 0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x00, 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
18、0x10,0x10,0x10,0x10,0x10,0x18,0x10,0x00, /*二*/ 0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00, 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, /*三*/ 0x00,0xFE,0x02,0x02,0x02,0xFE,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0xFE,0x00,0x00, 0x00
19、,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x22,0x7F,0x00,0x00, /*四*/ 0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00, 0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00, /*五*/ 0x10,0x10,0x10,0x10,0x10,0x91,0x12,0x1E,0x94,0x10
20、,0x10,0x10,0x10,0x10,0x10,0x00, 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x00,0x00,0x01,0x02,0x0C,0x78,0x30,0x00,0x00, /*六*/;/*半角数字点阵8乘16*/uchar code DIGITS= 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,/*0*/ 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x
21、20,0x20,0x00,0x00,/*1*/ 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,/*2*/ 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,/*3*/ 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,/*4*/ 0x00,0xF8,0x08,0x8
22、8,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,/*5*/ 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,/*6*/ 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,/*7*/ 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,
23、0x21,0x22,0x1C,0x00,/*8*/ 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,/*9*/;/*生日快乐歌的音符频率表,不同的频率由不同的延时值来决定*/uchar code SONG_TONE=212,212,190,212,159,169,212,212,190,212,142,159, 212,212,106,126,159,169,190,119,119,126,159,142,159,0;/*生日快乐歌节拍表,节拍表决定了每个音符的演奏长短*/uchar
24、 code SONG_LONG=9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0;void DelayMS(uint x) /*调用延时子函数*/uchar i;while(x-) for(i=0;i120;i+);void PlayMusic()/*音乐播放函数*/uint i=0,j,k;while(SONG_LONGi!=0|SONG_TONEi!=0)/*播放各个音符,SONG_LONG为拍*/for(j=0;jSONG_LONGi*20;j+)SPK=SPK;/*SONG_TONE延时表决定了每个
25、音符的频率*/for(k=0;kSONG_TONEi/3;k+);DelayMS(100);/*下一个音符的索引*/i+;void Alarm(uchar t) /*温度报警函数*/uchar i,j;for(i=0;i200;i+)SPK=SPK;/*由参数t形成不同的频率*/for(j=0;jt;j+);/*向DS1302写入一字节*/void Write_A_Byte_TO_DS1302(uchar x)uchar i;for(i=0;i=1;/*从DS1302读取一字节*/uchar Get_A_Byte_FROM_DS1302()uchar i,b,t;for(i=0;i=1;t=S
26、DA;b|=t7;CLK=1;CLK=0;/*BCD码转换*/return(b/16*10+b%16);/*从DS1302指定位置读数据*/uchar Read_Data(uchar addr)uchar dat;RST=0;CLK=0;RST=1;Write_A_Byte_TO_DS1302(addr);dat=Get_A_Byte_FROM_DS1302();CLK=1;RST=0;return dat;/*向DS1302某地址写入数据*/void Write_DS1302(uchar addr,uchar dat)CLK=0; RST=1;Write_A_Byte_TO_DS1302(a
27、ddr);Write_A_Byte_TO_DS1302(dat);CLK=1;RST=0;/*设置时间*/void SET_DS1302()uchar i;Write_DS1302(0x8E,0x00);/*秒分时日月年依次写入*/for(i=0;i7;i+)/*秒,分,时,日,月,星期,年的起始地址分别为0x80,0x82,0x84,0x86,0x88,0x8A,0x8C*/ Write_DS1302(0x80+2*i,(DateTimei/104)|(DateTimei%10);Write_DS1302(0x8E,0x80);/*读取当前时间*/void GetTime()uchar i;
28、for(i=0;i7;i+)DateTimei=Read_Data(0x81+2*i); uchar isLeapYear(uint y)/*判断是否为闰年*/return (y%4=0&y%100!=0)|(y%400=0);/*刷新星期*/void RefreshWeekDay()uint i,d,w=5;/*已知1999.12.31是周五*/for(i=2000;i2000+DateTime6;i+)d=isLeapYear(i)?366:365;w=(w+d)%7;d=0;for(i=1;iDateTime4;i+) d+=MonthsDaysi;d+=DateTime3;/*保存星期
29、,06表示星期日,星期一,二,三,四,五,六,为了与DS1302的星期格式匹配,返回值需要加1*/DateTime5=(w+d)%7+1;/*蜂鸣器函数*/void Beep(uchar t)uchar i;for(i=0;i100;i+)SPK=SPK;DelayMS(t);SPK=0;void DateTime_Adjust(char x)/*年月日时分+或-*/switch(Adjust_Index)case 6: /*年00-99*/if(x=1&DateTime60) DateTime6-;/*获取2月天数*/ MonthsDays2=isLeapYear(2000+DateTime
30、6)?29:28;/*如果年份变化后当前月份的天数大于上限则设为上限*/if(DateTime3MonthsDaysDateTime4)DateTime3=MonthsDaysDateTime4;RefreshWeekDay();/*刷新星期*/break;case 4: /*月01至12*/if(x=1&DateTime41) DateTime4-;/*获取2月天数*/ MonthsDays2=isLeapYear(2000+DateTime6)?29:28;/*如果年份变化后当前月份的天数大于上限则设为上限*/if(DateTime3MonthsDaysDateTime4) DateTim
31、e3=MonthsDaysDateTime4;RefreshWeekDay();/*刷新星期*/break;case 3:/*日00至28/29/30/31;调节之前首先根据年份得出该年中2月的天数*/ MonthsDays2=isLeapYear(2000+DateTime6)?29:28;/*再根据当前月份决定调节日期的上限*/if(x=1&DateTime30) DateTime3-;RefreshWeekDay();/*刷新星期*/break;case 2: /*小时*/if(x=1&DateTime223) DateTime2+;DateTime2-;break;case 1: /*
32、分钟*/if(x=1&DateTime10) DateTime1-;break;case 0: /*秒*/if(x=1&DateTime059) DateTime0+;break;/*定时器0每秒刷新LCD显示*/void T0_INT() interrupt 1TH0=(65536-50000)/256;TL0=(65536-50000)%256;if(+tCount!=2) return;tCount=0;/*年(后两位)*/Reverse_Display=Adjust_Index=6; Display_A_Char_8X16(V_Page_Offset,70+H_Offset,DIGIT
33、S+DateTime6/10*16); Display_A_Char_8X16(V_Page_Offset,78+H_Offset,DIGITS+DateTime6%10*16);/*星期*/Reverse_Display=Adjust_Index=5; Display_A_WORD(V_Page_Offset+3,32+H_Offset,WEEKDAY_WORDS+(DateTime5%10-1)*32);/*月*/Reverse_Display=Adjust_Index=4; Display_A_Char_8X16(V_Page_Offset,102+H_Offset,DIGITS+Dat
34、eTime4/10*16); Display_A_Char_8X16(V_Page_Offset,110+H_Offset,DIGITS+DateTime4%10*16);/*日*/Reverse_Display=Adjust_Index=3; Display_A_Char_8X16(V_Page_Offset,5+H_Offset,DIGITS+DateTime3/10*16); Display_A_Char_8X16(V_Page_Offset,13+H_Offset,DIGITS+DateTime3%10*16);/*时*/Reverse_Display=Adjust_Index=2;
35、Display_A_Char_8X16(V_Page_Offset+6,56+H_Offset,DIGITS+DateTime2/10*16); Display_A_Char_8X16(V_Page_Offset+6,64+H_Offset,DIGITS+DateTime2%10*16);/*分钟*/Reverse_Display=Adjust_Index=1; Display_A_Char_8X16(V_Page_Offset+6,88+H_Offset,DIGITS+DateTime1/10*16); Display_A_Char_8X16(V_Page_Offset+6,96+H_Off
36、set,DIGITS+DateTime1%10*16);/*秒*/Reverse_Display=Adjust_Index=0; Display_A_Char_8X16(V_Page_Offset+6,-10+H_Offset,DIGITS+DateTime0/10*16); Display_A_Char_8X16(V_Page_Offset+6,-2+H_Offset,DIGITS+DateTime0%10*16);/*键盘中断(INT0)*/void EX_INT0() interrupt 0if(K1=0) /*选择调整对象*/ Beep(1);if(Adjust_Index=-1|Ad
37、just_Index=0) Adjust_Index=7;Adjust_Index-;if(Adjust_Index=5) Adjust_Index=4; /*跳过对星期的调整*/elseif(K2=0) /*加*/ Beep(1);DateTime_Adjust(1);elseif(K3=0) /*减*/ Beep(1); DateTime_Adjust(-1);elseif(K4=0) /*确定*/Beep(1);SET_DS1302(); /*将调整后的时间写入DS1302*/Adjust_Index=-1; /*操作索引重设为-1,时间继续正常显示*/*主函数*/void main()
38、LCD_Initialize();/*液晶初始化*/Read_Temperature();DelayMS(50);DelayMS(50);/*显示年的固定前两位*/ Display_A_Char_8X16(V_Page_Offset,55+H_Offset,DIGITS+2*16); Display_A_Char_8X16(V_Page_Offset,62+H_Offset,DIGITS);/*显示固定汉字:年月日,星期,时分秒,温度:*/ Display_A_WORD(V_Page_Offset,86+H_Offset,DATE_TIME_WORDS+0*32); Display_A_WOR
39、D(V_Page_Offset,-10+H_Offset,DATE_TIME_WORDS+1*32); Display_A_WORD(V_Page_Offset,21+H_Offset,DATE_TIME_WORDS+2*32); Display_A_WORD(V_Page_Offset+3,0+H_Offset,DATE_TIME_WORDS+3*32); Display_A_WORD(V_Page_Offset+3,16+H_Offset,DATE_TIME_WORDS+4*32); Display_A_WORD(V_Page_Offset+3,56+H_Offset,DATE_TIME_
40、WORDS+8*32); Display_A_WORD(V_Page_Offset+3,72+H_Offset,DATE_TIME_WORDS+9*32); Display_A_WORD(V_Page_Offset+6,72+H_Offset,DATE_TIME_WORDS+5*32); Display_A_WORD(V_Page_Offset+6,104+H_Offset,DATE_TIME_WORDS+6*32); Display_A_WORD(V_Page_Offset+6,6+H_Offset,DATE_TIME_WORDS+7*32);/*允许外部中断,定时器0中断*/IE=0x83;IP=0x01;IT0=0x01;TMOD=0x01;TH0=0x3C;TL0=0xB0;TR0=1;while(1)/*如果未执行调整时间操作,则就继续显示当前时间*/if(Adjust_Index=-1) GetTime();Read_Temperature();if(DS18B20_IS_OK) Display_Temperature();DelayMS(100);/*温度*/if(Display_Digit3!=0) Display_A_Char_8X16(V_Page_Offset+3,80+H_Offset,DIGITS+Display_Digit3*16);