单片机仿真课程设计基于单片机的实时时钟.docx

上传人:doc321 文档编号:12890188 上传时间:2021-12-06 格式:DOCX 页数:16 大小:507.89KB
返回 下载 相关 举报
单片机仿真课程设计基于单片机的实时时钟.docx_第1页
第1页 / 共16页
单片机仿真课程设计基于单片机的实时时钟.docx_第2页
第2页 / 共16页
单片机仿真课程设计基于单片机的实时时钟.docx_第3页
第3页 / 共16页
单片机仿真课程设计基于单片机的实时时钟.docx_第4页
第4页 / 共16页
单片机仿真课程设计基于单片机的实时时钟.docx_第5页
第5页 / 共16页
亲,该文档总共16页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《单片机仿真课程设计基于单片机的实时时钟.docx》由会员分享,可在线阅读,更多相关《单片机仿真课程设计基于单片机的实时时钟.docx(16页珍藏版)》请在三一文库上搜索。

1、基于 51 系列单片机及 DS1302 时钟芯片的实时时钟仿真设计 一、课程设计目的意义通过本次课程设计可以灵活运用单片机的基础知识,依据课程设计内容,能够完成从硬 件电路图设计,到软件编程及系统调试实现系统功能,完成课程设计,加深对单片机基 础知识的理解并灵活运用。二、实现目标本设计主要为实现一款可正常显示时钟/日历的实时电子时钟。对当前电子钟开发手段 进行了比较和分析,最终确定了采用单片机技术实现电子时钟。本设计应用 AT89C52 芯片 作为核心,LCD 显示屏,使用 DS1302 实时时钟日历芯片完成时钟/日历的基本功能。这种 实现方法的优点是电路简单,性能可靠,实时性好,时间精确,操

2、作简单,编程容易。 三、硬件设计本设计采用具有 32 根 I/O 引脚的 AT89C52 单片机。AT89C52 单片机是一款低功耗,低 电压,高性能 CMOS 8 位单片机,片内含 4KB(可经受 1000 次擦写周期)的 FLASH 可编程可 反复擦写的只读程序存储器(EPROM),器件采用 CMOS 工艺和 ATMEI 公司的高密度、非易失 性存储器(NURAM)技术制造,其输出引脚和指令系统都与 MCS-52 兼容。片内的 FLASH 存储 器允许在系统内可改编程序或用常规的非易失性存储器编程器来编程。因此, AT89C52 是 一种功能强,灵活性高且价格合理的单片机,可方便的应用在各

3、个控制领域。AT89C52 具有以下主要性能:1. 4KB 可改编程序 Flash 存储器;2. 全静态工作:024Hz;3. 128×8 字节内部 RAM;4. 32 个外部双向输入/输出(I/O)口;5. 6 个中断优先级; 2 个 16 位可编程定时计数器;6. 可编程串行通道;7.片内时钟振荡器。DS1302 是美国 DALLAS 公司推出的一种高性能、低功耗的实时时钟日历芯片,附加 31 字节静态 RAM,采用 SPI 三线接口与 CPU 进行同步通信,并可采用突发方式一次传送多个字1 / 9节的时钟信号和 RAM 数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月

4、小于 31 天时可以自动调整,且具有闰年补偿功能。工作电压宽达 2.55.5V。采用双 电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后备电源进行涓 细电流充电的能力。有主电源和备份电源双引脚,而且备份电源可由大容量电容(1F) 来替代。需要强调的是,DS1302 需要使用 32.768KHz 的晶振。四、原理图五、程序源代码#include <REGX52.H>#include "LCD1602.h"#include "DS1302.h"void Delay1ms(unsigned int count)unsigned in

5、t i,j;for(i=0;i<count;i+)for(j=0;j<120;j+);main()2 / 9SYSTEMTIME CurrentTime;LCD_Initial();Initial_DS1302();GotoXY(0,0);Print("Date: ");GotoXY(0,1);Print("Time: ");while(1)DS1302_GetTime(&CurrentTime);DateToStr(&CurrentTime);TimeToStr(&CurrentTime);GotoXY(6,0);P

6、rint(CurrentTime.DateString);GotoXY(6,1);Print(CurrentTime.TimeString);Delay1ms(300);#ifndef _REAL_TIMER_DS1302#define _REAL_TIMER_DS1302sbit DS1302_CLK = P16; / 实时时钟时钟线引脚 sbit DS1302_IO = P17; / 实时时钟数据线引脚 sbit DS1302_RST = P15; / 实时时钟复位线引脚 sbit ACC0 = ACC0;sbit ACC7 = ACC7;typedef struct _SYSTEMTIM

7、E_unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString9;3 / 9unsigned char TimeString9; SYSTEMTIME;/定义的时间类型#define AM(X) X#define PM(X) (X+12)#define DS1302_SECOND 0x80#define DS1302_MINUTE 0

8、x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define DS1302_RAM(X)(0xC0+(X)*2)void DS1302InputByte(unsigned char d)unsigned char i;ACC = d;for(i=8; i>0; i-)/ 转成 24 小时制/用于计算 DS1302_RAM 地址的宏/实时时钟写入一字节(内部函数)DS1302_IO = ACC

9、0; /相当于汇编中的 RRC DS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;unsigned char DS1302OutputByte(void)unsigned char i;for(i=8; i>0; i-)/实时时钟读取一字节(内部函数)ACC = ACC >>1; /相当于汇编中的 RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;return(ACC);void Write1302(unsigned char ucAddr, unsigned char uc

10、Da) /ucAddr: DS1302 地址, ucData: 要写的数据DS1302_RST = 0;4 / 9DS1302_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;D

11、S1302_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(unsigned char Address, unsigned char Value) DS130

12、2_SetProtect(0);Write1302(Address, (Value/10)<<4 | (Value%10);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 = (Read

13、Value&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_HOUR);Time->Hour = (ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);5 / 9/ 设置时间函数ReadValue = Read1302(DS1302_DAY);Time->Day = (ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(

14、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&0x

15、0F); void DateToStr(SYSTEMTIME *Time)Time->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->D

16、ateString5 = '-' 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&

17、#39; 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' T

18、ime->DateString8 = '0'void Initial_DS1302(void)unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80)DS1302_SetTime(DS1302_SECOND,0);#endif6 / 9#ifndef LCD_CHAR_1602#define LCD_CHAR_1602#include <intrins.h>/Port Definitionssbit LcdRs = P20;sbit LcdRw = P21;sbit LcdEn = P22

19、;sfr DBPort = 0x80; /P0=0x80,P1=0x90,P2=0xA0,P3=0xB0. 数据端口/内部等待函数unsigned char LCD_Wait(void)LcdRs=0;LcdRw=1;_nop_();LcdEn=1; _nop_();/while(DBPort&0x80);/在用 Proteus 仿真时,注意用屏蔽此语句,在调用 GotoXY()时, 会进入死循环,/ 可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80=0x80/实际硬件时打开此语句LcdEn=0;return DBPort;/向 LCD 写入命令或数据#

20、define LCD_COMMAND 0 / Command#define LCD_DATA 1 / Data#define LCD_CLEAR_SCREEN 0x01 / 清屏#define LCD_HOMING 0x02 / 光标返回原点void LCD_Write(bit style, unsigned char input)LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();/注意顺序LcdEn=1; _nop_();/注意顺序LcdEn=0; _nop_();LCD_Wait();7 / 9/设置显示模式 #defin

21、e LCD_SHOW#define LCD_HIDE#define LCD_CURSOR#define LCD_NO_CURSOR0x04 /显示开0x00 /显示关0x02 /显示光标 0x00 /无光标#define LCD_FLASH 0x01 /光标闪动#define LCD_NO_FLASH 0x00 /光标不闪动void LCD_SetDisplay(unsigned char DisplayMode)LCD_Write(LCD_COMMAND, 0x08|DisplayMode);/设置输入模式#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0

22、x00 / default#define LCD_MOVE 0x01 / 画面可平移#define LCD_NO_MOVE 0x00 /defaultvoid LCD_SetInput(unsigned char InputMode)LCD_Write(LCD_COMMAND, 0x04|InputMode);/初始化 LCDvoid LCD_Initial()LcdEn=0;LCD_Write(LCD_COMMAND,0x38); /8 位数据端口,2 行显示,5*7 点阵 LCD_Write(LCD_COMMAND,0x38); LCD_SetDisplay(LCD_SHOW|LCD_NO

23、_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);8 / 9if(y=1)LCD_Write(LCD_COMMAND,0x80|(x-0x40);void Print(unsigned char *str)while(*str!='0')LCD_Write(LCD_DATA,*str);str+;#endif六、仿真结果七、实验心得通过本次课程设计,我不仅加深了对单片机理论的理解,而且能够完成从硬件电路 图设计,到软件编程及系统调试实现系统功能这一流程。还学会了如何应用proteus 进 行仿真,应用 keil 软件进行编程,加深了对 51 系列单片机的理解。在本次课程设计中遇到了一连串的问题,经过同学们的帮助,最终完成了本次课程 设计,我不仅学会了如何将所学的理论知识和实际结合起来,也学会了和他人的合作, 而且锻炼了我的实践能力。9 / 9

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1