单片机电子时钟的设计(毕业设计)_第1页
单片机电子时钟的设计(毕业设计)_第2页
单片机电子时钟的设计(毕业设计)_第3页
单片机电子时钟的设计(毕业设计)_第4页
单片机电子时钟的设计(毕业设计)_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、摘 要单片机,是集cpu ,ram ,rom ,计数和多种接口于一体的微控制器。自20世纪70年代问世以来,以其极高的性能价格比,受到人们的重视和关注。它体积小、重量轻、抗干扰能力强、环境要求不高、价格低廉、可靠性高、灵活性好、开发较为容易,广泛应用于智能生产和工业自动化上。本课题通过mcs-51单片机来设计,采用汇编语言进行编程,可以实现以下一些功能:小时,分,秒和年,月,的显示、定时报警功能。本次设计的电子时钟系统由时钟电路,lcd显示电路,定时报警电路,按键调整电路四部分组成。51单片机通过软件编程,在lcd1602液晶屏上实现小时,分,秒和年,月,的显示;利用时钟芯片ds1302来实现

2、计时,定时功能;通过两个按键开关,一个用于时钟的调节,一个用于闹钟的调节,来实现参数设置和调节功能;到达设置的闹钟时间时,由蜂鸣器发声,起报警作用。本次设计的电子时钟,经过对比测试,发现实际计时的走时精度较高,可满足多种场合的应用需求。本文详细介绍了at89c51单片机的基本原理,分析了at89c51各个管脚的功能及它在设计电路中的作用。本文论述了lcd1602液晶屏和时钟芯片ds1302的工作原理及其软件设计过程。关键词:单片机;电子时钟;时钟芯片;lcd16021 引 言单片机,亦称单片微电脑或单片微型计算机。它是把中央处理器(cpu)、随机存取存储器(ram)、只读存储器(rom)、输入

3、/输出端口 (i/0)等主要计算机功能部件都集成在一块集成电路芯片上的微型计算机。单片机是把主要计算机功能部件都集成在一块芯片上的微型计算机。它是一种集计数和多中接口于一体的微控制器,被广泛应用在智能产品和工业自动化上,而52单片机是个单片机中最为典型和最有代表性的一种。 现在高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟、石英钟、石英表都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调试,数字式电子钟用集成电路计时时,译码代替机械式传动,用led显示器代替指针显示进而显示时间,减小了计时误差,这种表具有时、分、秒显示时间的功能,还可以进行时和分的校对,片选的灵活性好

4、。2 系统结构整个电子时钟系统电路可分为五大部分:中央处理单元(cpu)、显示部分、键盘输入部分、温度采集部分。2 1 中央处理单元cpu选用at89c52对整个系统进行控制:1)它将定时数据输出到led,实现时间的显示;2)根据键盘输入调用相应键处理子程序,实现时间的调整设定;3)接收温度传感器输入的温度数据,进行一定转换,输出到lcd显示器显示。22 显示部分显示部分是整个电子时钟最为重要的部分,它分为时间的显示和温度的显示两部分,采用动态显示方式,动态显示方式是时间数字在led上逐个显示,通过位选端控制在哪个led上显示数字,由于led数字显示之间的时间非常的短,人眼看来是一起显示时间数

5、字的,并且动态显示方式所用的接口少,节省了cpu的管脚。由于端口的问题以及动态显示方式的优越性,在此设计的连接方式上采用共阴级接法。23 键盘部分它是整个系统中最简单的部分,根据功能要求,本系统共需四个按键:功能移位键、功能加键、功能减键、立刻跳出调整模式键采用独立式按键。24 温度采集部分 此部分选用ds18b20传感器,主要由四部分组成:64位rom、温度传感器、非挥发的温度报警触发器th和tl、配置寄存器。有三个管脚:dq为数字信号输入/输出端;gnd为电源地;vdd为外接供电电源输入端。它是支持“一线总线”接口的温度传感器,测量温度范围为-55c+125c,在-10+85c范围内,可编

6、程为9位12位a/d转换精度,工作电压在3v5v之间。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。2电路制作根据电路图(如图示1)将元器件布置在电路板上:如图(1)系统程序设计#include #include /#include lcd1602.h/#include ds1302.h#define uint unsigned int#define uchar unsigned charsbit ds1302_clk = p17; /实时时钟时钟线引脚 sbit ds1302_io = p16; /实时时钟数据线引脚 sbit ds1302_rst = p15; /实时

7、时钟复位线引脚sbit wireless_1 = p30;sbit wireless_2 = p31;sbit wireless_3 = p32;sbit wireless_4 = p33;sbit acc0 = acc0;sbit acc7 = acc7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; /秒,分,时到日,月,年位闪的计数sbit set = p20; /模式切换键sbit up = p21; /加法按钮sbit down = p22; /减法按钮sbit out = p23;

8、/立刻跳出调整模式按钮sbit dq = p10; /温度传送数据io口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; /温度值uchar tempbuffer5,week_value2;void show_time(); /液晶显示程序/*1602液晶显示部分子程序*/port definitions*sbit lcdrs= p25;sbit lcdrw= p26;sbit lcden = p27;sfr dbport = 0x80;/p0=0x80,p1=0x90,p2=0xa0,p3=0xb0.数据端口/内部等待

9、函数*unsigned char lcd_wait(void)lcdrs=0;lcdrw=1;_nop_();lcden=1;_nop_();lcden=0;return dbport;/lcd写入命令或数据*#define lcd_command0 / command#define lcd_data1 / data#define lcd_clear_screen0x01 / 清屏#define lcd_homing 0x02 / 光标返回原点void lcd_write(bit style, unsigned char input)lcden=0;lcdrs=style;lcdrw=0;_n

10、op_();dbport=input;_nop_();/注意顺序lcden=1;_nop_();/注意顺序lcden=0;_nop_();lcd_wait();/设置显示模*#define lcd_show0x04 /显示开#define lcd_hide0x00 /显示关 #define lcd_cursor0x02 /显示光标#define lcd_no_cursor0x00 /无光标 #define lcd_flash0x01 /光标闪动#define lcd_no_flash0x00 /光标不闪动void lcd_setdisplay(unsigned char displaymode

11、)lcd_write(lcd_command, 0x08|displaymode);/设置输入模*#define lcd_ac_up0x02#define lcd_ac_down0x00 / default#define lcd_move0x01 / 画面可平移#define lcd_no_move0x00 /defaultvoid lcd_setinput(unsigned char inputmode)lcd_write(lcd_command, 0x04|inputmode);/初始化lcd*void lcd_initial()lcden=0;lcd_write(lcd_command,

12、0x38); /8位数据端口,2行显示,5*7点阵lcd_write(lcd_command,0x38);lcd_setdisplay(lcd_show|lcd_no_cursor); /开启显示, 无光标lcd_write(lcd_command,lcd_clear_screen); /清屏lcd_setinput(lcd_ac_up|lcd_no_move); /ac递增, 画面不动/液晶字符输入的位置*void gotoxy(unsigned char x, unsigned char y)if(y=0)lcd_write(lcd_command,0x80|x);if(y=1)lcd_w

13、rite(lcd_command,0x80|(x-0x40);void print(unsigned char *str)while(*str!=0)lcd_write(lcd_data,*str);str+;/*ds1302时钟部分子程序*/typedef struct _systemtime_unsigned char second;unsigned char minute;unsigned char hour;unsigned char week;unsigned char day;unsigned char month;unsigned char year;unsigned char

14、datestring11;unsigned char timestring9;systemtime;/定义的时间类型systemtime currenttime;#define am(x)x#define pm(x)(x+12) / 转成24小时制#define ds1302_second0x80 /时钟芯片的寄存器位置,存放时间#define ds1302_minute0x82#define ds1302_hour0x84 #define ds1302_week0x8a#define ds1302_day0x86#define ds1302_month0x88#define ds1302_y

15、ear0x8c void ds1302inputbyte(unsigned char d) /实时时钟写入一字节(内部函数) unsigned char i; acc = d; for(i=8; i0; i-) ds1302_io = acc0; /相当于汇编中的 rrc ds1302_clk = 1; ds1302_clk = 0; acc = acc 1; unsigned char ds1302outputbyte(void) /实时时钟读取一字节(内部函数) unsigned char i; for(i=8; i0; i-) acc = acc 1; /相当于汇编中的 rrc acc7

16、 = ds1302_io; ds1302_clk = 1; ds1302_clk = 0; return(acc); void write1302(unsigned char ucaddr, unsigned char ucda) ds1302_rst = 0; ds1302_clk = 0; ds1302_rst = 1; ds1302inputbyte(ucaddr); / 地址,命令 ds1302inputbyte(ucda); / 写1byte数据 ds1302_clk = 1; ds1302_rst = 0; unsigned char read1302(unsigned char

17、ucaddr)/读取ds1302某地址的数据 unsigned char ucdata; ds1302_rst = 0; ds1302_clk = 0; ds1302_rst = 1; ds1302inputbyte(ucaddr|0x01); / 地址,命令 ucdata = ds1302outputbyte(); / 读1byte数据 ds1302_clk = 1; ds1302_rst = 0; return(ucdata);void ds1302_gettime(systemtime *time) /获取时钟芯片的时钟数据unsigned char readvalue;readvalu

18、e = read1302(ds1302_second);time-second = (readvalue&0x70)4)*10 + (readvalue&0x0f);readvalue = read1302(ds1302_minute);time-minute = (readvalue&0x70)4)*10 + (readvalue&0x0f);readvalue = read1302(ds1302_hour);time-hour = (readvalue&0x70)4)*10 + (readvalue&0x0f);readvalue = read1302(ds1302_day);time-d

19、ay = (readvalue&0x70)4)*10 + (readvalue&0x0f);readvalue = read1302(ds1302_week);time-week = (readvalue&0x70)4)*10 + (readvalue&0x0f);readvalue = read1302(ds1302_month);time-month = (readvalue&0x70)4)*10 + (readvalue&0x0f);readvalue = read1302(ds1302_year);time-year = (readvalue&0x70)4)*10 + (readval

20、ue&0x0f);void datetostr(systemtime *time) /将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里datestring if(hide_year2) /这里的if,else语句都是判断位闪烁,2就不显示,输出字符串为 2007/07/22 time-datestring0 = 2; time-datestring1 = 0; time-datestring2 = time-year/10 + 0; time-datestring3 = time-year%10 + 0; else time-datestring0 = ; time-datestri

21、ng1 = ; time-datestring2 = ; time-datestring3 = ;time-datestring4 = /;if(hide_monthdatestring5 = time-month/10 + 0; time-datestring6 = time-month%10 + 0; else time-datestring5 = ; time-datestring6 = ; time-datestring7 = /;if(hide_daydatestring8 = time-day/10 + 0; time-datestring9 = time-day%10 + 0;

22、else time-datestring8 = ; time-datestring9 = ; if(hide_weekweek%10 + 0; /星期的数据另外放到 week_value数组里,跟年,月,日的分开存放,因为等一下要在最后显示 else week_value0 = ; week_value1 = 0;time-datestring10 = 0; /字符串末尾加 0 ,判断结束字符void timetostr(systemtime *time) /将时,分,秒数据转换成液晶显示字符 if(hide_hourtimestring0 = time-hour/10 + 0; time-t

23、imestring1 = time-hour%10 + 0; else time-timestring0 = ; time-timestring1 = ;time-timestring2 = :; if(hide_mintimestring3 = time-minute/10 + 0; time-timestring4 = time-minute%10 + 0; else time-timestring3 = ; time-timestring4 = ; time-timestring5 = :; if(hide_sectimestring6 = time-second/10 + 0; tim

24、e-timestring7 = time-second%10 + 0; else time-timestring6 = ; time-timestring7 = ; time-datestring8 = 0;void initial_ds1302(void) /时钟芯片初始化 unsigned char second=read1302(ds1302_second);if(second&0x80) /判断时钟芯片是否关闭 write1302(0x8e,0x00); /写入允许write1302(0x8c,0x07);/写入初始化值07/07/25.星期:3.时间: 23:59:55write13

25、02(0x88,0x07);write1302(0x86,0x25);write1302(0x8a,0x07);write1302(0x84,0x23);write1302(0x82,0x59);write1302(0x80,0x55);write1302(0x8e,0x80); /禁止写入/*ds18b20子程序*/*ds18b20延迟子函数(晶振12mhz )*/ void delay_18b20(unsigned int i)while(i-);/*ds18b20初始化函数*/void init_ds18b20(void) unsigned char x=0; dq = 1; /dq复位

26、 delay_18b20(8); /稍做延时 dq = 0; /单片机将dq拉低 delay_18b20(80); /精确延时 大于 480us dq = 1; /拉高总线 delay_18b20(14); x=dq; /稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay_18b20(20);/*ds18b20读一个字节*/ unsigned char readonechar(void)uchar i=0;uchar dat = 0;for (i=8;i0;i-) dq = 0; / 给脉冲信号 dat=1; dq = 1; / 给脉冲信号 if(dq) dat|=0x80;

27、delay_18b20(4); return(dat);/*ds18b20写一个字节*/ void writeonechar(uchar dat) unsigned char i=0; for (i=8; i0; i-) dq = 0; dq = dat&0x01; delay_18b20(5); dq = 1; dat=1; /*读取ds18b20当前温度*/void readtemp(void)unsigned char a=0;unsigned char b=0;unsigned char t=0;init_ds18b20();writeonechar(0xcc); / 跳过读序号列号的

28、操作writeonechar(0x44); / 启动温度转换delay_18b20(100); / this message is wery importantinit_ds18b20();writeonechar(0xcc); /跳过读序号列号的操作writeonechar(0xbe); /读取温度寄存器两个就是温度delay_18b20(100);a=readonechar(); /读取温度值低位b=readonechar(); /读取温度值高位temp_value=b4; void temp_to_str() /温度数据转换成液晶字符显示 tempbuffer0=temp_value/1

29、0+0; /十位 tempbuffer1=temp_value%10+0; /个位 tempbuffer2=0xdf; /温度符号 tempbuffer3=c; tempbuffer4=0;void delay1ms(unsigned int count)unsigned int i,j;for(i=0;icount;i+)for(j=0;j0;delay-) for(i=0;i0x59) /超过59秒,清零 temp=0; break; case 2: temp=read1302(ds1302_minute);/读取分数 temp=temp+1; /分数加1 up_flag=1; if(te

30、mp0x59) /超过59分,清零 temp=0; break; case 3: temp=read1302(ds1302_hour);/读取小时数 temp=temp+1; /小时数加1 up_flag=1; if(temp0x23) /超过23小时,清零 temp=0; break; case 4: temp=read1302(ds1302_week);/读取星期数 temp=temp+1; /星期数加1 up_flag=1; if(temp0x7) temp=1; break; case 5: temp=read1302(ds1302_day); /读取日数 temp=temp+1; /

31、日数加1 up_flag=1; if(temp0x31) temp=1; break; case 6: temp=read1302(ds1302_month);/读取月数 temp=temp+1; /月数加1 up_flag=1; if(temp0x12) temp=1; break; case 7: temp=read1302(ds1302_year); /读取年数 temp=temp+1; /年数加1 up_flag=1; if(temp0x85) temp=0; break; default:break; while(up=0); while(wireless_2=1); void do

32、wnkey()/降序按键 down=1; if(down=0|wireless_3=1) mdelay(8); switch(count) case 1: temp=read1302(ds1302_second);/读取秒数 temp=temp-1;/秒数减1 down_flag=1; /数据调整后更新标志 if(temp=0x7f) /小于0秒,返回59秒 temp=0x59; break; case 2: temp=read1302(ds1302_minute);/读取分数 temp=temp-1; /分数减1 down_flag=1; if(temp=-1) temp=0x59; /小于

33、0秒,返回59秒 break; case 3: temp=read1302(ds1302_hour);/读取小时数 temp=temp-1; /小时数减1 down_flag=1; if(temp=-1) temp=0x23; break; case 4: temp=read1302(ds1302_week);/读取星期数 temp=temp-1; /星期数减1 down_flag=1; if(temp=0) temp=0x7; break; case 5: temp=read1302(ds1302_day); /读取日数 temp=temp-1; /日数减1 down_flag=1; if(

34、temp=0) temp=31; break; case 6: temp=read1302(ds1302_month); /读取月数 temp=temp-1; /月数减1 down_flag=1; if(temp=0) temp=12; break; case 7: temp=read1302(ds1302_year); /读取年数 temp=temp-1; /年数减1 down_flag=1; if(temp=-1) temp=0x85; break; default:break; while(down=0); while(wireless_3=1); void setkey()/模式选择按

35、键set=1;if(set=0|wireless_4=1) mdelay(8); count=count+1; /setkey按一次,count就加1 done=1; /进入调整模式 while(set=0); while(wireless_4=1); void keydone()/按键功能执行 uchar second; if(flag=0) /关闭时钟,停止计时 write1302(0x8e,0x00); /写入允许 temp=read1302(0x80); write1302(0x80,temp|0x80); write1302(0x8e,0x80); /禁止写入 flag=1; set

36、key(); /扫描模式切换按键 switch(count) case 1:do /count=1,调整秒 outkey(); /扫描跳出按钮 upkey(); /扫描加按钮 downkey(); /扫描减按钮 if(up_flag=1|down_flag=1) /重新写入新的数据 write1302(0x8e,0x00); /写入允许 write1302(0x80,temp|0x80); /写入新的秒数 write1302(0x8e,0x80); /禁止写入 up_flag=0; down_flag=0; hide_sec+; /位闪计数 if(hide_sec3) hide_sec=0;

37、show_time(); /液晶显示数据 while(count=2);break; case 2:do /count=2,调整分 hide_sec=0; outkey(); upkey(); downkey(); if(temp0x60) temp=0; if(up_flag=1|down_flag=1) write1302(0x8e,0x00); /写入允许 write1302(0x82,temp); /写入新的分数 write1302(0x8e,0x80); /禁止写入 up_flag=0; down_flag=0; hide_min+; if(hide_min3) hide_min=0; show_time(); while(count=3);break; case 3:do /cou

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论