




已阅读5页,还剩24页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
桂林电子科技大学课程设计课题名称: 电子钟设计 专 业:电气工程及其自动化学 生: 指导教师: 郭福利 2013年12月25日目录一、设计要求-3二、设计方案和论证-31、总设计原理图-32、设计方案的选择-33、硬件部分-44、软件部分-75、pcb制板图与整体电路仿真-8三、元件清单-9四、安装与调试-9五、设计总结-六、参考文献-一、设计要求1.有8位显示2.可以显示时间、日期、星期3.几个按键可以校正时间。二、设计方案和论证本次设计时钟电路,使用了以atc89c52单片机为核心控制器件,再配上ds1302时钟芯片、lcd1602液晶显示、八个按键开关组成的简单时钟电路,并在题目要求的基础上用ds18b20拓展了一个温度检测电路。单片机的使用使电路得到了很大的简化,按键是用来调时和日期的,同时使用c语言程序来控制整个时钟运行及显示,程序的使用使得设计变得更加简单方便。此设计可以满足题目所提出的所有要求。(一)总设计原理框图如下图所示:(二)设计方案的选择1.计时方案方案1:采用实时时钟芯片现在市场上有很多实时时钟集成电路,如ds1287、ds12887、ds1302等。这些实时时钟芯片具备年、月、日、时、分、秒计时功能和多点定时功能,计时数据的更新每秒自动进行一次,不需要程序干预。因此,在工业实时测控系统中多采用这一类专用芯片来实现实时时钟功能。方案2:使用单片机内部的可编程定时器。利用单片机内部的定时计数器进行中端定时,配合软件延时实现时、分、秒的计时。该方案节省硬件成本,但程序设计较为复杂。2.显示方案方案一:两个4位七段数码管显示由于单片机的i/o有限,并且无法直接驱动7段数码管显示,所以必须得加4个锁存器用于拓展单片机的i/o口,这样一来便会增加硬件的开销,其显示也较为麻烦,而且两个4位一体的7段数码管的体积有些大,因此也会增加板子的面积而且不够美观。方案二:lcd1602液晶显示lcd1602占用的i/o口较少,而且不用外加芯片驱动,显示较为方便,可以在一个界面上全部显示所要显示的内容,硬件开销小,编程方便,板子占用面积小。经过两个方案的比较,决定使用方案二。(三)硬件部分1、stc89c51单片机介绍stc89c51单片机是由深圳宏晶公司代理销售的一款mcu,是由美国设计生产的一种低电压、高性能cmos8位单片机,片内含8kbytes的可反复写的flashrom和128bytes的ram,2个16位定时计数器5。stc89c51单片机内部主要包括累加器acc(有时也简称为a)、程序状态字psw、地址指示器dptr、只读存储器rom、随机存取存储器ram、寄存器、并行i/o接口p0p3、定时器/计数器、串行i/o接口以及定时控制逻辑电路等。这些部件通过内部总线联接起来,构成一个完整的微型计算机。其管脚图如图所 示:vcc:电源。gnd:接地。p0口:p0口为一个8位漏级开路双向i/o口,每脚可吸收8ttl门电流。当p1口的管脚第一次写1时,被定义为高阻输入。p0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在fiash编程时,p0口作为原码输入口,当fiash进行校验时,p0输出原码,此时p0外部必须被拉高。p1口:p1口是一个内部提供上拉电阻的8位双向i/o口,p1口缓冲器能接收输出4ttl门电流。p1口管脚写入1后,被内部上拉为高,可用作输入,p1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在flash编程和校验时,p1口作为第八位地址接收。p2口:p2口为一个内部上拉电阻的8位双向i/o口,p2口缓冲器可接收,输出4个ttl门电流,当p2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,p2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。p2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,p2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,p2口输出其特殊功能寄存器的内容。p2口在flash编程和校验时接收高八位地址信号和控制信号。p3口:p3口管脚是8个带内部上拉电阻的双向i/o口,可接收输出4个ttl门电流。当p3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,p3口将输出电流(ill)这是由于上拉的缘故。p3口也可作为at89c51的一些特殊功能口,如下表所示:口管脚备选功能p3.0rxd(串行输入口)p3.1txd(串行输出口)p3.2/int0(外部中断0)p3.3/int1(外部中断1)p3.4t0(记时器0外部输入)p3.5t1(记时器1外部输入)p3.6/wr(外部数据存储器写选通)p3.7/rd(外部数据存储器读选通)p3口同时为闪烁编程和编程校验接收一些控制信号。rst:复位输入。当振荡器复位器件时,要保持rst脚两个机器周期的高电平时间。ale/prog:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在flash编程期间,此引脚用于输入编程脉冲。在平时,ale端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ale脉冲。如想禁止ale的输出可在sfr8eh地址上置0。此时,ale只有在执行movx,movc指令是ale才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ale禁止,置位无效。psen:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/psen有效。但在访问外部数据存储器时,这两次有效的/psen信号将不出现。ea/vpp:当/ea保持低电平时,则在此期间外部程序存储(0000h-ffffh),不管是否有内部程序存储器。注意加密方式1时,/ea将内部锁定为reset;当/ea端保持高电平时,此间内部程序存储器。在flash编程期间,此引脚也用于施加12v编程电源(vpp)。2、时钟显示电路 3、时钟校正电路本设计共用到了8个按键,其电路图及各个按键的功能如下: key1:key2:key3:key4:key5:key6:key7:key8:4、蜂鸣器电路电路接法:三极管选定npn型,基极b通过一个1k的电阻接到p3.6,射极e直接接地,集电极c接到蜂鸣器的阴极。单片机在复位后的个i/o口是高电平,此时三极管是截止的,通过编写程序当所设定的闹铃时间到,则p3.6输出低电平,此时三极管导通,导通后蜂鸣器与电源正极连通,构成一个工作回路,从而发出滴滴的响声。其中电阻r4在电路里起分压限流的作用,pnp三极管起到模拟开关的作用。8、外接电源电路外接电源电路用于连接外部5v电源与电子时钟电路,当上电正常时d1指示灯亮,否则说明上电不正常。(四)软件部分1、实验原理图:2、pcb制板图与电路仿真图3、实验总程序如下:#include#include1602.c#include1302.c#include18b20.csbit set_time = p27;sbit set_date = p26;sbit set_clock = p25;sbit add0 = p20;sbit add1 = p21;sbit add2 = p22;sbit set_week = p23;sbit confir = p24;systemtime time;unsigned char nweek;unsigned char code week76 = m o n,t u e,w e d,t h u,f r i,s a t,s u n;void scan();void main()double temp0;unsigned char day0;lcd_init();initial_ds1302();while(1)day0 = time.day;scan();ds1302_gettime(&time);if(day0 != time.day)nweek+;if(nweek = 7)nweek = 0;lcd_disp_str(0,0,time.datestring);lcd_disp_str(10,0,weeknweek);lcd_disp_str(0,1,time.timestring);tempchange();temp = get_temp();temp0 = 10*(temp*0.0625+0.05);lcd_disp_char(10,1,0 + (int)temp0/100);lcd_disp_char(11,1,0+(int)temp0%100/10);lcd_disp_char(12,1,.);lcd_disp_char(13,1,0+(int)temp0%10);lcd_disp_char(14,1,94);lcd_disp_char(15,1,c);void scan()if(set_time = 0)ds1302_timestop(1);while(confir = 1)timetostr(&time);lcd_disp_str(0,1,time.timestring);if(add0 = 0)/delay();if(add0 = 0)if(time.hour23)time.hour+;elsetime.hour = 0;while(add0 = 0);if(add1 = 0)/delay();if(add1 = 0)if(time.minute59)time.minute+;elsetime.minute = 0;while(add1 = 0) ;if(add2 = 0)/delay();if(add2 = 0)if(time.second59)time.second+;elsetime.second = 0;while(add2 = 0);ds1302_settime(time);ds1302_timestop(0);if(set_date = 0)ds1302_timestop(1);while(confir = 1)datetostr(&time);lcd_disp_str(0,0,time.datestring);lcd_disp_str(10,0,weeknweek);if(add0 = 0)/delay();if(add0 = 0)if(time.year99)time.year+;elsetime.year = 0;while(add0 = 0);if(add1 = 0)/delay();if(add1 = 0)if(time.month12)time.month+;elsetime.month = 1;while(add1 = 0);if(add2 = 0)/delay();if(add2 = 0)if(time.day31)time.day+;elsetime.day = 0;while(add2 = 0);if(set_week = 0)/delay();if(set_week = 0)if(nweek6)nweek+;elsenweek = 0;while(set_week = 0);ds1302_settime(time);ds1302_timestop(0);/*void timeset() interrupt 0ds1302_timestop(1);while(confir = 1)timetostr(&time);lcd_disp_str(0,1,time.timestring);if(add0 = 0)/delay();if(add0 = 0)if(time.hour23)time.hour+;elsetime.hour = 0;while(add0 = 0);if(add1 = 0)/delay();if(add1 = 0)if(time.minute59)time.minute+;elsetime.minute = 0;while(add1 = 0);if(add2 = 0)/delay();if(add2 = 0)if(time.second59)time.second+;elsetime.second = 0;while(add2 = 0);ds1302_settime(time);ds1302_timestop(0);void dateset() interrupt 2ds1302_timestop(1);while(confir = 1)datetostr(&time);lcd_disp_str(0,0,time.datestring);if(add0 = 0)/delay();if(add0 = 0)if(time.year99)time.year+;elsetime.year = 0;while(add0 = 0);if(add1 = 0)/delay();if(add1 = 0)if(time.month12)time.month+;elsetime.month = 1;while(add1 = 0);if(add2 = 0)/delay();if(add2 = 0)if(time.day31)time.day+;elsetime.day = 0;while(add2 = 0);ds1302_settime(time);ds1302_timestop(0);#includesbit ds1302_clk = p30; /实时时钟时钟线引脚sbit ds1302_io = p31; /实时时钟数据线引脚sbit ds1302_rst = p32;/实时时钟复位线引脚/*sbit ds1302_clk = p36; /实时时钟时钟线引脚sbit ds1302_io = p34; /实时时钟数据线引脚sbit ds1302_rst = p35;*/实时时钟复位线引脚sbit acc0 = acc0;sbit acc7 = acc7;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 datestring9;unsigned char timestring9;systemtime;/定义的时间类型#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_year0x8c#define ds1302_ram(x)(0xc0+(x)*2) /用于计算 ds1302_ram 地址的宏void ds1302inputbyte(unsigned char d) /实时时钟写入一字节(内部函数)unsigned char i;acc = d;for(i=8; i0; i-)ds1302_io = acc0; /相当于汇编中的 rrcds1302_clk = 1;ds1302_clk = 0;acc = acc 1;unsigned char ds1302outputbyte(void) /实时时钟读取一字节(内部函数)unsigned char i;for(i=8; i0; i-)acc = acc 1; /相当于汇编中的 rrcacc7 = ds1302_io;ds1302_clk = 1;ds1302_clk = 0;return(acc);void write1302(unsigned char ucaddr, unsigned char ucda)/ucaddr: ds1302地址, ucdata: 要写的数据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 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_setprotect(bit flag) /是否写保护if(flag)write1302(0x8e,0x10);elsewrite1302(0x8e,0x00);void ds1302_settime(systemtime time) / 设置时间函数ds1302_setprotect(0);write1302(ds1302_second, (time.second/10)4 | (time.second%10);write1302(ds1302_minute, (time.minute/10)4 | (time.minute%10);write1302(ds1302_hour, (time.hour/10)4 | (time.hour%10);write1302(ds1302_year,(time.year/10)4 | (time.year%10);write1302(ds1302_month,(time.month/10)4 | (time.month%10);write1302(ds1302_day,(time.day/10)datestring0 = time-year/10 + 0;time-datestring1 = time-year%10 + 0;time-datestring2 = -;time-datestring3 = time-month/10 + 0;time-datestring4 = time-month%10 + 0;time-datestring5 = -;time-datestring6 = time-day/10 + 0;time-datestring7 = time-day%10 + 0;time-datestring8 = 0;void timetostr(systemtime *time)time-timestring0 = time-hour/10 + 0;time-timestring1 = time-hour%10 + 0;time-timestring2 = :;time-timestring3 = time-minute/10 + 0;time-timestring4 = time-minute%10 + 0;time-timestring5 = :;time-timestring6 = time-second/10 + 0;time-timestring7 = time-second%10 + 0;time-datestring8 = 0;void ds1302_gettime(systemtime *time)unsigned char readvalue;readvalue = 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-day = (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 + (readvalue&0x0f);datetostr(time);timetostr(time);void initial_ds1302(void)unsigned char second=read1302(ds1302_second);if(second&0x80)write1302(ds1302_second, (0/10)0; i-) /8byte = 7byte 时钟数据 + 1byte 控制ds1302inputbyte(*pwclock); / 写1byte数据pwclock+;ds1302_clk = 1;ds1302_rst = 0;void burstread1302(unsigned char *prclock)/读取ds1302时钟数据(时钟多字节方式)unsigned char i;ds1302_rst = 0;ds1302_clk = 0;ds1302_rst = 1;ds1302inputbyte(0xbf); / 0xbf:时钟多字节读命令for (i=8; i0; i-)*prclock = ds1302outputbyte(); / 读1byte数据prclock+;ds1302_clk = 1;ds1302_rst = 0;void ds1302_timestop(bit flag) / 是否将时钟停止unsigned char data;data=read1302(ds1302_second);ds1302_setprotect(0);if(flag)write1302(ds1302_second, data|0x80);elsewrite1302(ds1302_second, data&0x7f);#include#include #include #include /*lcd1602 设置 start*/#define lcd_db p0sbit lcd_rs=p11;unsigned char lcd_rw;sbit lcd_e=p10;/*#define lcd_db p0sbit lcd_rs=p26;sbit lcd_rw = p25;sbit lcd_e=p27;*/*lcd1602 设置 start*/*定义函数*/#define uchar unsigned char#define uint unsigned intvoid lcd_init(void); /初始化函数void lcd_write_command(uchar command); /写指令函数void lcd_write_data(uchar dat); /写数据函数void lcd_disp_char(uchar x,uchar y,uchar dat);/ 在某个屏幕位置上显示一个字符,x(0-15),y(1-2)void lcd_disp_str(uchar x,uchar y,uchar *str); /lcd1602 显示字符串函数void delay_n10us(uint n); /延时函数uint jishu,jishu1=0,wendu,bb,fen=0,miao=0,fmiao=0;/*-;模块名称:lcd_init();功 能:初始化lcd1602;占用资源:-;参数说明:-;-*/void delay(uint z)uint i,j;for(i=z;i0;i-)for(j=100;j0;j-);void lcd_init(void)delay_n10us(10);lcd_write_command(0x38);/设置8 位格式,2 行,5x7delay_n10us(10);lcd_write_command(0x0c);/整体显示,关光标,不闪烁delay_n10us(10);lcd_write_command(0x06);/设定输入方式,增量不移位delay_n10us(10);lcd_write_command(0x01);/清除屏幕显示delay_n10us(100); /延时清屏,延时函数,延时约n 个10us/*-;模块名称:lcd_write_command();功 能:lcd1602 写指令函数;占用资源: p2.0-rs(lcd_rs),p2.1-rw(lcd_rw),p2.2-e(lcd_e).;参数说明:dat 为写命令参数;-*/void lcd_write_command(uchar dat)delay_n10us(10);lcd_rs=0; /指令lcd_rw=0; /写入lcd_e=1; /允许lcd_db=dat;delay_n10us(10); /lcd_e=0;delay_n10us(10); /*-;模块名称:lcd_write_data();功 能:lcd1602 写数据函数;占用资源: p2.0-rs(lcd_rs),p2.1-rw(lcd_rw),p2.2-e(lcd_e).;参数说明:dat 为写数据参数;-*/void lcd_write_data(uchar dat)delay_n10us(10);lcd_rs=1;/数据lcd_rw=0; /写入lcd_e=1;/允许lcd_db=dat;delay_n10us(10);lcd_e=0;delay_n10us(10);/*-;模块名称:;功 能:显示一个字符;占用资源:-;参数说明:;-*/void lcd_disp_char(uchar x,uchar y,uchar dat)uchar address;if(y=1)address=0x80+x;elseaddress=0xc0+x;lcd_write_command(address);lcd_write_data(dat);/*-;模块名称:;功 能:显示一个字符串。;占用资源:-;参数说明:;-*/void lcd_disp_str(uchar x,uchar y,uchar *str)uchar address;if(y=1)address=0x80+x;elseaddress=0xc0+x;lcd_write_command(address);while(*str!=0)lcd_write_data(*str);str+;/*-;模块名称:delay_n10us();功 能:延时函数,延时约n 个10us;占用资源:-;参数说明:-;-*/void delay_n10us(uint n) /延时n 个10us12m 晶振uint i;for(i=n;i0;i-)_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();/*lcd1602 设置 end*/*主函数*/*void main()while(1)lcd_init();lcd_disp_char(0,1,1+0);/显示一个字符lcd_disp_char(15,1,1+0);/显示一个字符lcd_disp_str(3,1,we are good);/显示字符串delay(500);/延时lcd_disp_str(5,2,partner!);/显示字符串delay(500);/延时*/#includesbit ds = p37;unsigned int temp;void delay()int i , j;for(i=0;i10;i+)for(j=0;j0)i-;ds = 1;i = 4;while(i0)i-;bit tempreadbit(void)unsigned i;bit dat;ds = 0;i+;ds = 1;i+;i+;dat = ds;i = 8;while(i0)i-;return dat;unsigned char tempread(void)unsigned char i,j ,dat;dat = 0;for(i = 1;i=8;i+)j = tempreadbit();dat=(j1);return dat;void tempwritebyte(unsigned char dat)unsigned int i;unsigned char j;bit testb;for(j = 1;j1;if(testb)ds = 0;i+;i+;ds = 1;i = 8;while(i0)i-;elseds = 0;i = 8;while(i0)i-;ds = 1;i+;i+;void tempchange()dsreset();delay();tempwritebyte(0xcc);tempwritebyte(0x44);unsigned get_temp()unsigned char a,b;dsreset();delay();tempwritebyte(0xcc);tempwritebyte(0xbe);a = tempread();b = tempread();temp = b;temp=8;temp = temp | a;return temp;三、元件清单名称数量型号四、安装与调试本设计是先使用proteus软件进行仿真,把各个问题逐一解决后再使用altium designer 把原理图和pcb图做好,最后就是做板、安装、调试。1.电路安装安照电路原理图把元器件安装到已打好的铜板对应的位置,把个元器件固定在铜板后,用导线把对应的元器件的引脚相连接,再用焊锡焊接好即可。注意事项:(1)元器件的布局应尽
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大学生在线学习平台
- 江苏省安全文明施工措施费
- 项目进度汇报及协调通知
- 跨部门协作会议纪要与行动计划
- 高效会议管理技巧与实践指南
- 台风应急预案演练方案
- 项目预算控制表模板(财务部门)
- 可持续发展战略实践分享
- 电子交易系统操作指南
- 办公室职员健康促进措施
- 【可行性报告】2023年水利信息化相关项目可行性研究报告
- 物料承认流程
- 第二章1:公文写作的构成要素
- 单兵队列教学法
- DB14-T 2803-2023 药品委托储存配送管理规范
- 五年级上册猜字谜课件
- 空白试卷模板(可编辑修改word版)
- 第三章生物信息数据库检索及其应用
- 纳兰性德全集
- 数字孪生水利工程建设技术导则(试行)
- 儿童节约用水你我同行3月22日世界水日主题班会PPT
评论
0/150
提交评论