基于51单片机和DS1302数字时钟
硬件总体
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
说明
书
关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf
编制单位:*****
作 者:*****
版 本:V1.0
发布日期:2011-2-12
目录
一、引言-----------------------------------------------1
1.1编写目的-----------------------------------------1
1.2背景---------------------------------------------1
1.3参考资料-----------------------------------------1
二、总体设计--------------------------------------------3
2.1设计与运行环境------------------------------------3
2.2硬件功能描述--------------------------------------3
三、数字钟软件和硬件设计-------------------------------3
3.1 硬件电路设计-------------------------------------3
3.1.1电源---------------------------------------3
3.1.2独立按键模块-------------------------------3
3.1.3显示模块------------------------------------4
3.1.4复位电路模块--------------------------------4
3.1.5时钟芯片模块--------------------------------5
3.1.6主控模块------------------------------------5
3.1.7闹铃模块------------------------------------6
3.2软件设计--------------------------------------------6
3.2.1程序设计
流程
快递问题件怎么处理流程河南自建厂房流程下载关于规范招聘需求审批流程制作流程表下载邮件下载流程设计
图-------------------------------6
3.2.2 源程序--------------------------------------8
四、数字钟制作过程中遇到的问题-------------------------19
五、总结-----------------------------------------------20
附录Ⅰ:DS1302时钟芯片的工作原理和使用方法-----------22
附录Ⅱ:如何利用软件减小的计时误差--------------------25
一、引言
1.1编写目的
为了进一步熟悉51单片机的编程以及学习数字钟的相关设计方法,在老师的指导下我们进行了本次数字钟的设计。
我们在寒假利用10天的时间里基于51单片机——STC89C52单片机和时钟芯片DS1302设计并实现了数字时钟。在PCB板制作完成并且调试成功之际,为了进一步提高自己和动手能力和编程能力,对这次数字钟的设计和制作的过程中遇到的问题及设计思路做一总结。
1.2背景
随着人们生活水平的提高和生活节奏的加快,对时间的要求越来越高,精准数字计时的消费需求也是越来越多。
二十一世纪的今天,最具代表性的计时产品就是电子万年历,它是近代世界钟表业界的第三次革命。第一次是摆和摆轮游丝的发明,相对稳定的机械振荡频率源使钟表的走时差从分级缩小到秒级,代表性的产品就是带有摆或摆轮游丝的机械钟或表。第二次革命是石英晶体振荡器的应用,发明了走时精度更高的石英电子钟表,使钟表的走时月差从分级缩小到秒级。第三次革命就是单片机数码计时技术的应用(电子万年历),使计时产品的走时日差从分级缩小到1/600万秒,从原有传统指针计时的方式发展为人们日常更为熟悉的夜光数字显示方式,直观明了,并增加了全自动日期、星期、温度以及其他日常附属信息的显示功能,它更符合消费者的生活需求!因此,电子万年历的出现带来了钟表计时业界跨跃性的进步……
我国生产的电子万年历有很多种,总体上来说以研究多功能电子万年历为主,使万年历除了原有的显示时间,日期等基本功能外,还具有闹铃,报警等功能。商家生产的电子万年历更从质量,价格,实用上考虑,不断的改进电子万年历的设计,使其更加的具有市场。
除了采用集成化的时钟芯片外,还有采用MCU的
方案
气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载
,利用STC89系列单片微机制成万年历电路,采用软件和硬件结合的方法,控制LED数码管输出,分别用来显示年、月、日、时、分、秒,其最大特点是:硬件电路简单,安装方便易于实现,软件设计独特,可靠。
在21世纪的今天,单片机仍然有着它不可替代的地位和独特的作用在学完单片机后,为了进一步学习51单片机的控制和编程,我们利用51单片机自己设计并制作数字钟。
1.3参考资料
【1】8051系列单片机C程序设计完全手册 求是科技 编著
人民邮电出版社 2006
【2】51单片机应用从零开始 杨欣 编著 清华大学出版社 2008
【3】单片机原理及接口技术(第三版) 李朝青 编著 北京航空航天大学出版社 2008
【4】51单片机C语言教程 郭天祥 编著 电子工业出版社 2009
二、总体设计
此数字钟利用单片机STC89C52和时钟芯片DS1302设计完成。
2.1设计与运行环境
数字钟的程序设计和调试均在Keil uVision2环境下完成的。设计并完成的程序下载至STC89C52单片机后,即可初始化时钟芯片DS1302从而开始计时,系统开始正常运行。
2.2硬件功能描述
数字钟能够完成24小时制计时,计时初始化值为00:00:00,用户可以通过按键调整时钟的初值实现校时功能,并且可以通过按键设定一个24小时以内任意时刻的闹铃,用户可以手动选择闹铃的开或者关两种状态。
三、数字钟软件和硬件设计
3.1 硬件电路设计
数字钟的电路主要有电源模块、显示模块、按键模块、复位电路模块、时钟芯片模块、主控芯片STC89C52模块和闹铃模块等7大模块组成。
3.1.1电源
电源模块采用7805进行稳压,保证+5V电压的稳定输出,进一步提高系统的抗干扰能力和稳定性。
3.1.2独立按键模块
系统有三个独立按键,独立按键S1、S2、S3分别接至单片机P3.2、P3.3、P3.4口。
S1用来功能选择,其功能可以用按键次数N来表示:
N=1:校准计时的小时位 N=2:校准计时的分钟位
N=3:校准闹铃的小时位 N=1:校准闹铃的分钟位
N=5:退出
S2主要功能用来进行加一操作。在有功能选择的情况下,无论选中那一种功能操作,按下S2即进行一次加一操作,在没有功能选择的情况下,系统不响应此按键的任何操作。
S3用来控制闹铃的开或者关,在任意时间只要按下此键即可打开(或关闭)闹铃,在按键一次就可以关闭(或打开)闹铃。
3.1.3显示模块
一个良好的显示模块对一个系统非常重要,所有操作结果和计时结果,都要通过显示模块来显示出来。同时显示模块提供了良好的人机交互平台。常用的显示模式有LED 7段数码管显示、点阵显示和液晶显示。
液晶显示屏(LCD)具有轻薄短小、低耗电量、无辐射危险,平面直角显示以及影象稳定不闪烁等优势,可视面积大,画面效果好,分辨率高,抗干扰能力强等特点。但由于液晶其成本也偏高。在使用时,不能有静电干扰,否则易烧坏液晶的显示芯片。鉴于LED 7段数码管成本低,也比较容易实现的特点,最终确定使用共阴极数码管来显示。
本系统显示模块电路由一块74HC573、一块74HC138芯片和两个四位一体7段数码管组成。74HC573用来驱动数码管,74HC573的Q0~Q7分别接四位一体数码管的A~dp。74HC138控制位选。
3.1.4复位电路模块
复位电路主要的功能是是整个系统初始化,在每次上电时系统自动初始化,如果在程序运行的过程中程序没有响应或者需要进行一次初始化,这是可以通过按复位开关来实现需要的有效操作。
3.1.5时钟芯片模块
DS1302时钟芯片是本系统实现高精度计时的关键。利用DS1302时钟芯片独立于单片机来计时,在提高计时进度的同时也提高了整个系统的抗干扰能力。DS1302通过SCLK、I/O、RES端口和单片机STC90C52进行通信。SCLK接至单片机P1.7口,在读写操作时给DS1302提供相应的时钟脉冲;I/O接至P3.5用来传送所有的数据;RES接至单片机P1.6上用来控制单片机与时钟芯片间的数据传送的开始于结束。
DS1302的工作原理及使用方法见附录Ⅰ。
3.1.6主控模块
主控模块的核心组成部分是单片机STC89C52, 承担着所有操作任务的调控与分派工作。
3.1.7闹铃模块
闹铃模块由蜂鸣器和蜂鸣器的驱动组成。在有闹铃发生的时候,蜂鸣器的驱动电路驱动蜂鸣器发声,产生闹铃的效果。
3.2软件设计
3.2.1程序设计流程图
1、主程序流图
2、读DS1302中断及闹铃检测流程图
3、功能选择中断操作的程序流程图
4、加一中断操作的程序流程图
3.2.2 源程序
/* 本程序主要实现的功能:
利用时钟芯片DS1302和STC89C52进行高精度计时,能够实现时、分、秒的显示,具有校时,调整闹铃的功能。
设计者:**** 2011/1/24 */
ORG 0000H
SJMP MAIN ;主程序入口地址
ORG 0003H
AJMP ANJIAN_FUNCTION ;功能选择操作入口
ORG 000BH
AJMP DELAY_10MS ;防抖延时以及闹铃
ORG 0013H
AJMP COUNT_UP ;按键加1操作入口
ORG 001BH
AJMP DU_1302 ;每300ms读ds1302中断入口
MAIN:
T_CLK BIT P1.7;实时时钟
T_IO BIT P3.5 ;数据线
T_RST BIT P1.6 ;复位线
MOV TMOD,#11H
MOV TH1,#15H ;设置扫描ds1302的计数初值
MOV TL1,#0A0H
MOV TH0,#0C5H ;设置按键防抖延时
MOV TL0,#68H
SEC0 DATA 40H ;定义秒显示的个位
SEC1 DATA 41H ;定义秒显示的十位
LINE0 DATA 42H ;定义秒-时分隔符
MIN0 DATA 43H ;定义分显示个位
MIN1 DATA 44H ;定义分显示十位
LINE1 DATA 45H ;定义时-分分隔符
HOUR0 DATA 46H ;定义时显示个位
HOUR1 DATA 47H ;定义时显示十位
;--------预读计数位寄存器-----------
SECOND DATA 52H ;秒寄存器,用于暂存当前由DS1302读的的秒的数据
MINUTE DATA 53H ;分-用于暂存当前由DS1302读的的分的数据
HOUR DATA 54H ;时-用于暂存当前由DS1302读的的时的数据
SMJS DATA 55H ;设置ds1302 扫描定时控制位(扫描计数)
FUNC DATA 56H ;定义按键功能选择控制位
ZANCUN0 DATA 57H ;定义按键操作时存储校准值的个位
ZANCUN1 DATA 58H ;定义按键操作时存储校准值的十位
ZANCUN_SECOND DATA 59H ;用于校时和对闹铃时对秒的显示值清零
NLHOUR_0 DATA 60H ;闹铃小时值存储单元
NLMINUTE_0 DATA 61H ;闹铃分值存储单元
;NLHOUR_1 DATA 62H
;NLMINUTE_1 DATA 63H
TEMP DATA 64H ;闹铃发生标志位
NLJS DATA 65H ;闹铃计时标志
MOV TEMP,#00H ;闹铃发生标志位初始化为0,表示没有闹铃的发生
MOV NLJS,#00H ;闹铃铃声长短控制单元
MOV NLHOUR_0,#08H ;闹铃符初值
MOV NLMINUTE_0,#30H
MOV LINE0,#40H ;显示分和秒的间隔符
MOV LINE1,#40H ;显示小时和分的间隔符
MOV SMJS,#00H
MOV SECOND,#00H ;时钟计时初始化值
MOV MINUTE,#25H
MOV HOUR,#08H
MOV ZANCUN_SECOND,#00H
MOV R1,#40H ;--------------------------------R1
MOV R3,#07H ;确定当前选通的显示位 ------R3
SETB EX0
SETB IT0 ;外部中断葿边沿触发
SETB IT1
SETB ET0
SETB ET1
SETB PT0 ;设置定时器T0中断位高优先级
SETB PX1 ;外部中断1中断为高优先级,用来在有功能操作
;时来中断功能选择的中断
SETB EA ;开总中断
SETB TR1 ;T1主要进行显示扫描中断
LCALL SET1302 ;DS1302初始化
;--------------------数码管显示程序------------------
XIANSHI:
;-----检测闹铃是否发生-------------------------
MOV ZANCUN0,R6
PUSH ZANCUN0 ;R6压栈
MOV R6,TEMP
CJNE R6,#01H,XIANSHI_1 ;检测闹零定时是否到时
SETB TR0 ;
XIANSHI_1:MOV A,@R1 ;读计数位的计数值----R1
CJNE R3,#05H,NEXTWEI ;判断当前为是否需要显示分隔符"-"
MOV P2,R3
MOV P0,LINE0
NEXTWEI:CJNE R3,#02H,SEL_0
MOV P2,R3
MOV P0,LINE1
SEL_0:MOV P2,R3 ;送位选信号
/*--对计数位的计数值译码输出--开始-*/
CJNE A,#00H,SEL_1
MOV P0,#3FH ;0,如果当前计数位的计数值位0,则将0的共阴极七段数码管编码3FH送出显示
SJMP SEL_10
SEL_1: CJNE A,#01H,SEL_2
MOV P0,#06H ;1
SJMP SEL_10
SEL_2: CJNE A,#02H,SEL_3
MOV P0,#5BH ;2
SJMP SEL_10
SEL_3: CJNE A,#03H,SEL_4
MOV P0,#4FH ;3
SJMP SEL_10
SEL_4: CJNE A,#04H,SEL_5
MOV P0,#66H ;4
SJMP SEL_10
SEL_5: CJNE A,#05H,SEL_6
MOV P0,#6DH ;5
SJMP SEL_10
SEL_6: CJNE A,#06H,SEL_7
MOV P0,#7DH ;6
SJMP SEL_10
SEL_7:CJNE A,#07H,SEL_8
MOV P0,#07H ;7
SJMP SEL_10
SEL_8:CJNE A,#08H,SEL_9
MOV P0,#7FH ;8
SJMP SEL_10
SEL_9:CJNE A,#09H,SEL_10
MOV P0,#6FH ;9
SJMP SEL_10
/*--对计数位的计数值译码输出--结束-*/
SEL_10: INC R1 ;R1加一,使当前计数位后移一位
DEC R3 ;位扫描控制位减一,因为初始位扫描是从111开始的
ACALL DELAY
CJNE R3,#0FFH,SEL_11
MOV R3,#07H
SEL_11:CJNE R1,#48H,SEL_12
MOV R1,#40H
SEL_12: POP ZANCUN0
MOV R6,ZANCUN0
AJMP XIANSHI
;---------------------扫描延时程序--------
DELAY:
MOV R5,#4 ;----------------R5
D1: MOV 48H,#120
DJNZ 48H,$
DJNZ R5,D1
RET
;--功能:对当前由ds1302读得的计数值进行转换--- (寄存器均已压栈)---
JSZH: ;功能:计数转换子程序,用于对当前读得的ds1302的计数值转换成sec0-houro的格式,便于显示
PUSH ACC
MOV A,R0
PUSH ACC ;R0压栈
MOV A,R1
PUSH ACC ;R1压栈
PUSH PSW
MOV R1,#40H ;计数数据sec0---hour0的存储首地址
MOV R0,#52H ;由ds1302读得的数据存放首地址
LOOP_1:MOV A,@R0
ANL A,#0FH
MOV @R1,A
INC R1
MOV A,@R0
ANL A,#0F0H
SWAP A
MOV @R1,A
INC R1
INC R1 ;地址加一跳过分隔符"_"的存储单元
INC R0
CJNE R1,#49H,LOOP_1
POP PSW
POP ACC ;R1弹栈
MOV R1,A
POP ACC ;R0弹栈
MOV R0,A
POP ACC ;A弹栈
RET
;-------读取DS1302计数程序(T1中断)----- --(寄存器均已压栈)
DU_1302:
PUSH ACC
MOV A,R1
PUSH ACC ;R1压栈
DU_1302_1:
INC SMJS
MOV R1,SMJS
CJNE R1,#03H,BELL ;每300ms读一次ds1302的计数值,避免在ds1302定时一秒
;计数值改变时发生错读
MOV SMJS,#00H
LCALL GET1302
LCALL JSZH ;调计数转换子程序
MOV TH1,#15H ;设置扫描ds1302的计数60MS初值
MOV TL1,#0A0H
BELL: ;-------------闹铃----------------
MOV A,NLHOUR_0
CJNE A,HOUR,DU_1302_RET
MOV A,NLMINUTE_0
CJNE A,MINUTE,DU_1302_RET
MOV TEMP,#01H ;定义TEMP为闹铃发生的标志
MOV NLMINUTE_0,#00H
MOV NLHOUR_0,#00H
DU_1302_RET:
POP ACC
MOV R1,A ;R1弹栈
POP ACC
RETI
;************ DS1302初始化子程序 ************************************
SET1302: ;设置ds1302初始时间,并启动计时
PUSH ACC ;A断点保护
MOV A,R1
PUSH ACC
CLR T_RST
CLR T_CLK
SETB T_RST
MOV B,#8EH ;控制寄存器
LCALL WRITEBYTE
MOV B,#00H ;写操作前WP=0
LCALL WRITEBYTE
SETB T_CLK
CLR T_RST
mov R0,#SECOND
MOV R7,#3 ;秒/时/分 ;-----R7
MOV R1,#80H ;秒写地址 ;-----R1
S1302:
CLR T_RST
CLR T_CLK
SETB T_RST
MOV B,R1 ;写秒/时/分地址 ;---R1
LCALL WRITEBYTE
MOV A,@R0 ;写秒数据 ;-----R0
MOV B,A
LCALL WRITEBYTE
INC R0
INC R1
INC R1
SETB T_CLK
CLR T_RST
DJNZ R7,S1302
CLR T_RST
CLR T_CLK
SETB T_RST
MOV B,#8EH ;控制寄存器
LCALL WRITEBYTE
MOV B,#80H;控制,wp=1,写保护
LCALL WRITEBYTE
SETB T_CLK
CLR T_RST
POP ACC
MOV R1,A
POP ACC ;A恢复数据
RET
;-------------------------------------
GET1302: ;从ds1302读时间秒/时/分
MOV R0,#SECOND ;------R0
MOV R7,#03H ;-----R7
MOV R2,#81H ;-----R2
G13021:CLR T_RST
CLR T_CLK
SETB T_RST
MOV B,R2
LCALL WRITEBYTE ;写操作时,将一字节的内容由B写至DS1302中
LCALL READBYTE ;读操作时,将一字节的内容读至A中
MOV @R0,A
INC R0
INC R2
INC R2
SETB T_CLK
CLR T_RST
DJNZ R7,G13021
RET
;--------------------------------------------
WRITEBYTE: ;写B寄存器中的内容至1302一字节
MOV R4,#08H ;------R4
INBIT1:MOV A,B
RRC A
MOV B,A
SETB T_IO ;T_IO口做输入口
MOV T_IO,C
SETB T_CLK
CLR T_CLK
DJNZ R4,INBIT1
RET
;-------------------------------------------
READBYTE: ;读1302一字节至 A 寄存器
MOV R4,#8 ;----R4
OUTBIT1:MOV C,T_IO
RRC A
SETB T_CLK
CLR T_CLK
DJNZ R4,OUTBIT1
RET
;---------- ----------END DS0302--------------------------------
;****** **************按键操作*********************
ANJIAN_FUNCTION: ;功能选择键中断 接至P3.2
WAIT:JB P3.2,WAIT
SETB TR0 ;启动定时器0,延时10ms
JNB TF0,$
JNB P3.2,$ ;检测按键是否弹起
SETB EX1 ;在有功能选择的时候开中断1
INC FUNC
PUSH ACC ;保存A中的数值
MOV A,FUNC
CJNE A,#03H,FUN_1
MOV LINE0,#80H ; 分隔符下移,以便区分于校时操作
MOV LINE1,#80H
FUN_1:CJNE A,#04H,FUN_2
MOV LINE0,#80H ; 分隔符下移,以便区分于校时操作
MOV LINE1,#80H
FUN_2:CJNE A,#05H,ANJIAN_FUNCTION_RET ;控制所要置数的计数位闪动
SETB ET1
CLR EX1 ;在功能选择的时退出开中断1
MOV FUNC,#00H
MOV LINE0,#40H ;显示分和秒的间隔符
MOV LINE1,#40H ;显示小时和分的间隔符
ANJIAN_FUNCTION_RET:
POP ACC ;恢复A中的值
RETI
;-------------校时加--中断-----------------------------------------
COUNT_UP:
PUSH ACC
MOV A,FUNC
CLR C
SUBB A,#00H ;检测当前有无校时或者对闹铃的操作
CJNE A,#00H,COUNT_UP_NEXT
AJMP COUNT_UP_RET
;*****************时********************
COUNT_UP_NEXT:
CJNE A,#01H,COUNT_UP_1 ;检测当前操作是否为时钟校时--时钟位
INC HOUR0
MOV R6,HOUR1 ;校时------------------R6
CJNE R6,#02H,COUNT_UP_0_1 ;先判断小时高位是否已计数值2
MOV R6,HOUR0
CJNE R6,#04H,COUNT_UP_RET
MOV HOUR1,#00H
MOV HOUR0,#00H
AJMP COUNT_UP_RET ;返回
COUNT_UP_0_1: MOV R6,HOUR0
CJNE R6,#0AH,COUNT_UP_RET
MOV HOUR0,#00H
INC HOUR1
AJMP COUNT_UP_RET
;***************分****************************
COUNT_UP_1:
CJNE A,#02H,COUNT_UP_2 ;校时---分
INC MIN0
MOV R6,MIN0
CJNE R6,#0AH,COUNT_UP_1_1 ;先判断分的低位
INC MIN1
MOV MIN0,#00H
COUNT_UP_1_1: MOV R6,MIN1
CJNE R6,#06H,COUNT_UP_RET
MOV MIN1,#00H
;SJMP COUNT_UP_RET
COUNT_UP_RET:
LCALL HECHENG
MOV SECOND,ZANCUN_SECOND ;每次校时秒都归零
LCALL SET1302 ;每加一次对当前计数值进行一次重置
POP ACC
RETI
COUNT_UP_2:
CJNE A,#03H,COUNT_UP_3 ;闹铃---时
CLR ET1 ;暂停对DS1302的读操作
MOV R6,HOUR1 ;时------------------------R6
CJNE R6,#02H,COUNT_UP_2_1 ;先判断小时高位是否已计数值2
INC HOUR0
MOV R6,HOUR0
CJNE R6,#04H,COUNT_UP_NLRET
MOV HOUR1,#00H
MOV HOUR0,#00H
AJMP COUNT_UP_NLRET ;返回
COUNT_UP_2_1: INC HOUR0
MOV R6,HOUR0
CJNE R6,#0AH,COUNT_UP_NLRET
MOV HOUR0,#00H
INC HOUR1
SJMP COUNT_UP_NLRET
COUNT_UP_3:CJNE A,#04H,COUNT_UP_RET ;闹铃---分
CLR ET1 ;暂停对DS1302的读操作
INC MIN0
MOV R6,MIN0
CJNE R6,#0AH,COUNT_UP_3_1 ;先判断分的低位
INC MIN1
MOV MIN0,#00H
COUNT_UP_3_1:MOV R6,MIN1
CJNE R6,#06H,COUNT_UP_NLRET
MOV MIN1,#00H
COUNT_UP_NLRET:
LCALL HECHENG
POP ACC
RETI
;*********** 有按键时重置ds1302当前位计数值(R5) **************
;功能:将当前时,分的高低显示计数值分别合成为HOUR,MINUTE,对校时时ds1302重新写入数据做准备
HECHENG: ;---------------R0,A
PUSH ACC ;对R0的值压栈
MOV A,FUNC
CLR C
SUBB A,#00H ;检测当前有无校时或者对闹铃的操作
CJNE A,#01H,HECHENG_1
MOV ZANCUN0,HOUR0
MOV ZANCUN1,HOUR1
ANL ZANCUN0,#0FH
ANL ZANCUN1,#0FH
MOV R5,A ;保存A中的值
MOV A,ZANCUN1
SWAP A
ADD A,ZANCUN0
MOV HOUR,A
MOV A,R5 ;恢复A的计数值
SJMP HECHENG_RET
HECHENG_1:
CJNE A,#02H,HECHENG_2
MOV ZANCUN0,MIN0
MOV ZANCUN1,MIN1
ANL ZANCUN0,#0FH
ANL ZANCUN1,#0FH
MOV R5,A ;保存A中的值
MOV A,ZANCUN1
SWAP A
ADD A,ZANCUN0
MOV MINUTE,A
MOV A,R5 ;恢复A的计数值
SJMP HECHENG_RET
HECHENG_2:
CJNE A,#03H,HECHENG_3 ;闹----时
MOV ZANCUN0,HOUR0
MOV ZANCUN1,HOUR1
ANL ZANCUN0,#0FH
ANL ZANCUN1,#0FH
MOV R5,A ;保存A中的值
MOV A,ZANCUN1
SWAP A
ADD A,ZANCUN0
MOV NLHOUR_0,A
MOV A,R5 ;恢复A的计数值
SJMP HECHENG_RET
HECHENG_3:
CJNE A,#04H,HECHENG_RET ;闹--分
MOV ZANCUN0,MIN0
MOV ZANCUN1,MIN1
ANL ZANCUN0,#0FH
ANL ZANCUN1,#0FH
MOV R5,A ;保存A中的值
MOV A,ZANCUN1
SWAP A
ADD A,ZANCUN0
MOV NLMINUTE_0,A
MOV A,R5 ;恢复A的计数值
HECHENG_RET:POP ACC
RET
;-----------T0防抖延时10ms----------------------------------
DELAY_10MS:
PUSH ACC
MOV A,R6
PUSH ACC
MOV R6,TEMP
CJNE R6,#01H,DELAY_FD ;如果没有闹铃事件发生转防抖延时DELAY_FD
INC NLJS
MOV TH0,#0ECH
MOV TL0,#78H
CPL P1.0
MOV R6,NLJS
CJNE R6,#0FFH,DELAY_RET ;
MOV TEMP,#00H
MOV NLJS,#00H
MOV TH0,#0D1H ;恢复T0的初值
MOV TL0,#20H
CLR P1.0
CLR TR0 ;T0复用结束后关定时器
SJMP DELAY_RET
DELAY_FD:
MOV TH0,#0C5H
MOV TL0,#68H
CLR TR0
DELAY_RET:
POP ACC
MOV R6,A
POP ACC
RETI
END
四、数字钟制作过程中遇到的问题
问题一:对于时钟的各个计时单元:时、分、秒,由于单片机内部的寄存器资源有限,在程序设计的开始首先必须得解决由时钟芯片DS1302读得的数据如何保存的问题。
解决办法:由于我使用的编程语言是汇编语言,不能像C语言那样使用一个数组来保存数据。为了能够及时的保存数据,在程序设计的过程中使用DATA指令在单片机的内存空间中开辟出了一些具有固定地址的内存单元来存储相应的数据。在程序中定义的用于保存当前由DS1302读得的数据单元如下:
SEC1 DATA 41H ;定义秒显示的十位
SEC0 DATA 40H ;定义秒显示的个位
LINE0 DATA 42H ;定义秒-时分隔符“-”
MIN0 DATA 43H ;定义分显示个位
MIN1 DATA 44H ;定义分显示十位
LINE1 DATA 45H ;定义时-分分隔符“-”
HOUR0 DATA 46H ;定义时显示个位
HOUR1 DATA 47H ;定义时显示十位
通过以上的方法,在单片机的RAM中开辟了一片用户可直接操作的内存单元,解决例如数据的保存问题。
问题二:焊接好自己刻的板子后,数码管显示跳动不稳定,但时钟没停,但有时走一分钟后就停掉了。
解决方法:将写好的程序下在51开发板上,发现程序运行稳定,没有上述现象的发生。由此首先说明程序没有问题,可能是做的电路板有问题,为了找到问题的根源所在,从开发板上引出了时钟芯片的输出信号接至自己做的电路板,发现电路板能正常工作。由此推断问题的根源出在电路板的时钟芯片模块,经过进一步的排查,发现在时钟芯片在没有接地的情况下竟然能够正常工作。由此进一步说明问题是出在时钟芯片的接地上。
为了能够进一步寻找问题根源,我们将自己刻的电路板的地线接至示波器上观察。结果证明了我们的推断完全正确,为了最大程度的降低干扰,我们直接对DS1302单独接地,并且对数码管驱动芯片74HC573等需较大电流的芯片单独接电源,同时划断电路板中对74HC573等供电的电源线路以进一步降低电源带来的干扰。
问题总结:由于我们是第一次做PCB板,在布局的时候根本没有考虑到布线的不合理会带来的众多干扰的问题,而且布线也全部由电脑自动布线完成,这样使得电路滋生出大量的寄生电容以及其他的干扰。同样的程序在开发板上运行很稳定,在我们自己刻的PCB板上刚开始很不稳定进一步告诉我们,在以后绘制PCB板的过程中需要周密的考虑到布局的合理性以及电路的干扰问题。
问题三:在程序设计完成后,在开发板和自己刻的PCB板上时发现再有按键按下的情况下,数码管所显示时间有闪动。
解决方法:因为单片机是一个顺序执行程序微机,不像CPLD或FPGA等具有并行处理数据的特点,CPU在当前时间只能处理一件事。在开始我以为产生这个问题的原因是我设的防抖延时间太长了(我的防抖延时设置为10ms)。当我进一步减小防抖延时的时间时情况还是没有好转,由于单片机的软件防抖延时最佳时间段在5ms~10ms,太大或者太小都不利于软件防抖。
通过对电平触发和边沿触发两种中断触发方式的比较,发现在按键时数码管显示闪动的原因是:起初时,中断触发方式我选的是电平触发方式。在按键按下时可能由于按键性能不太好,按键稍稍的抖动使得在软件防抖后依然不太稳定,单片机在此检测到中断发生的有效电平,从而再次发生中断,导致在有按键按下时单片连续处理按键中断,从而产生数码管在有按键按下的情况下出现闪动的问题。在将按键的中断方式由电平触发模式改为边沿触发后,数码管再有按键按下的情况下闪动的问题得到了解决。
问题四:蜂鸣器在没有闹铃发生时没有声音,在闹铃响完以后还回有比较小的嘟嘟声。
可能原因:理想状态下在闹铃响完后驱动蜂鸣器的三极管截止,蜂鸣器上没有电流流过,蜂鸣器出在不发声状态。闹铃响完后蜂鸣器蜂鸣器仍然有很小的嘟嘟声,说明此时有干扰脉冲通过蜂鸣器。为了进一步减小蜂鸣器的嘟嘟声。在蜂鸣器两端接入300PF的电容后声音有所减小但没有消除。但干扰的来源尚不清楚,可能是来自电源地的干扰。
问题五:T2定时器在汇编编程的情况下如何使用。
可能原因:在C语言编程时,只需要包含头文件 #include
,所有的52单片机所用到的端口,寄存器,定时器等资源均已事先定义好了。在汇编编程的过程中我模仿C语言的模式首先定义在使用T2定时器,但一直出现错误。如何在汇编编程的情况下如何使用还未解决。
五、总结
经过10天的工作,我的数字钟从只能计时功能改进到具有闹铃功能、校时功能、闹铃调整功能。刚刚开始时,我采用的定时器方法进行计时。在编写完计时程序加闹铃功能和按键操作的时候,考虑到数字钟计时的准确性,我改变了程序设计方案,采用时钟芯片DS1302配合单片机STC89C52的设计方案。
在程序设计的过程中总体方案很简单,我只需在一定时间内读取DS1302的计时值,省去了一大堆的计时程序。但是在开始程序设计的时候才发现并没想的那么简单。我花了两天时间才把时钟芯片的操作完全的掌握,并且用汇编完成了对DS1302的读写等操作的程序设计。通过修正后走时一天的误差在10s内。
在程序全部设计完成后我们开始做PCB板。虽然上一学期学习了Protell 99SE但只是纯理论性的学习了如何绘制PCB板。这次我们不仅要自己绘制数字钟电路的PCB,并且还要刻PCB板。大家都猛然发现以前课堂上学到知识太少,在两天的时间里大家从画元器件的封装开始重新对Protell进行了学习并且完成了相应的工作。在这次绘制PCB的过程中,虽然我们最终完成了这次工作,但从调试中出现的问题来看,我们确实还存在许多问题需要解决。
首先,在焊接完成后,同样的程序在我们自己买的开发板上运行很稳定,但在我们自己刻的PCB板上运行时,数码管显示的时间出现闪动的情况。在王老师的指导下我们队PCB板的电源和地线在示波器上观察,发现地线上的干扰很大,再将部分芯片的地和电源直接用导线接至电源的地和电源上后问题得到了解决。这个问题凸显出了我们初次做的PCB板布局不太合理。
其次,由于是第一次做PCB,也根本没考虑过线宽和布线的问题,整块PCB的电源线、地线都很细,焊盘也比较小,布线也全部由自动布线完成。在检查电路的过程中发现有两个焊盘可以用直线连在一起,可能是安全间距设的太大的缘故,导线转了一圈才将两个焊盘连在一起。虽然这次绘制的PCB出了诸多问题,但经过调试中的有效处理后现在已经能够正常工作。
在这次数字钟的设计过程中,通过使用时钟芯片DS1302和单片机STC89C52完成高精度的计时。进一步学习了51单片机的编程技巧,尤其是单片机中断的使用以及中断优先级的扩展方法,同时学会了时钟芯片DS1302,进一步了解了时钟芯片的工作原理。虽然首次绘制的PCB出现了诸多问题,但同时学到了许多绘制PCB的技巧,知道了绘PCB需要注意的问题。
附录Ⅰ:
DS1302时钟芯片的工作原理和使用方法
DS1302 是DALLAS 公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和31 字节静态RAM ,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、日期、月、年的信息,每月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM 指示决定采用24 或12 小时格式DS1302 与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:(1)RES 复位,(2) I/O 数据线,(3)SCLK串行时钟时钟/RAM 的读/写数据以一个字节或多达31 个字节的字符组方式通信。DS1302 工作时功耗很低,保持数据和时钟信息时功率小于1mW。
DS1302 是由DS1202 改进而来,增加了以下的特性:双电源管脚用于主电源和备份电源供应,Vcc1 为可编程涓流充电电源,附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域。下面将主要的性能指标作一综合:
·实时时钟具有能计算2100 年之前的秒、分、时、日、日期、星期、月、年的能力还有闰年调整的能力
·31×8 位暂存数据存储RAM
·串行I/O 口方式使得管脚数量最少
·宽范围工作电压:2.0 5.5V
· 工作电流:2.0V 时,小于300nA
·读/写时钟或RAM 数据时:有两种传送方式:单字节传送和多字节传送(字符组方式)
· 8 脚DIP 封装或可选的8 脚SOIC 封装(根据表面装配)
· 简单3 线接口
· 与TTL 兼容(Vcc=5V)
· 可选工业级温度范围-40~+85
· 与DS1202 兼容
· 在DS1202 基础上增加的特性
—对Vcc1 有可选的涓流充电能力
—双电源管用于主电源和备份电源供应
—备份电源管脚可由电池或大容量电容输入
—附加的7 字节暂存存储器
1 DS1302 的基本组成和工作原理
DS1302 的管脚排列及描述如下图及表所示:
2. DS1302 内部寄存器
CH: 时钟停止位
CH=0 振荡器工作允许
CH=1 振荡器停止
WP: 写保护位
WP=0 寄存器数据能够写入
WP=1 寄存器数据不能写入
TCS: 涓流充电选择
TCS=1010 使能涓流充电
TCS=其它 禁止涓流充电 寄存器2 的第7 位12/24 小时标志
bit7=1,12 小时模式
bit7=0,24 小时模式
寄存器2 的第5 位:AM/PM 定义
AP=1 下午模式
AP=0 上午模式
DS: 二极管选择位
DS=01 选择一个二极管
DS=10 选择两个二极管
DS=00 或11, 即使TCS=1010, 充电功能也被禁
3、DS1302使用说明及注意的问题
DS1302在任何数据传送时必须先初始化,把RST脚置为高电平,然后把8位地址和命令字装入移位寄存器,数据在SCLK的上升沿被访问到。在开始8个时钟周期,把命令字节装入移位寄存器后,另外的时钟周期在读操作时输出数据,在写操作时写入数据。时钟脉冲的个数在单字节方式下为8+8,在多字节方式下为8+字节数,最大可达248字节数。如果在传送过程中置RST脚为低电平,则会终止本次数据传送,并且I/O引脚变为高阻态。上电运行时,在Vcc≥2.5V之前,RST脚必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。
DS1302的控制字如表1所示。控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。位6如果为0,则表示存取日历时钟数据;为1则表示存取RAM数据。位5~1(A4~A0)指示操作单元的地址。最低有效位(位0)如果为0,则表示要进行写操作;为1表示进行读操作。控制字节总是从最低位开始输入/输出。
为了提高对32个地址寻址能力(地址/命令位1~5=逻辑1),可以把时钟/日历或RAM寄存器规定为多字节(burst)方式。位6规定时钟或RAM,而位0规定读或写。在时钟/日历寄存器中的地址9~31或RAM寄存器中的地址31不能存储数据。在多字节方式下,读或写从地址0的位0开始。必须按数据传送的次序写最先的8个寄存器。但是,当以多字节方式写RAM时,为了传送数据不必写所有的31字节,不管是否写了全部31字节,所写的每一字节都将传送至RAM。
表1 DS1302控制字
DS1302共有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式。其日历、时间寄存器及其控制字如上表所示,其中奇数为读操作,偶数为写操作。
时钟暂停:秒寄存器的位7定义位时钟暂停位。当它为1时,DS1302停止振荡,进入低功耗的备份方式,通常在对DS1302进行写操作时(如进入时钟调整程序),停止振荡。当它为0时,时钟将开始启动。
AM-PM/12-24小时方式:小时寄存器的位7定义为12或24小时方式选择位。它为高电平时,选择12小时方式。在此方式下,位5为第二个10小时位(20~23h)。
DS1302的晶振选用32768Hz,电容推荐值为6pF。因为振荡频率较低,也可以不接电容,对计时精度影响不大。
附录Ⅱ:
如何利用软件减小的计时误差
此次所设计的数字钟,总的来看计时的误差来源主要由中断响应延迟引起的误差(不使用时钟芯片的情况下)。
如下对误差来源进行详细的
分析
定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析
。不考虑晶振等固件的误差, 则系统机器周期可以由公式准确算出, 因而系统误差不可能来自于硬件, 而应该主要来自于软件方面。 系统每次调用定时中断程序的过程中, 硬件并没有自动进入下一个定时周期, 而是在调用中断程序以后由软件置数来实现的。 而在程序调用过程中,堆栈建立、参数传递等都是需要耗时,而这些时间都被无形中加到了定时长度中去。所以,使得每次定时长度都大于理论推导值,在宏观上表现出来就是系统比理论计算出来的结果变慢了。另外,由于系统每次调用中断处理程序所执行的操作都是相同的,也就是说,系统每次定时的时间误差应该是一个常数。
MCS-51单片机的中断响应延迟时间,取决于其它中断服务程序是否在进行,或取决于正在执行的是什么样的指令。单中断系统中的中断响应时间为3~8个机器周期。无论是哪一种原因引起的误差,在精确定时的应用场合,必须考虑它们的影响,以确保精确的定时控制。根据定时中断的不同应用情况,应选择不同的精确定时编程方法。
如果设置定时器中断为中断高优先级,外部中断位低优先级,则中断过程中产生的中断延时如下图所示:
A:有按键按下的情况下发生定时中断
B:仅有时钟中断的情况CPU响应定时中断
设置定时器T1工作在定时方式1为,晶振频率为12MHz 。以下通过5种方法来解决由中断引起的延时误差问题。
方法1:
在定时器溢出中断得到响应时,停止定时器计数,读出计数值(反映了中断响应的延迟时间),根据此计数值算出到下一次中断时,需多长时间,由此来重装载和启动定时器。例如定时周期为1ms,则通常定时器重装载值为65536-1000(0FC18H)。下面的程序在计算每个定时周期的精确重装载值时,考虑了由停止计数(CLR TR1)到重新启动计数(SETB TR1)之间的7个机器周期时间。程序中#LOW(65536-1000+7)和#HIGH(65536-1000+7)是汇编符号,分别表示65536-1000+7=0FC1FH这个立即数的低位字节(1FH)和高位字节(0FCH)。
......
CLR EA ;禁止所有中断
CLR TR1 ;停止定时器T1
MOV A,# LOW (LOW -1000+7) ;期望数的低位字节
ADD A,TL1 ;进行修正
MOV TL1,A ;重装载低位字节
MOV A,#HIGH(HIGH -1000+7) ;对高位字节处理
ADDC A,TH1
MOV TH1,A
SETB TR1 ;重启动定时器
SETB EA ;重开中断
......
适用范围:此方法适用于各种原因造成的定时误差的情况,为通用方法。
方法2:
假如定时周期为10ms,通常定时器重装载值为0D8F0H,中断子程序如下:
ORL TL1,#0F0H
MOV TH1,#0D8H
......
这里用ORL TL1,#0F0H代替MOV TL1,#0F0H 可提高定时精度。此方法只适用于重装载值低位字节的低4位为零,且中断响应的延迟时间小于16个机器周期的情况。类似的定时器重装载值有0FFF0H,0FFE0H等。
方法3:
假如定时周期为1ms,通常定时器重装载值为0FC18H,中断子程序如下:
MOV A,#LOW(LOW -1000+4) ;期望数的低位字节
ADD A,TL1
MOV TL1,A
MOV A,#HIGH(HIGH -1000+4) ;对高位字节处理
ADDC A,TH1
MOV TH1,A
DEC TL1 ;恢复提前了的2个机器周期
......
这种方法中不停止定时器计数过程,若在执行指令ADDC A,TH1 或MOV TH1,A时,恰好产生TL1溢出向TH1进位的情况,则TH1的值就不对了,会产生更大的误差。为此,程序段开头为重装载值加4,若有溢出进位,则可提前发生,其中2个机器周期是考虑到为TL1重装载占用的时间。
适用范围:此方法适用于系统中无其它更高优先级中断源的情况。若类似方法1,在程序段开头和结尾分别加上禁止所有中断(CLR EA)和开中断(SETB EA)指令,则将适用于所有情况。
方法4:
假如定时周期不确定,只知道定时器重装载值存放在寄存器R3、R2中,中断子程序如下:
MOV A,#05H ;3个机器周期装载TL1,2个周期提前
ADD A,TL1
ADD A,R2
MOV TL1,A
MOV A,R3 ;处理高位字节
ADDC A,TH1
MOV TH1,A
DEC TL1 ;恢复提前了的2个机器周期
......
适用范围:此法适用于定时周期不确定的情况,其它同方法3。
方法5:当定时中断发生的位置可预知时,通常出现在主程序的AJMP $ (或SJMP $)等待指令处,中断延迟时间为3个或4个机器周期。取固定值4可简化补偿程序。以定时周期1ms为例,中断子程序如下:
ORG 001BH
MOV TL1,#LOW(LOW -1000+4)
MOV TH1,#HIGH(HIGH -1000+4)
......
适用范围:此方法适用于定时中断总发生在同一条指令位置,且无其它中断源的情况。
上述5种方法误差均不超过1个机器周期,其中方法1、3、4较为通用,适用于任何情况,但程序较长;方法2、5简单,但必须注意满足对应条件,才能使用。
袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇羅膃蚈螂羁膂莈蚅袇膁蒀袀螃膀薂蚃肂腿节衿羈腿莄蚂袄芈蒇袇螀芇蕿蚀聿芆艿蒃肅芅蒁螈羁芄薃薁袆芃芃螆螂芃莅蕿肁节蒈螅羇莁薀薈袃莀艿螃蝿荿莂薆膈莈薄袁肄莇蚆蚄羀莇莆袀袆羃蒈蚂螂羂薁袈肀肁芀蚁羆肁莃袆袂肀薅虿袈聿蚇蒂膇肈莇螇肃肇葿薀罿肆薂螆袅肅芁薈螁膅莃螄聿膄蒆薇袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈
芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈葿螈聿蒄葿袁羁莀蒈羃膇芆蒇蚃羀膂蒆螅膅蒁薅袇羈莇薄罿膄芃薃虿羆艿薃袁节膅薂羄肅蒃薁蚃芀荿薀螆肃芅蕿袈芈膁蚈羀肁蒀蚇蚀袄莆蚇螂肀莂蚆羅袂芈蚅蚄膈膄蚄螇羁蒂蚃衿膆莈蚂羁罿芄螁蚁膄膀螁螃羇葿螀袅膃蒅蝿肈羆莁螈螇芁芇莄袀肄膃莄羂艿蒂莃蚂肂莈蒂螄芈芄蒁袆肀膀蒀罿袃薈