赞
踩
目录
本次设计的多功能时钟系统采用STC89C52单片机为核心器件,利用其定时器/计数器定时和记数的原理,结合液晶显示电路、时钟芯片DS1302电路、电源电路以及按键电路来设计计时器。将软硬件有机地结合起来,使得系统能够实现液晶显示,显示有年、月、日、时、分、秒以及星期,还可以设置闹钟和整点报时。其中软件系统采用单片机汇编语言编写程序,包括显示程序、闹钟程序、中断、延时程序,按键消抖程序等,并在keil中调试运行,硬件系统利用PROTEUS强大的功能来实现,简单且易于观察,在仿真中就可以观察到实际的工作状态。
电路原理设计是基于小系统板包括电源电路、复位电路、按键电路、DS1302时钟电路、液晶显示驱动电路、输出控制电路。电源部分是用电池来提供的3v-5v,晶体振荡器采用的是12MHz的石英晶体振荡器。
整个系统用单片机为中央控制器,由单片机执行采集时钟芯片的时间信号并通过显示模块来输出信号及相关的控制功能。时钟芯片产生时钟信号,利用单片机的I/O口传给单片机;并通过I/O口实现LCD的显示。系统设有4个独立式按键可以对时间年、月、日和星期进行调整,还可以设置闹钟。
STC89C52是一款非常适合单片机初学者学习的单片机,它完全兼容传统的8051,8031的指令系统,他的运行速度要比8051快最高支持达33MHz的晶体震荡器,在此系统中使用12MHz的晶振。
AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。使用Atmel公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。STC89C52具有以下标准功能:8k字节Flash,256字节RAM,32 位I/O 口线,看门狗定时器,2 个数据指针,三个16位定时器/计数器。一个6向量2级中断结构,全双工串行口及时钟电路。另外,STC89C52 可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
STC89C52单片机内部有一个高增益反相放大器,用于构成振荡器,但要形成时钟,外部还需附加电路。XTAL1引脚为反相放大器和时钟发生电路的输入端,XTAL2引脚为反相放大器的输出端。振荡电路如图3.1所示:
片内时钟发生器实质是个2分频的触发其输入来自振荡器的fosc,输出为2相时钟信号,即节拍信号P1、P2,器频率为fosc\2。2个节拍为1个状态时钟S。状态时钟再3分频后为ALE信号,其频率为fosc\6,状态时钟6分频后为机器周期信号,器频率为fosc\12。特殊功能寄存器PCON的PD位可以控制振荡器的工作,当PD=0时,振荡器停止工作,单片机进入低功耗工作状态,复位后,PD=0,振荡器正常工作。时钟电路如图3.2所示:
(1)DS1302是一种可编程的实时时钟芯片,具有计算2100年前的时间的能力,包括时钟/日历寄存器和31字节(8位)的数据暂存寄存器,数据通信权通过一条串行输出口。时钟/日历提供包括秒、分、时、日期、月份和年份信息。闰年可自行调整,以串行方式向单片机传送单字节或多字节的秒、分、时、日、月、年等实时时间数据;只通过三根线进行数据的控制和传递:RST、I/O、SCLK;其在电路的功能是还具有在出现主电源断电时备用电源可继续保持时钟的连续运行。时钟引脚图如图3.4所示:
如果单片机要对DS1302内部寄存器进行读写操作,必须先将与寄存器对应的位操作地址传送给DS1302,然后再进行读写数据的操作。控制寄存器是用来决定能否对DS1302进行读写操作,当控制字的最高位WP=0时,允许进行读写操作;当WP=1时,禁止读写操作。所以单片机对DS1302进行读写操作时,必须先将控制字00H写入到DS1302的控制寄存器中。
LCD显示器能显示数码管不能显示的其他字符、文字和图形,是十分重要的显示终端,LCD1602是字符点阵液晶显示模块。利用LCD1602,所用的时间年、月、日、星期可同时可见,一目了然,采用双行显示,让电子钟能够更直观的显示。其实图如图3.5、显示电路图如图3.6、引脚功能如表3-2所示:
-
- ;初始化
-
- P_Lcd equ P0 ;液晶lcd数据总线
- pq equ p1 ;按键接口
- pf bit p2.0 ;蜂鸣器接口
- led bit p2.1 ;led灯指示接口
- lcdrs bit p2.5 ;lcdrs=1选择数据寄存器,lcdrs=0选择指令寄存器
- lcdrw bit p2.6 ;lcdrw=1进行读操作,lcdrw=0进行写操作
- lcde bit p2.7 ;lcdep由1-->0 时,液晶模块执行命令
- sclk bit p3.5 ;时钟芯片时钟线引脚
- io bit p3.6 ;时钟芯片数据传输线引脚
- rst bit p3.7 ;时钟芯片复位线引脚
- IsSheZhi bit 30h ;设置状态标示位
- BJ bit 31h ;比较标示位
- QH bit 32h ;切换标示位
- bs bit 33h ;报时功能标示位
- cxbs bit 34h ;执行报时标志位
- sec equ 50h
- min equ 51h
- hour equ 52h
- day equ 53h
- week equ 54h
- month equ 55h
- year equ 56h
- KeyCode equ 57h ;按键1功能子程序序号存储地址
- jiepai equ 58h ;存放报时声音的节拍常数
- chuzhi equ 59h ;报时开始秒时间常数
- shengshu equ 5ah ;存放报时声数
- DspBuf equ 60h ;当前时间拆字后存储首地址
- dspba equ 70h ;闹钟时间首地址
- org 0h
- ljmp main
- org 00bh
- ljmp sub1
- org 01bh
- ljmp sub2
- org 30h
-
- ;主程序
-
- main:
- clr IsSheZhi
- clr QH
- setb BJ
- setb bs
- setb cxbs
- mov KeyCode,#00h
- mov sp ,#30h
- mov year,#16h ;为当前时间赋初值
- mov month,#06h
- mov week,#4h
- mov day,#30h
- mov hour,#00h
- mov min,#00h
- mov sec,#00h
- mov DspBuf-1,#0h
- mov DspBuf-2,#02h
- mov jiepai,#80h ;设置节拍常数
- mov chuzhi,#00h ;设置1秒时开始报时
- mov dspba+0,#00h ;为闹钟时间赋初值
- mov dspba+1,#09h
- mov dspba+2,#0h
- mov dspba+3,#0h
- mov TH0,#0ffh
- mov TL0,#0ffh
- mov TH1,#0ffh
- mov TL1,#0ffh
- mov IE,#8aH
- mov TMOD,#11h
- setb pf
- acall lcd_init ;调LCM的初始化程序
- lcall word ;把自创字符写入CGRAM的子程序
- lcall set1302 ;DS1302初始化
- mainloop:
- jb IsSheZhi, SheZhi ;判断是否处于设置状态,处于设置状态则跳转
- lcall get1302 ;调读时间子程序
- lcall chaizi
- lcall display ;调显示子程序,显示当前时间与温度
- SheZhi:
- jb BJ,xq ;判断闹钟功能是否开启,未开启则跳转
- lcall bijiao ;调比较子程序,比较当前时间与闹钟时间
- xq:
- lcall anjian ;按键扫描
- jb bs,bs_1
- lcall zhengshi ;判断当前时间是否是整时,即能否报时
- bs_1:
- jb cxbs,cx_1
- lcall baoshi ;执行报时功能
- cx_1:
- sjmp mainloop
-
- ;液晶显示初始化设定
-
- lcd_init:
- mov a,#01h ;清除LCD的显示内容(清屏)
- acall LcdWrCmd
- mov a,#10 ;10ms延时
- acall delay
- mov a,#38h ;显示模式设置(使用8位数据,显示两行,使用5*7的字型)
- acall LcdWrCmd
- mov a,#10
- acall delay
- mov a,#0ch ;显示开及光标设置(显示器开,光标关,字符不闪烁)
- acall LcdWrCmd
- mov a,#10
- acall delay
- mov a,#06h ;显示光标移动设置(字符不动,光标自动右移)
- acall LcdWrCmd
- mov a,#10
- acall delay
- ret
-
- ;LCM命令嵌入
-
- LcdWrCmd:
- clr LCDRW
- clr LCDRS
- mov P_Lcd, A
- mov a,#6
- acall delay
- setb LcdE
- clr LcdE
- ret
-
- ;LCM数据输入
-
- LcdWrDat:
- setb LCDRS
- clr LCDRW
- mov P_Lcd, A
- mov a,#6
- acall delay
- setb LcdE
- clr LcdE
- ret
-
- ;延时子程序
-
- delay:
- mov r7,a ;设置a为自定义变量,可省去其他延时程序的编写
- d2: mov r6,#250 ;设置1ms延时
- d1:
- nop
- nop
- djnz r6,d1
- djnz r7,d2
- ret
-
- ;ds1302初始化程序set1302
-
- set1302:
- mov a,#8eh ;写ds1302控制寄存器地址
- mov b,#00h ;允许写操作,将WP位设置为低电平
- lcall clockwr
- mov a,#8ch ;写年初值
- mov b,year
- lcall clockwr
- mov a,#88h ;写月初值
- mov b,month
- lcall clockwr
- mov a,#8ah ;写星期初值
- mov b,week
- lcall clockwr
- mov a,#86h ;写日期初值
- mov b,day
- lcall clockwr
- mov a,#84h ;写时初值
- mov b,hour
- lcall clockwr
- mov a,#82h ;写分初值
- mov b,min
- lcall clockwr
- mov a,#80h ;写秒初值
- mov b,sec
- lcall clockwr
- ret
-
- ;读时间子程序get1302
-
- get1302:mov a,#81h ;读秒
- lcall clockrd
- mov sec,a
- mov a,#83h ;读分
- lcall clockrd
- mov min,a
- mov a,#85h ;读时
- lcall clockrd
- mov hour,a
- mov a,#87h ;读日
- lcall clockrd
- mov day,a
- mov a,#8bh ;读星期
- lcall clockrd
- mov week,a
- mov a,#89h ;读月
- lcall clockrd
- mov month,a
- mov a,#8dh ;读年
- lcall clockrd
- mov year,a
- ret
-
- ;ds1302读子程序
- clockrd:clr rst ;rst先设置低电平,再设置高电平,起到去乱码作用
- clr sclk ;sclk置为低电平
- setb rst ;rst置为高电平,选通DS1302
- mov r7,#8 ;串行移位传送次数
- rds1:
- rrc a
- mov io,c ;输出一位寄存器读地址
- setb sclk ;发串行脉冲
- nop
- nop
- clr sclk ;sclk置为低电平
- djnz r7,rds1
- nop ;延时,防后面串行读数据丢失
- nop
- setb io ;8位地址输出完毕,IO设置为输入端口
- mov r7,#8
- rds2:
- mov c,io ;读入一位数据
- rrc a
- setb sclk ;发串行脉冲
- nop
- nop
- clr sclk
- djnz r7,rds2
- clr rst
- setb sclk
- ret
-
- ;ds1302写数据子程序
-
- clockwr:
- push acc ;设置堆栈,入栈
- push b
- clr rst
- clr sclk
- setb rst ;选通DS1302
- mov r7,#8
- wrs1:
- rrc a
- mov io,c ;输出一位寄存器写地址
- clr sclk ;发串行输出脉冲
- setb sclk
- djnz r7,wrs1
- nop
- mov a,b ;将待写入数据送A
- mov r7,#8
- wrs2:
- rrc a
- mov io,c ;经IO输出一位数据
- clr sclk
- setb sclk
- djnz r7,wrs2
- pop b ;出栈
- pop acc
- ret
-
- ;显示设置—— 分配时间显示空间
-
- chaizi:
- mov a,year ;拆年
- mov r0,#60h
- acall hex2bcd
- mov a,month ;拆月
- mov r0,#62h
- acall hex2bcd
- mov a,day ;拆日期
- mov r0,#64h
- lcall hex2bcd
- mov a,week;
- mov 66h,a
- mov a,hour ;拆时
- mov r0,#67h
- lcall hex2bcd
- mov a,min
- mov r0,#69h ;拆分
- lcall hex2bcd
- mov a,sec
- mov r0,#6bh ;拆秒
- acall hex2bcd
- ret
-
- ;显示设置—— 采用除法指令实现的拆字子程序
-
- hex2bcd:
- mov b,a
- anl a,#0f0h
- swap a
- mov @r0,a
- mov a,b
- anl a,#0fh
- inc r0
- mov @r0,a
- ret
-
- ;显示设置——连续显示相邻的两字节
-
- LcdDspBuf:
- mov A, @R0
- orl a,#30h
- acall LcdWrDat
- inc R0
- djnz R2, LcdDspBuf
- ret
-
- ;显示设置——自创字符写入CGRAM的子程序
-
- word:
- mov a,#40h
- lcall LcdWrCmd
- mov r5,#40
- mov dptr,#tab1
- mov r4,#0
- nextt:
- mov a,r4
- movc a,@a+dptr
- lcall LcdWrDat
- inc r4
- djnz r5,nextt
- ret
- tab1:
- db 08h,0fh,12h,0fh,0ah,1fh,02h,00h;年
- db 0fh,09h,0fh,09h,0fh,09h,13h,00h;月
- db 0fh,09h,09h,0fh,09h,09h,0fh,00h;日
- db 06h,0fh,1fh,0fh,07h,1bh,19h,00h;显示闹钟功能开启标示符号
- db 15h,15h,04h,11h,1bh,1fh,0eh,00h;显示报时功能开启标示符号
-
- ;进入闹钟功能设置显示
-
- display_nz:
- mov a,#0c2h
- acall LcdWrCmd ;确定闹钟时间的首地址
- mov R0, #dspba+0
- mov R2, #2
- acall LcdDspBuf ;显示时
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov R0, #dspba+2
- mov R2, #2
- acall LcdDspBuf ;显示时
- jb BJ,XT ;判断闹钟功能是否开启
- mov a,#0c0h
- acall LcdWrCmd
- mov a,#03h ;显示闹钟功能开启标示符号
- acall LcdWrDat
- XT: ret
-
- ;正常显示设置
-
- display:
- mov a,#80h
- acall LcdWrCmd ;指明显示的首地址
- mov R0, #DspBuf-2
- mov R2, #2
- acall LcdDspBuf ;显示年份前两位
- mov R0, #DspBuf+0
- mov R2, #2
- acall LcdDspBuf ;显示年后两位
- mov a,#00h ;显示汉字年
- acall LcdWrDat
- mov R0, #DspBuf+2
- mov R2, #2
- acall LcdDspBuf ;显示月份
- mov a,#01h ;显示汉月字年
- acall LcdWrDat
- mov R0, #DspBuf+4
- mov R2, #2
- acall LcdDspBuf ;显示日期
- mov a,#02h ;显示汉日字年
- acall LcdWrDat
- mov a,#8ch ;w指明星期的首地址
- acall LcdWrCmd
- mov a,#57h
- acall LcdWrDat ;显示w
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov a,66h ;显示星期值
- orl a,#30h
- acall LcdWrDat
- jb bs,XtT ;判断报时功能是否开启
- mov a,#04h ;显示报时功能开启标示符号
- acall LcdWrDat
- XtT:
- mov a,#0c2h
- acall LcdWrCmd ;确定地址
- mov R0, #DspBuf+7
- mov R2, #2
- acall LcdDspBuf ;显示时
- mov a,#3ah ;显示分隔符号
- acall LcdWrDat
- mov R0, #DspBuf+9
- mov R2, #2
- ……………………
-
- …………限于本文篇幅 余下代码请从51黑下载附件…………
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。