第一篇:89C51单片机时钟程序
SECOND EQU 40H
;给内存RAM空间中40H单元起名SECOND MINUTE EQU 41H
;给内存RAM空间中41H单元起名MINUTE HOUR EQU 42H
;给内存RAM空间中42H单元起名HOUR SECONDGEWEI EQU 43H
;给43H单元起名SECONDGEWEI存秒的个位 SECONDSHIWEI EQU 44H
;给44H单元起名SECONDSHIWEI存秒的十位 MINUTEGEWEI EQU 45H
;给45H单元起名MINUTEGEWEI存分的个位 MINUTESHIWEI EQU 46H
;给46H单元起名MINUTESHIWEI存分的十位 HOURGEWEI EQU 47H
;给47H单元起名HOURGEWEI存小时的个位 HOURSHIWEI EQU 48H
;给48H单元起名HOURSHIWEI存小时的十位 ORG 0000H
;复位时程序从此开始 SJMP START
;跳到START进行初始化 ORG 000BH
;定时器 0中断入口 AJMP TIMER0
;跳转到TIMER0处
ORG 0030H
;初始化程序从30H开始;---------------初始化START------------------------------START:
MOV SECOND, #0
;给秒存储单元SECOND赋初始值0 MOV MINUTE, #0
;给分存储单元MINUTE赋初始值0 MOV HOUR , #12
;给小时存储单元HOUR赋初始值12 MOV DPTR , #TAB
;给数据指针赋值,将DPTR指向TAB数据表头处 MOV 30H, #0
;给30H单元赋初始值0(用于计20次的50ms中断)MOV TH0,#3CH
;给计数容器的高8位TH0赋初始值3CH MOV TL0,#0B0H
;给计数容器的低8位TL0赋初始值B0H MOV TMOD,#00000001B
;C/T位设置为0,M1M0设置位10,即模式1定时 MOV TCON,#00010000B
;TR0设置为1,即启动定时器0开始工作 SETB ET0
;IE中的ET0位设置为1,开定制器中断0 SETB EA
;IE中的EA位设置为1,开总中断;-----------------------主程序MAIN-----------------------------MAIN:CALL KEY
;调按键子程序KEY CALL PROCESS
;调数据处理子程序PROCESS CALL DISPLAY
;调显示子程序DISPLAY SJMP MAIN
;跳转到MAIN标号处;------------------------------按键子程序KEY调时-------------------KEY:MOV P1,#0FEH
;行扫描 LCALL DELAY
;JNB P1.4,HOURJIA
;P1.4引脚如果是低电平就跳到HOURJIA处
JNB P1.5,HOURJIAN
;P1.5引脚如果是低电平就跳到HOURJIAN处 JNB P1.6,MINUTEJIA
;P1.6引脚如果是低电平就跳到MIMUTEJIA处 JNB P1.7,MINUTEJIAN
;P1.7引脚如果是低电平就跳到MIMUTEJIAN处 FANHUI:RET
;子程序返回(如果没有按键按下)
HOURJIA:CALL DELAY
;调延时程序目的是跳过按键抖动期(去抖)JB P1.4,FANHUI
;P1.4如果是高电平就跳到FANHUI处(没键按)JNB P1.4,$
;如果P1.4是低电平就停在当前位置等键释放 MOV R4,HOUR CJNE R4,#23,A1
;判断时数字是否为23 AJMP A2
A1:INC HOUR
;把小时位加1 MOV SECOND, #0
;小时进位,秒归0
RET
A2:MOV HOUR,#0
;小时数为23时加一为0
MOV SECOND, #0
;小时进位,秒归0
RET
;子程序返回
HOURJIAN:CALL DELAY
;调延时程序目的是跳过按键抖动期(去抖)JB P1.5,FANHUI
JNB P1.5,$
MOV R5,HOUR CJNE R5,#0,A3
AJMP A4 A3:DEC HOUR
MOV SECOND, #0
RET A4:MOV HOUR,#23
MOV SECOND, #0 RET
MINUTEJIA:CALL DELAY
JB P1.6,FANHUI
JNB P1.6,$
MOV R6,MINUTE
CJNE R6,#59,A5
AJMP A6 A5:INC MINUTE
MOV SECOND, #0
RET A6:MOV SECOND, #0
MOV MINUTE, #0
MOV R4,HOUR CJNE R4,#23,A10
MOV HOUR,#0
RET A10:INC HOUR
RET
MINUTEJIAN:CALL DELAY
JB P1.7,FANHUI
JNB P1.7,$
MOV R7,MINUTE CJNE R7,#0,A7
AJMP A8 A7:DEC MINUTE
;P1.5如果是高电平就跳到FANHUI处(没键按)
;如果P1.5是低电平就停在当前位置等键释放
;判断时数字是否为23
;把小时位减1
;小时数为0时减一为23
;子程序返回
;调延时程序目的是跳过按键抖动期(去抖)
;P1.6如果是高电平就跳到FANHUI处(没键按)
;如果P1.6是低电平就停在当前位置等键释放
;判断分钟数是否为59
;把分钟位加1
;给秒存储单元SECOND赋初始值0
;分钟数为59则分钟归0
;判断时数字是否为23
;23时增1归0
;分钟数为59 自增1后小时增1
;子程序返回
;调延时程序目的是跳过按键抖动期(去抖)
;P1.7如果是高电平就跳到FANHUI处(没键按)
;如果P1.7是低电平就停在当前位置等键释放
;判断分钟数是否为0
;分钟不为0把分钟位减1
MOV SECOND, #0
RET
A8:MOV MINUTE, #59
;分钟数为0时减一为59 MOV R4,HOUR CJNE R4,#0,A9
;判断时钟数是否为0 MOV HOUR,#23
;时钟数为0减1为23 MOV SECOND, #0 RET
A9:DEC HOUR
;时钟数不为0则减1 MOV SECOND, #0
RET
;子程序返回;-------------------处理子程序PROCESS-----------------------PROCESS:MOV A, SECOND
;把SECOND中的秒值拷贝给A MOV B, #10
;给寄存器B赋值10 DIV AB
;A除以B,结果存入A中,余数存入B中 MOV SECONDSHIWEI , A
;结果即秒的十位数拷贝给SECONDSHIWEI MOV SECONDGEWEI , B
;余数即秒的个位拷贝给SECONDGEWEI MOV A, MINUTE
;把MINUTE中的分值拷贝给A MOV B, #10
;给寄存器B赋值10 DIV AB
;A除以B,结果存入A中,余数存入B中 MOV MINUTESHIWEI , A
;结果即分的十位拷贝给MINUTESHIWEI MOV MINUTEGEWEI , B
;余数即分的个位拷贝给MINUTEGEWEI MOV A, HOUR
;把HOUR中的小时值拷贝给A MOV B, #10
;给寄存器B赋值10 DIV AB
;A除以B,结果存入A中,余数存入B中 MOV HOURSHIWEI , A
;结果即小时的十位拷贝给HOURSHIWEI MOV HOURGEWEI , B
;余数即小时的个位拷贝给HOURGEWEI RET
;子程序结束返回到主程序;-----------------显示子程序DISPLAY--------------DISPLAY:MOV A, HOURSHIWEI
;小时的十位拷贝给A MOVC A, @A+DPTR
;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A
;把显示段码(小时的十位)送到P0 CLR P2.0
;将P2.0置低电平,对应的三极管导通 CALL DELAY
;调延时(让显示小时十位的数码管持续亮一段时间)SETB P2.0
;将P2.0置高电平,对应三极管截止,对应数码管灭 MOV A, HOURGEWEI
;小时的个位拷贝给A MOVC A,@A+DPTR
;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A
;把显示段码(小时的个位)送到P0 CLR P2.1
;将P2.1置低电平,对应的三极管导通
CALL DELAY
;调延时(让显示小时个位的数码管持续亮一段时间)SETB P2.1 MOV P0,#7FH CLR P2.1 CALL DELAY SETB P2.1
;将P2.1置高电平,对应三极管截止,对应数码管灭 MOV A, MINUTESHIWEI
;分钟的十位拷贝给A MOVC A,@A+DPTR
;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A
;把显示段码(分钟的十位)送到P0 CLR P2.2
;将P2.2置低电平,对应的三极管导通 CALL DELAY
;调延时(让显示分钟十位的数码管持续亮一段时间)SETB P2.2
;将P2.2置高电平,对应三极管截止,对应数码管灭 MOV A, MINUTEGEWEI
;分钟的个位拷贝给A MOVC A,@A+DPTR
;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A
;把显示段码(分钟的个位)送到P0 CLR P2.3
;将P2.3置低电平,对应的三极管导通
CALL DELAY
;调延时(让显示分钟个位的数码管持续亮一段时间)SETB P2.3
;将P2.3置高电平,对应三极管截止,对应数码管灭
MOV P0,#7FH CLR P2.3 CALL DELAY SETB P2.3
MOV A, SECONDSHIWEI
;秒的十位拷贝给A MOVC A,@A+DPTR
;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A
;把显示段码(秒钟的十位)送到P0 CLR P2.4
;将P2.4置低电平,对应的三极管导通 CALL DELAY
;调延时(让显示秒钟十位的数码管持续亮一段时间)SETB P2.4
;将P2.4置高电平,对应三极管截止,对应数码管灭 MOV A, SECONDGEWEI
;秒的个位拷贝给A MOVC A,@A+DPTR
;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A
;把显示段码(秒钟的个位)送到P0 CLR P2.5
;将P2.5置低电平,对应的三极管导通
CALL DELAY
;调延时(让显示秒钟个位的数码管持续亮一段时间)SETB P2.5
;将P2.5置高电平,对应三极管截止,对应数码管灭 RET
;显示子程序结束返回主程序;--------------------中断服务子程序----------------------------TIMER0:MOV R3, A
;把A中的数据送入R3保护起来 INC 30H
;30H单元中的数加1 MOV A, 30H
;30H单元中的数据拷贝给A CJNE A,#20,JIXU
;A中的数据与20比较不相等就跳转到JIXU处 MOV 30H,#0
;(如果30H单元计满20了)给30H赋值0 INC SECOND
;把SECOND中的秒钟数加1 MOV A,SECOND
;把SECOND中的数据拷贝给A CJNE A, #60, JIXU
;A中的数据与60比较不相等就跳转到JIXU处 MOV SECOND, #0
;给秒SECOND赋值0 INC MINUTE
;把MINUTE中的分钟数加1 MOV A, MINUTE
;把MINUTE中的数据拷贝给A CJNE A, #60, JIXU
;A中的数据与60比较不相等就跳转到JIXU处 MOV MINUTE, #0
;给分钟MINUTE赋值0 INC HOUR
;把HOUR中的小时数据加1 MOV A, HOUR
;把HOUR中的数据拷贝给A CJNE A, #24, JIXU
;A中的数据与24比较不相等就跳转到JIXU处 MOV HOUR, #0
;给小时HOUR赋值0 JIXU: MOV A,R3
;把刚才送入R3中的数据还给A MOV TH0,#3CH
;给计数容器的高8位TH0赋初始值3CH MOV TL0,#0B0H
;给计数容器的低8位TL0赋初始值B0H RETI
;中断子程序返回主程序;---------------------------延时子程序----------------------------DELAY:MOV R0, #50
;给R0赋值50 D2:MOV R1, #10
;给R1赋值10 D1:DJNZ R1, D1
;R1减1不等于0跳到D1处 DJNZ R0, D2
;R0减1不等于0跳到D2处
RET
;延时子程序结束返回调用该程序的下一条;---------------下面的数据表中存储的是显示段码(共阳)-------------------TAB:DB 0C0H,0F9H,0A4H,0B0H,99H
;从TAB处开始存储0、1、2、3、4
DB 92H ,82H ,0F8H,80H ,90H
;5、6、7、8、9对应的显示段码 END
;程序结束
第二篇:基于单片机的时钟控制器设计
时钟控制器设计任务书
1.设计目的与要求
设计出一个用于数字时钟的控制器,准确地理解有关要求,独立完成系统设计,要求所设计的电路具有以下功能:
(1)显示: 可以显示时、分和秒
(2)调时功能:时(0-24)、分和秒(0-60)可以连续可调(3)时间日误差< 2秒(4)增加整点报时功能(5)增加闹钟任意设定功能 2.设计内容
(1)画出电路原理图,正确使用逻辑关系;(2)确定元器件及元件参数;(3)进行电路模拟仿真;(4)SCH文件生成与打印输出;(5)PCB文件生成与打印输出; 3.编写设计报告
写出设计的全过程,附上有关资料和图纸,有心得体会。4.答辩
在规定时间内,完成叙述并回答问题。
目录
1.引言…………………………………………………………………………-1-2 总体设计方案………………………………………………………………-1-2.1 设计思路…………………………………………………………………-1-2.2 方案确立…………………………………………………………………-1-2.3 设计方框图………………………………………………………………-2-3 设计原理分析………………………………………………………………-2-3.1 系统硬件电路设计 ……………………………………………………-2-3.2 主控器件AT89S51 ………………………………………………………-2-3.3 译码器74HC245 …………………………………………………………-3-3.4 显示电路 …………………………………………………………………3-3.5 按键电路…………………………………………………………………-4-3.6 复位电路…………………………………………………………………-4-3.7 蜂鸣电路…………………………………………………………………-5-3.8 时钟电路…………………………………………………………………-5-3.9 总体原理图………………………………………………………………-5-3.10程序框图…………………………………………………………………-5-4 结束语………………………………………………………………………-7-参考文献………………………………………………………………………-8-附录 1 电路总原理图 ………………………………………………………-9-附录 2 总程序………………………………………………………………-10-
基于单片机控制的时钟控制器
摘要:本设计以Atmel公司的AT89S51单片机为控制系统的核心,模型采用单片机作为主控制器,以汇编语言为程序设计的基础,设计的一个用两个四位一体数码管串口显示的时钟控制电路,包含了时钟控制电路的基本功能:数码显示,时间调整,闹钟设定,秒表显示等,按照二十四小时循环,具有调节方便,简单实用,可靠性强的优点,有很高的利用价值。关键词:单片机 AT89C51 74LS245 数码管 引言
数字钟是采用数字电路实现对时、分、秒及数字显示的计时装置,广泛用于个人家庭、车站、码头、办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,所有这些,都是以钟表数字化为基础的。因此,研究数字钟及扩大其应用,有着非常现实的意义。为了适应时代的潮流,本设计采用AT89S51单片机为核心,使得计时的精度有了很大的提高,而且调节也变的简单实用,采用数字显示也跟加的直观方便。总体设计方案
2.1 设计思路
本设计采用AT89S51单片机为控制核心,产生精确的时钟震荡,来控制数码管显示电路来进行数码显示,外围电路主要有复位电路,震荡电路,按键电路,显示电路,蜂鸣电路组成;复位电路可及时的对单片机进行复位,恢复到初始的状态,震荡电路主要用于计数,定时,产生合适的波特率,按键电路主要是给人们提供一个合适的人机对话的界面,方便人们进行实时的调节,显示电路主要用于数码的显示,蜂鸣电路用于闹铃设定等辅助功能。2.2 方案确立
本设计主要有包含了时钟电路,按键扫描,显示电路等几个部分。由单片机实现时钟功能单片机内部具有定时器,可方便实现定时功能。按键电路:键盘分为矩阵式键盘扫描电路和独立式按键电路。。矩阵式键盘电路,此类键盘是采用行列扫描方式,优点是当按键较多时可以降低占用单片机的I/O口数目,缺点是电路复杂且会加大编程难度。独立按键电路,每个键单独占有一根I/O接口线,每个I/O口的工作状态互不影响,此类键盘采用端口直接扫描方式。缺点是当按键较多时占用单片机的I/O数目较多,优点是电路设计简单,且编程极其容易。由于该系统采用了常规钟表式的校对方式,用键较少,系统资源足够用,故采用了独立按键电路。显示电路分为:静态显示法与动态显示法,由于静态显示法需要数据锁存器等硬件,接口复杂一些,又考虑到时钟显示只有6位,且系统没有其它复杂的处理任务,所以决定采用动态显示法。2.3 硬件设计方框图
电路的设计以AT89S51单片机为核心,包含了按键电路,复位电路,震荡电路,数 码显示电路,整点报时电路等一系列独立环节,下面介绍一下电路设计过程中的总体框图,如图1所示。
图1 时钟电路总体框图 设计原理分析
用AT89S51单片机控制的数字时钟电路,外接震荡电路,按键电路,显示电路,蜂鸣电路等:用单片机电路P0口来输出7段码数据,P2.0~P2.5口作列扫描输出;按键用P1口控制,分别用于调节时,分,以及秒表和闹钟的设定;P1.7口接5V的小蜂鸣器,用于按键发音以及定时提醒,整点报时提醒等;采用74HC245作为数码管的段码驱动,为了提供共阳LED数码管的列扫描驱动电压,用三极管8550做电源的驱动输出;采用12MHZ晶振,可提高秒计时的精确性;在软件设计方面,应完成时钟控制电路的各项要求。
3.1 系统硬件电路设计
系统硬件电路主要组成:主控制器AT89S52、译码器74HC245、显示电路、蜂鸣器电路,复位电路时钟电路。3.2 主控器件AT89C51 AT89S51是一款低功耗,高性能CMOS 8位单片机,片内含4k Bytes ISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80C51引脚结构,芯片内集成了通用8位中央处理器和ISP Flash存储单元,AT89S51在众多嵌入式控制应用系统中得到广泛应用。管脚如图2所示。
图2 DIP-40封装89C51引脚图
3.3译码器74LS245 74LS245是我们常用的芯片,用来驱动led或者其他的设备,它是8路同相三态双向总线收发器,可双向传输数据。74LS245还具有双向三态功能,既可以输出,也可以输入数据。当89S51单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。当片选端/CE低电平有效时,DIR=“0”,信号由 B 向 A 传输;(接收)DIR=“1”,信号由 A 向 B 传输;(发送)当CE为高电平时,A、B均为高阻态。P0口与74LS245输入端相连,E端接地,保证数据线畅通。管脚如图3所示。
图3 74LS245管脚图
3.4 显示电路
LED显示块是由发光二极管显示字段的显示器件。这种显示块有共阴与共阳两种结构。共阴极LED显示块的发光二极管阴极共地,当某个发光二极管的阳极为高电平时,发光二极管点亮。共阳极LED显示块的放光二极管阳极并接。显示块与单片机接口非常容易,只要将一个8位并行输出口语显示块的发光二极管引脚相连即可(AT89S51需要加上拉电阻)。此次电路采用2个4位共阳LED数码管,从P0口输出段码,列扫描用P2.0~P2.7来实现。如图4所示。
图4 74LS245驱动段码显示电路图
3.5 按键电路
按键调节电路有四个独立的按键接到P1口的P1.0—P1.3端口,控制着电路的调时,调分以及秒表功能和闹钟的设定。具体电路如下图5所示。
图5 按键电路图
3.6 复位电路
AT89S51单片机的复位电路,如图5所示中左边电路。在RESET输入端出现高电平时实现复位和初始化。在震荡器运行的情况下,要实现复位操作,必须使RST引脚至少 保持两个机器周期的高电平。在CPU在第二个机器周期内执行内部复位操作,以后每一个机器周期重复一次,直至RST端电平变低复位期间不产生ALE信号。当RST引脚返回低电平以后,CPU从0地址开始执行程序。3.7 蜂鸣电路
蜂鸣器是广泛应用于各种电子产品的一种元器件,它用于提示、报警、音乐等许多应用场合。三极管8550作蜂鸣器的驱动,增加了蜂鸣器的驱动电流。蜂鸣器的正极性的一端接到三极管的集电极,另一端连接到地,三极管的基极由单片机的P1.7管脚控制,底电平时蜂鸣器响,高电平时不响。另外,蜂鸣器的声音大小及音调可以通过调整P1.7管脚的置低时间及输出的波形进行控制。蜂鸣器的连接电路的原理图如图5所示。3.8 时钟电路
AT89S51内部片内有一个由反相放大器构成的振荡电路,XTAL1和XTAL2分别为震荡电路的输入端和输出端。时钟可以由内部方式产生或外部方式产生。在XTAL1和XTAL2引脚上外接定时元件,内部震荡电路就产生自己震荡。定时元件通常采用石英晶体和电容组成的并联谐振回路。外部方式的时钟电路,XTAL1接地,XTAL2接外部振荡器。一般要求输入方波信号的频率低于33Mhz。本文设计的系统采用的是内部方式的时钟电路。如图6所示。
图6 时钟电路原理图
3.9 总体原理图
见附录1 3.10程序框图
主程序如图7所示首先是初始化部分,主要是计时单元清零,中断初始化,启动定时器工作,然后是调用显示子程序,接着是判断有无按键。无按键则回到调用显示子程序处;有按键,则执行按键处理子程序,执行完后回到调用显示子程序处,重复循环。定时器T0中断如图8所示
图7 主程序流程图
图8 中断程序流程图 结束语
三周实习很快就过去了,通过自行设计、焊接和调试一个单片机系统,我熟悉了单片机基本的开发流程和单片机的深入学习。在完成这个设计的同时,我复习了书本上的许多相关内容,受益匪浅。因此我在获得理论知识的同时,实践中也获得了许多书本上没有的东西。提高了调试以及查找并解决问题的能力,我深入了解了焊普通元件与电路元件的技巧、数字时钟的工作原理及其它各电路元件的作用等。这些知识不仅在课堂上有效,对以后的学习工作有很大的指导意义,在日常生活中更是有着现实意义;也对自己的动手能力是个很大的锻炼。实践出真知,纵观古今,所有发明创造无一不是在实践中得到检验的。没有足够的动手能力,就奢谈在未来的科研尤其是实验研究中有所成就。最后,感谢老师对我们这次实习的辛勤指导和帮助。
参考文献
[1] 李光飞,楼然苗,胡佳文编著.单片机课程设计实例指导.北京:北京航空航天大学出版社.2004 [2] 黄仁欣主编.单片机原理及应用技术.北京: 清华大学出版社.2005.[3] 高吉祥主编.电子技术基础实验与课程设计.北京:电子工业出版社.2002 [4] 肖玲妮.印刷电路板设计教程.[M].北京:清华大学出版社,2003.[5] 康华光.电子技术基础.[M].北京;高等教育出版社,2006.[6] 余小平等.电子系统设计.[M].北京:北京航空航天大学出版社,2007.附录1: 11 电路总原理图
附录2: 总程序
ORG 0000H LJMP START ORG 000BH LJMP INIT0 START: MOV 70H,#0 MOV 71H,#0 MOV 72H,#0 MOV 73H,#0 MOV 74H,#0 MOV 75H,#0 MOV 76H,#0 MOV 77H,#0 MOV 78H,#0 MOV 79H,#0 MOV 7AH,#0 MOV 7BH,#0 MOV 7CH,#0 MOV 7DH,#0 MOV 7EH,#0 MOV 72H,#0AH;对连字符进行装值
MOV 75H,#0AH MOV 60H,#0 MOV 61H,#0 MOV 63H,#0 MOV 64H,#0 CLR P1.7 MOV TMOD,#01H;选择定时器/计数器T0的方式1 MOV TL0,#0B0H;对低位赋初值 MOV TH0,#03CH;高位赋初值 SETB EA SETB ET0 SETB TR0 START1: LCALL SCAN LCALL KEYSCAN SJMP START1 DL1MS: MOV R6,#14H;延时1子程序 DL1: MOV R7,#19H DL2: DJNZ R7,DL2 DJNZ R6,DL1 RET DELAY: MOV R6,#10 D1: MOV R7,#30 DJNZ R7,$ DJNZ R6,D1 RET
DL20MS: ACALL SCAN;延时20ms子程序 ACALL SCAN ACALL SCAN RET
;整点报时将秒和分的单元与零比较 SCAN: MOV A,7EH;7F单元的内容为0
CJNE A,79H,NEXT MOV A,7DH
CJNE A,7AH,NEXT SETB P1.7 AJMP NEXT1 NEXT: CLR P1.7 NEXT1:
MOV A,79H
CJNE A,#0,NEXT2 MOV A,78H
CJNE A,#0,NEXT2 SETB P1.7 LJMP NEXT3 NEXT2:CLR P1.7
;数码管总显示程序开始分两部分
;校正时间和数码管正常工作的显示程序 NEXT3: MOV A,78H MOV B,#0AH
DIV AB;时间秒的十位送给A,时间秒的个位送B
MOV 71H,A;时间秒要显示的十位
MOV 70H,B;时间秒要显示的个位
MOV A,79H MOV B,#0AH
DIV AB;时间分的十位送给A,时间分的个位送B
MOV 74H,A;时间分要显示的十位送地址
MOV 73H,B;时间分要显示的个位送地址
MOV A,7AH MOV B,#0AH DIV AB;时间时的十位送给A,时间时的个位送B MOV 77H,A;时间时显示的十位送地址
MOV 76H,B;时间时要显示的个位送地址
MOV R1,#70H LCALL DL1MS JB P1.2,LAST HERE3:JNB P1.2,HERE3 INC 7EH MOV A,7EH
CJNE A,#3CH,LOOP3 MOV 7EH,#00H;调制闹铃的时间显示 LOOP3: MOV DPTR,#TAB MOV R5,#0FEH MOV A,7DH MOV R3,#09H
MOV B,#10 SCAN1: MOV A,R5;数码管正常工作的显 DIV AB 示程序
MOV 64H,A MOV P2,A MOV 63H,B MOV A,@R1 MOV A,7EH MOV DPTR,#TAB
MOV B,#10 MOVC A,@A+DPTR;对字段表取值 DIV AB 显示
MOV 61H,A MOV P0,A MOV 60H,B MOV A,R5 MOV P2,#0F7H LCALL DL1MS MOV A,60H INC R1 MOVC A,@A+DPTR MOV A,R5 MOV P0,A RL A LCALL DELAY MOV R5,A MOV P2,#0EFH DJNZ R3,SCAN1 MOV A,61H MOV P2,#00H MOVC A,@A+DPTR MOV P0,#00H MOV P0,A JB P1.3,QQ LCALL DELAY LCALL DL1MS MOV P2,#0DFH JB P1.3,QQ MOV P0,#40H HERE: JNB P1.3,HERE LCALL DELAY SJMP LOOP1 MOV P2,#0BFH
MOV A,63H QQ: LJMP LAST MOVC A,@A+DPTR LOOP1:JB P1.1,LOOP2 MOV P0,A LCALL DL1MS LCALL DELAY JB P1.1,LOOP2 MOV P2,#07FH HERE1:JNB P1.1,HERE1 MOV A,64H INC 7DH MOVC A,@A+DPTR MOV A,7DH
MOV P0,A CJNE A,#18H,LOOP2 LCALL DELAY MOV 7DH,#00H JB P1.3,LOOP4 LOOP2:JB P1.2,LOOP3 LCALL DL1MS 14 JB P1.3,LOOP4 HERE4:JNB P1.3,HERE4 LJMP LAST LOOP4:LJMP LOOP1 LAST: RET;“0~9”和“-”的字段表 TAB:
DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H
;定时/计数器T0中断程序 INIT0: PUSH ACC PUSH PSW CLR ET0 CLR TR0 MOV TL0,#0B0H MOV TH0,#03CH SETB TR0 INC 7BH MOV A,7BH CJNE A,#14H,OUTT0;50ms是否到20次,没有到就继续执行50ms的延时
MOV 7BH,#00 INC 78H MOV A,78H CJNE A,#3CH,OUTT0;一秒的延时是否计到60次,没有就继续执行
MOV 78H,#00 INC 79H MOV A,79H CJNE A,#3CH,OUTT0 MOV 79H,#00 INC 7AH MOV A,7AH CJNE A,#18H,OUTT0;60分钟的延时是否计到24次,没有就继续执行程序 MOV 7AH,#00 OUTT0: SETB ET0;启动定时器T0 POP PSW POP ACC RETI;按键处理程序 KEYSCAN:CLR EA
JNB P1.0,KEYSCAN0;P1.0有按键按下则跳转到子程序
JNB P1.1,KEYSCAN1;P1.1有按键按下则跳转到子程序
JNB P1.2,KEYSCAN2;P1.2有按键按下则跳转到子程序
KEYOUT: SETB EA RET
KEYSCAN0:LCALL DL20MS;20ms的延时消抖
JB P1.0,KEYOUT WAIT0: JNB P1.0,WAIT0;判断按键是否松手,松手就往下执行程序 INC 7CH MOV A,7CH CLR ET0 CLR TR0
CJNE A,#04H,KEYOUT;按下第一次和第二次对时、分选定
MOV 7CH,#00;按下第三次时就启动计时
SETB ET0 SETB TR0 LJMP KEYOUT
KEYSCAN1:LCALL DL20MS;按键加一的程序
JB P1.1,KEYOUT WAIT1: JNB P1.1,WAIT1 MOV A,7CH
CJNE A,#03H,KSCAN11;如果功能键按下则对时加一调整 INC 78H MOV A,78H
CJNE A,#60,KEYOUT MOV 78H,#00 LJMP KEYOUT
KSCAN11: CJNE A,#02H,KSCAN12 INC 79H MOV A,79H
CJNE A,#60,KEYOUT;如果加到60则清零
MOV 79H,#00 LJMP KEYOUT KSCAN12:CJNE A,#01H,KEYOUT INC 7AH;如果功能键是按下第二次则对分进行加一调整
MOV A,7AH CJNE A,#18H,KEYOUT MOV 7AH,#00 LJMP KEYOUT KEYSCAN2:LCALL DL20MS;延时消抖程序 JB P1.2,KEYOUT WAIT2: JNB P1.2,WAIT2;判断是否放开按键
MOV A,7CH;如果功能键是按下第一次对时进行减一 CJNE A,#03H,KSCAN22 DEC 78H MOV A,78H CJNE A,#00H,KEYOUT MOV 78H,#3BH LJMP KEYOUT KSCAN22:CJNE A,#02H,KSCAN23 DEC 79H MOV A,79H CJNE A,#00H,KEYOUT1 MOV 79H,#3BH LJMP KEYOUT KSCAN23:CJNE A,#01H,KEYOUT1 DEC 7AH MOV A,7AH;如果功能键是按下第二次则对分进行减一 CJNE A,#00H,KEYOUT1 MOV 7AH,#17H LJMP KEYOUT1 KEYOUT1: SETB EA RET END
第三篇:AVR单片机的时钟设计(范文)
基于AVR单片机Mega16的时钟设计报告
1摘 要
近年来随着计算机在社会领域的渗透和大规模集成电路的发展,单片机的应用正在不断地走向深入,由于它具有功能强,体积小,功耗低,价格便宜,工作可靠,使用方便等特点,因此越来越广泛地应用各个领域.本文的电子钟系统是以单片机(ATmega16)为核心,时钟芯片、数码管显示驱动芯片等元器件组成。具体介绍应用Proteus的ISIS软件进行单片机系统的电子钟设计与仿真的实现方法。该方法既能准确验证所设计的系统是否满足技术要求,又能提高系统设计的效率和质量,降低开发成本,具有推广价值。
关键词:单片机; 时钟芯片 ;数码管显示驱动芯片 ;电子钟
2引 言
单片机电子时钟系统可以用多种技术手段实现。本文借助于Proteus仿真系统进行系统虚拟开发成功之后再进行实际操作,可以节约开发时间,降低开发成本,具有很大的灵活性和可扩展性。在国外有包括斯坦福、剑桥等在内的几千家高校将Proteus作为电子工程学位的教学和实验平台;在国内也有众多大学正在体验Proteus的独一无二的功能并申报大学计划。该方法具有普遍意义。通过实际应用发现,采用该方法可以大大简化硬件电路测试和系统调试过程中电路板制作、元器件安装、焊接等过程。很明显,使用该方法可以提高开发效率、降低开发成本、提升开发…
AVR系列的单片机不仅具有良好的集成性能,而且都具备在线编程接口,其中的系列还具备仿真和下载功能;含有片内看门狗电路、片内程序FLASH、同步串行接口SPI;多数AVR单片机还内嵌了A/D转换器、EEPROM、模拟比较器、PWM定时计数器等多种功能;AVR单片机的I/O接口具有很强的驱动能力,灌人电流可直接驱动继电器、LED等元件,从而省去驱动电路,节约系统成本。
3设计思路
利用单片机(ATmega16)制作简易电子时钟,由六个LED数码管分别显示小时十位、小时个位、分钟十位、分钟个位、秒钟十位、秒钟个位。6个PNP管分别控制六个数码管的亮灭,此外还可以实现时间调整、等多种实用功能。整个设计分硬件和软件两大部分。硬件部分采用MEGA16单片机作为可编程芯片,字符液晶作为信号显示;软件部分利用C语言作为设计语言,对MEGA16进行编程实现各种功能。
硬件设计电路分解为单片机、晶体振荡器和数码管3个部分,其结构简单,经济实惠。单片机内部晶体振荡器的外接电路。由两个电容和晶体振荡器构成,其电路如图1所示。图中X1和X2分别接MEGA16的两个脉冲控制端,使得MEGA16的内部脉冲电路为电子时钟和整个系统时钟提供脉冲。
图1所示给出了采用单片机外加电源及晶体振荡器构成最小单片机系统。配合单片机开发的设计、调试和下载,最终将时钟信息从端口输出到字符液晶显示。
图26位模式与单片机的端口相连。
4软件设计及调试过程
软件设计包括Proteus的ISIS软件、Code Vision AVR编辑软件和AVRStudio4调试。利用ISP将生成程序timer.cof 下载到目标板。其主要程序如下:
void display(void)// 6 位LED 数码管动态扫描函数
{
PORTC = 0xff;
PORTA = led_7[dis_buff[posit]];
if(point_on &&(posit==2||posit==4))PORTA |= 0x80;
PORTC = position[posit];
if(++posit >=6)posit = 0;
}
// Timer 0 比较匹配中断服务
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
display();// 调用LED 扫描显示
if(++time_counter>=100)
{
time_counter = 0;
time_1s_ok = 1;
}
}
void time_to_disbuffer(void)// 时钟时间送显示缓冲区函数
{
char i,j=0;
for(i=0;i<=2;i++)
{
dis_buff[j++] = time[i] % 10;
dis_buff[j++] = time[i] / 10;
}
}
// INT0 中断服务程序
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if(++time[2]>=24)time[2] = 0;
}
// INT1 中断服务程序
interrupt [EXT_INT1] void ext_int1_isr(void)
{
if(++time[1]>=60)time[1]=0;
}
void main(void)
{
PORTA=0x00;// 显示控制I/O 端口初始化
DDRA=0xFF;
PORTC=0x3F;
DDRC=0x3F;// T/C0 初始化
PORTA=0xFF;
DDRA=0xFF;
GICR|=0xC0;// 允许INT0、INT1 中断
MCUCR=0x0A;// INT0、INT1 下降沿触发
GIFR=0xC0;// 清除INT0、INT1 中断标志位
TCCR0=0x0B;// 内部时钟,64 分频(4M/64=62.5KHz),CTC 模式
TCNT0=0x00;
OCR0=0x7C;// OCR0 = 0x7C(124),(124+1)/62.5=2ms
TIMSK=0x02;// 允许T/C0 比较匹配中断
time[2] = 14;time[1] = 01;time[0] = 55;// 设时间初值23:58:5
5posit = 0;
time_to_disbuffer();
#asm(“sei”)// 开放全局中断
while(1)
{
if(time_1s_ok)// 1 秒到
{
time_1s_ok = 0;
point_on = ~point_on;
if(++time[0] >= 60)// 以下时间调整
{
time[0] = 0;
if(++time[1] >= 60)
{
time[1] = 0;
if(++time[2] >= 24)time[2] = 0;
}
} time_to_disbuffer();// 新调整好的时间送显示缓冲区
5总结心得
这次设计报告培养了学生综合运用所学知识,发现,提出,分析和解决问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域,在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握单片机的开发技术是十分重要的。
回顾起此次单片机设计,我仍感慨颇多,的确,从选题到定稿,从理论到仿真,在这些日子里,我学到很多很多的的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,这毕竟第一次做的,难免会遇到过各种各样的问题,同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,比如说不懂一些元器件的使用方法,对单片机汇编语言掌握得不好……通过这次课程设计之后,一定把以前所学过的知识重新温故。
这次设计终于顺利完成了,在设计中遇到了很多编程问题,最后在老师的辛勤指导下,终于游逆而解。同时,在老师那里我学得到很多实用的知识,在次我表示感谢!同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!
}结束语
单片机自20世纪70年代问世以来,以其极高的性能价格比,受到人们的重视和关注,应用很广、发展很快。单片机体积小、重量轻、抗干扰能力强、环境要求不高、价格低廉、可靠性高、灵活性好、开发较为容易。尤其是AVR单片机可以用高级语言编程,极容易地实现系统移植,并且加快了软件的开发过程。这次设计通过对它的学习、应用,以Mage16单片机为核心,辅以必要的电路,采用高级C语言编程,设汁了一个简易的电子时钟,由
4.5 V直流电源供电,通过数码管能够准确显示时间。
第四篇:单片机数字时钟课程设计感想
五.实验总结及感想
在实验的开始几天,基本上没有收获,不知何从下手,不知所措。为了看得更远,不妨站在前人的肩膀上,我在整体思路模糊的情况下,在网上大量招资粮,各种与电子时钟相关的文章,我阅读了不少。随着涉猎的点滴积累,我对电子时钟的设计方案已经慢慢酝酿而成。有了方向和不少知识储备后,在接下来的几天,几乎每天都有突破,虽然有时只是一句程序的修改或诞生,但那种收获的感觉很暖人心。
实验中遇到了不少问题,接下来总结一下,共同探讨。
1,按键问题。我的设计中,很多功能选择是通过按键开关实现的。在仿真中发现,调整数值时,有时按键反应太快,按一次,跳了几下,使设置时间,日期很不方便。但是仿真多了之后,找到了按键(实际上是按鼠标)的节奏,对按键的掌控力提高了不少,不怎么会出现跳变的情况了。有些开关我采用了长按键的方式来防抖,效果不错,但是每次都要长按键,调整效率太低,我没有普及。本来想把所有的按键都加延时防抖电路,但仿真中感觉对键盘的控制力没提高多少,有时还是会出问题,这个方案放弃了。索性将板子焊接出来了在调试软件吧,仿真毕竟不是那么“真”啊!实际电路调试中,按键反应没有出现过于灵敏的问题,基本可控制。
出现以上问题,我认为是电路板上焊接点太多,接触不是很好,影响了信号的传输时间,从而解决了按键问题!也有可能是按键质量问题,接触不良。
2,P0口开关问题。P0口比较特殊,它存在高阻态,要使其输入不是高电平就是低电平,就要接上拉电阻,给其高电平输入。
3,音乐闹铃问题。在闹铃时间到,闹铃提醒时,我的数码管为熄灭状态,因为开始我的响铃程序内,没有数码管扫描显示程序。但加入数码管显示子程序后,我的闹铃音乐被影响了,一开始不知所措,有点怀疑是显示程序时间过长,影响音乐的定时(节拍),我就在响铃程序中加延时模块,延时长度逐渐提高,最后出现了类似的问题,看来时显示程序占用时间太长,使音乐每个音符的节拍出现了紊乱,音乐功能被遏制了!鱼和熊掌不能兼得,我只能牺牲显示来获得音乐闹铃,但为了弥补显示,我设计了闪烁提醒方案,就是在手动或音乐自然停止后,进入当前时间闪烁提示,8秒后若不按返回键,则自动跳入主程序。
在仿真中,老师提供的响铃电路不能实现功能,但是在我的电路板中效果很好,令人费解!4,中断冲突问题,为了实现秒表,我在T0中断嵌套了秒表相关进位程序,由于秒表要求精度0.01秒,故我的T0中断定时为就刚好0.01秒,中断100次,刚好1秒。秒表确实实现了,但是我的闹铃音质变差了。一开始以为是闹铃程序存太多冗余环节,影响了T1的音乐输出中断,但是检查程序后,发现没什么多余的,裁剪无从下手。
在仿真中,我让音乐模块运行,发现音质很好。添加T0中断服务程序,但是将中断进入的间隔变大,即0.05秒进入一次中断,发现音质有所下降,有滋滋声,但比原来的好。最后认定应该是T0中断过于频繁,T1音乐频率发生中断被打破,当单位时间内被打破的次数达到一定程度时,音符和节拍的对应发生紊乱,最终音质变差。
虽然如此,我的焊接的电路板的表现却很争气,闹铃音质可以接受!虽然这次实际表现不错,但问题还是有的,还是要解决的,我的方案是把秒表程序放在T1中断服务程序,虽然音乐的发生要用到T1中断,但是秒表的显示和闹铃音乐的演奏上不会重合在一起,闹铃判断是在主程序,而秒表实现是在秒表子程序,故原本相互矛盾的两个功能,在T1中断服务程序中找到了共同的归宿,和谐相处。
5,显示数字分隔问题。本实验中用8个共阴极数码管显示日历及其时间,但是8个数码管连在一起,显示过程中不能有效地区分时,分,秒和年,月,日,数码管是两两组合起来,形成某位的十位和个位,故用小数点在适当位置一直保持高亮状态,形成分隔符,实现方便的读取数据。具体方法是,将需要小数点位高亮的数码管找出来,在动态显示扫描到该数码管时,先将提取的字段码的最高位变为1,利用语句 ORL A,#10000000B 实现,修正字码后,再将字码送入P1口显示数字,如此问题得以解决。
6,添加倒计时器嘀嘀声提示功能。这个功能我用到了T1中断,作为音调频率发生器,但是T1已经承担了音乐闹铃的音调发生功能,在此通过设立标志位实现中断服务程序的转变。即使我将秒表的实现服务程序放入T1中断实现,也没问题,只要选择标志位判断就可以了。在此,我们用调整状态指示灯的状态来做标志位,具体的说是P0.1口做标志位。
还有一个问题就是如何使铃声有间隔的响,这就牵涉到定时,在此我们用硬件定时,即T1中断的次数作为定时参数。我的设计是音调响0.25秒,然后用T1延时0.5秒,由于计数器工作于方式1时,12MHZ时钟频率下时,一次中断最多定时65536*1us=0.065536秒,为了实现0.5秒的响声间隔,将T1中断1次定时为0.05秒,中断10次后,重新装音调发生计数初值。对于响铃时间的设定原理类似,可以有发声频率求出一次发声定时中断的时间,N次发声定时中断后,使时间变化0.25秒,而后转入发声间隔定时程序。
设计体会
以前看别人的一个电子表卖十几块钱,心里面有点愤愤不平,现在,自己做过一个电子钟,才发现,其中的不容易,还有艰辛。其实做其他的事情也是一样,都会经过很多的困难,才能成功。突然想起一句话“不经历风雨,怎么见彩虹”。其实想想,这一个月,也留下了很多美好的回忆。一分耕耘,一分收获。只有亲自用实践来验证这句话,在能得其要领。经过这次单片机课程设计,我从一个单片机实践的门外汉,已经越升为略知一二的新手。虽然还有很多有关单片机的应用有待学习,但万变不离其宗,只要深入了解单片的原理,全部知识点,各个细节,一切设计皆有可能。还记得那个晚上通宵达旦仿真,不成功,誓不睡觉,很困了,都还在弄着。却当仿真成功时,没有一丝睡意,有的只是心中的喜悦通过这次的设计使我认识到本人对单片机方面的知识知道的太少了,对于书本上的很多知识还不能灵活运用,尤其是对程序设计语句的理解和运用,不能够充分理解每个语句的具体含义,导致编程的程序过于复杂,使得需要的存储空间增大。损耗了过多的内存资源。本次的设计使我从中学到了一些很重要的东西,那就是如何从理论到实践的转化,怎样将我所学到的知识运用到我以后的工作中去。只要我们有耐心,够细心,都可以把它们解决。在大学的课堂的学习只是在给我们灌输专业知识,而我们应把所学的用到我们现实的生活中去,此次的电子时钟设计给我奠定了一个实践基础,我会在以后的学习、生活中磨练自己,使自己适应于以后的竞争,同时在查找资料的过程中我也学到了许多新的知识,在和同学协作过程中增进同学间的友谊,使我对团队精神的积极性和重要性有了更加充分的理解。我知道,今后我的路还是很长,我要学的东西也有很多。通过这次实习,我深刻的认识到计算机专业的路的不平坦,但我会以一种良好的态度去迎接每一个挫折和挑战。
第五篇:基于51单片机电子时钟设计
基于51单片机的电子时钟设计
摘要
本电子时钟以STC89C52单片机作为主控芯片,采用DS12C887时钟芯片,使用1602液晶作为显示输出。该时钟走时精确,具有闹钟设置,以及可同时显示时间、日期等多种功能。本文将详细介绍该电子时钟涉及到的一些基本原理,从硬件和软件两方面进行分析。
【关键词】
STC89C52单片机
DS12C887时钟芯片
1602液晶
蜂鸣器
目录
一、绪论…………………………………………………………4
1.1 电子时钟功能…………………………………………1.2设计方案………………………………………………4
二、硬件设计……………………………………………………4
2.151
2.2 单片机部分设计………………………………4
USB供电电路设计………………………………5
2.3 串行通信电路设计………………………………6
2.4DS12C887时钟芯片电路的设计…………………6
2.51602LCD液晶屏显示电路设计………………7
2.6
蜂鸣器电路设计………………………………8
2.7
按键调整电路设计…………………………8
三、软件设计…………………………………………9
3.1 系统程序流程图设计…………………………9
3.2程序设计……………………………………11
四、心得体会………………………………………………22 参考文献……………………………………………………23
一、绪
论
1.1电子时钟功能
(1)在1602液晶上显示年、月、日、星期、时、分、秒,并且按秒实时更新显示。(2)具有闹铃设定即到时报警功能,报警响起时按任意键可取消报警。
(3)能够使用实验板上的按键随时调节各个参数,四个有效键分别为功能选择键、数值增大键、数值减小键和闹钟查看键。
(4)每次有键按下时,蜂鸣器都以短“滴”声报警。
(5)利用DS12C887自身掉电可继续走时的特性,该时钟可实现断电时间不停、再次上电时时间仍准确显示在液晶上的功能。
1.2设计方案
DS12C887时钟芯片+1602LCD液晶屏
DS12C887时钟芯片功能丰富、价格适中,能够自动产生世纪、年、月、日、时、分、秒等时间信息,其内部含有世纪寄存器,从而利用硬件电路解决“千年”问题。DS12C887中自带锂电池,外部掉电时,其内部时间信息还能保持10年之久。1602LCD液晶屏可以输出2行,每行显示16个字符。1602LCD液晶屏显示清晰且不会闪烁,由于液晶屏是数字式的,因此和单片机系统的接口简单,操作方便。
以STC89C52为主控芯片,DS12C887为时钟芯片,1602LCD液晶屏作为显示器。程序控制DS12C887时钟芯片实现小时、分、秒和年、月、日的计时,并在1602LCD液晶屏上显示出来。当时间走到程序所设定的时间时,蜂鸣器响起,起到闹钟功能。
二、硬
件
设
计
2.1 51单片机部分设计
单片机部分如图2—1所示:
以STC89C52单片机为核心,选用12MHZ的晶振,由于晶振的频率越高,单片机的运行速度就越快,考虑到单片机的运行速度快会导致对存储器的要求就会变高,因此12MHZ为最佳选择。外接电容的值虽然没有严格的要求,但是外接电容的大小会影响振荡器的频率高低、振荡器的稳定性和起振的快速性,因此选用30pF的电容作为起振电容。复位电路为按键高电平复位,当按键按下,RES端为高电平,当高电平持续4us的时间单片机即复位。
2.2 USB供电电路设计
USB供电电路如下图2—2所示:
该电子时钟采用USB端口的方式为单片机供电,LPOW1为电源显示灯,当按键S5按下,电源显示灯LPOW1亮,表示给单片机供+5V电。
2.3 串行通信电路设计
串行通信电路如下图2—3所示:
图中通过MAX232进行RS—232电平与单片机TTL电平之间的转换,从而为单片机和上位机之间通信提供通道。通信电路的目的就是让通信双方的电平匹配,单片机用的是TTL电平,上位机的串口用的是RS—232电平。TTL电平逻辑1的电压范围是+3.3V到+5V,逻辑0的电压范围是0到+3.3V;RS—232电平的逻辑1的电压范围是—15V到—5V,逻辑0的电压范围是+5V到+15V。MAX232可以把输入的+5V电源电压变换成为RS—232输出电平所需的+10V电压。所以采用此芯片接口的串行通信系统只需单一的+5V电源就可以了。对于没有+12V电源的场合,其适应性更强,2.4 DS12C887时钟芯片电路的设计
时钟芯片电路如下图2—4所示:
DS12C887时钟芯片共需要13条信号线,分别是并行数据地址复用线AD0~AD7,CS,AS,R/W,DS和IRQ。
MOT—总线操作时序选择端。它有两种工作模式,当MOT接
VCC时,选用Motorola模式;当MOT接GND或悬空时,选用Intel模式。NC—空引脚。
AD0~AD7—复用地址数据总线。在总线周期的前半部分,出现在AD0~AD7上的是地址信息,可用以选通DS12C887内的RAM,总线周期的后半部分出现在AD0~AD7上的是数据信息。GND,VCC—系统电源接入端。当
VCC输入为+5V时,用户可以访问DS12C887内RAM的输入小于+4.25V时,禁止用户对内部RAM中的数据,并可对其进行读/写操作;当
VCC进行读/写操作,此时用户不能正确芯片内的时间信息;当
VCC的输入小于+3V时,DS12C887会自动的将电源切换到内部自带的锂电池上,以保证内部的电路能正常工作。
CS—芯片片选端。
AS—地址选通输入端。在进行读/写操作时,AS的上升沿将AD0~AD7上出现的地址信息锁存到DS12C887上,而下一个下降沿清除AD0~AD7上的地址信息,不论CS是否有效,DS12C887都将执行该操作。
R/W—读/写输入端。该引接脚有两种工作模式,当MOT接
VCC时,R/W工作在Motorola模式。此时该引脚的作用是区分读操作还是写操作,R/W高电平时为读操作,R/W为低电平时为写操作;当MOT接GND时,该引脚工作在Intel模式,此时该引脚为写允许输入,此信号的上升沿锁存数据。
DS—数据选择或读输入脚。该引脚有两种工作模式,当MOT接
VCC时,选用Motorola模式,此时,每个总线周期后一部分的DS为高电平,称为数据选通。在读操作中,DS的上升沿使DS12C887将内部数据送往总线AD0~AD7上,以供外部读取。在写操作中,DS的下降沿将使总线AD0~AD7上的数据锁存在DS12C887中。当MOT接GND时,选用Intel模式,此时该引脚是读允许输入引脚。
RESET—芯片复位引脚。
IRQ—中断请求输出。用作处理器的中断申请输入。只要引起中断的状态位置位,并且相应中断使能位也置位,IRQ将一直保持低电平,处理器程序通常读取C存储器来清除IRQ引脚输出,RESET引脚也会清除未处理的中断。没有中断发生时,IRQ为高阻状态,可将多个中断器件接到一条IRQ总线上,只要它们均为漏极开路输出即可。IRQ引脚为漏极开路输出,需要使用一个外接上拉电阻与SQW—方波输出引脚。当供电电压
VCC相连。
VCC大于4.25V时,SQW引脚可输出方波。
2.5 1602LCD液晶屏显示电路设计
1602LCD液晶屏显示电路如下图2—5所示:
1602液晶为5V电压驱动,带背光,可显示2行,每行16个字符,不能显示汉字,内置含128个字符的ASCII字符集字库,只有并行接口,无串行接口。接口说明如下:(1)液晶1,2端为电源;15,16为背光电源;为防止直接加5V电压烧坏背光灯,在15脚串接一个1K电阻用于限流。
(2)液晶3端为液晶对比度调节端,通过一个10K电位器接地来调节液晶显示对比度。首次使用时,在液晶上电状态下,调节至液晶上面一行显示出黑色小格为止。
(3)液晶4端为向液晶控制器写数据/写命令选择端,接单片机的P3.5口。
(4)液晶5端为读/写选择端,因为我们不从液晶读取任何数据,只向其写入命令和显示数据,因此此端始终选择为写状态,即低电平接地。
(5)液晶6端为使能信号,是操作时必须的信号,接单片机的P3.4口。
2.6 蜂鸣器电路设计
蜂鸣器电路如下图2—6所示:
蜂鸣器电路接在单片机的P2.3引脚上,当该引脚一个低电平,三极管导通,蜂鸣器发出声音作为闹铃。
2.7 按键调整电路设计
按键调整电路如下图2—7所示:
四个独立键盘均采用查询方式,将按键的一端接地,另一端各接一根输入线直接与STC89C52的I/O口相连。当按键闭合时,相当于该I/O口通过按键与地相连,变成低电平,单片机通过检测I/O口的电平状态,即可识别出按下的键。通过四个键实现参数的调节,S1为功能选择键,S2为数值增大键,S3为数值减小键,S4为闹钟查看键。
三、软
件
设
计
3.1 系统程序流程图设计
流程图1:实验主程序流程图
流程图2:定时中断程序流程图
流程图3:调时功能流程图
3.2 程序设计
#include
//延时函数 {
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);} void di()
//蜂鸣器报警声音 {
beep=0;
delay(100);
beep=1;} void
write_com(uchar com)
//写液晶命令函数
{
rs=0;
lcden=0;
P0=com;
delay(3);
lcden=1;
delay(3);
lcden=0;} void write_data(uchar
data)
//写液晶数据函数 {
rs=1;
lcden=0;
P0=data;
delay(3);
lcden=1;
delay(3);
lcden=0;} void
init()
//初始化函数 {
uchar
num;
EA=1;
//打开总中断
EX1=1;
//开外部中断1
IT1=1;
//设置负跳变沿触发中断
flag1=0;
//变量初始化
t0_num=0;
s1num=0;
week=1;
dula=0;
//关闭数码管显示
wela=0;
lcden=0;
rd=0;/*以下几行在首次设置DS12C887时使用,以后不必再写入
write_ds(0x0A,0x20);
//打开振荡器
write_ds(0x0B,0x26);
//设置24小时模式,数据二进制格式,开启闹铃中断
set_time();
//设置上电默认时间
---------------*/
write_com(0x38);
//1602液晶初始化
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
//写入液晶固定部分显示
{
write_data(table[num]);
delay(1);}
write_com(0x80+0x40);
for(num=0;num<11;num++)
{
write_data(table1[num]);
delay(1);
} } void write_sfm(uchar add,char data)
{ //1602液晶刷新时分秒函数,4为时,7为分,10为秒
char
shi,ge;
shi=data/10;
ge=data%10;
write_com(0x80+0x40+add);
write_data(0x30+shi);
write_data(0x30+ge);} void
write_nyr(uchar add,char
data)
{
//1602液晶刷新年月日函数,3为年,6为月,9为日
char
shi,ge;
shi=data/10;
ge=data%10;
write_com(0x80+add);
write_data(0x30+shi);
write_data(0x30+ge);void
write_week(char we)
//写液晶星期显示函数 {
write_com(0x80+12);
switch(we)
{
case 1:
write_data('M');delay(5);
write_data('O');delay(5);
write_data('N');
break;
case 2:
write_data('T');delay(5);
write_data('U');delay(5);
write_data('E');
break;
case 3:
write_data('W');delay(5);
write_data('E');delay(5);
write_data('D');
break;
case 4:
write_data('T');delay(5);
write_data('H');delay(5);
write_data('U');
break;
case 5:
write_data('F');delay(5);
write_data('R');delay(5);
write_data('I');
break;
case 6:
write_data('S');delay(5);
write_data('A');delay(5);
write_data('T');
break;
case 7:
write_data('S');delay(5);
write_data('U');delay(5);
write_data('N');
break;
} } void keyscan(){ if(flag_ri==1){
//这里用来取消闹钟报警,按任意键取消报警
if((s1==0)||(s2==0)||(s3==0)||(s4==0))
{
delay(5);
if((s1==0)||(s2==0)||(s3==0)||(s4==0))
{
while(!(s1&&s2&&s3&s&s4));di();
flag_ri=0;
//清除报警标志
}
}
}
if(s1==0)
//检测s1
{
delay(5);
if(s1==0)
{
s1num++;
//记录按下次数
if(flag1==1)
if(s1num==4)
s1num=1;
flag=1;
while(!s1);di();
switch(s1num)
{
//光标闪烁点定位
case 1: write_com(0x80+0x40+10);
write_com(0x0f);
break;
case 2: write_com(0x80+0x40+7);
break;
case 3: write_com(0x80+0x40+4);
break;
case 4: write_com(0x80+12);
break;
case 5: write_com(0x80+9);
break;
case 6: write_com(0x80+6);
break;
case 7: write_com(0x80+3);
break;
case 8: s1num=0;
write_com(0x0c);
flag=0;
write_ds(0,miao);
write_de(2,fen);
write_ds(4,shi);
write_ds(6,week);
write_ds(7,day);
write_ds(8,month);
write_ds(9,year);
break;
}
}
}
if(s1num!=0)
//只有当s1按下后,才检测s2和s3
{
if(s2==0)
{
delay(1);
if(s2==0)
while(!s2);di();
switch(s1num)
{
//根据功能键次数调节相应数值
case 1: miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+10);
break;
case 2: fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
break;
case 3: shi++;
case 4:
case 5:
case 6:
case 7:
}
}
}
if(s3==0)
{
delay(1);
if(shi==24)
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+4);
break;week++;
if(week==8)
week=1;
write_week(week);
write_com(0x80+12);
break;day++;
if(day==32)
day=1;
write_nyr(9,day);
write_com(0x80+9);
break;month++;
if(month==13)
month=1;
write_nyr(6,month);
write_com(0x80+6);
break;year++;
if(year==100)
year=0;
write_nyr(3,year);
write_com(0x80+3);
break;
if(s3==0)
{
while(!s3);di();
switch(s1num)
{
//根据功能键次数调节相应数值
case 1: miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
break;
case 2: fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
break;
case 3: shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
break;
case 4: week--;
if(week==0)
week=7;
write_week(week);
write_com(0x80+12);
break;
case 5: day--;
if(day==0)
day=31;
write_nyr(9,day);
write_com(0x80+9);
break;
case 6: month--;
if(month==0)
month=12;
write_nyr(6,month);
write_com(0x80+6);
break;
case 7: year--;
if(year==-1)
year=99;
write_nyr(3,year);
write_com(0x80+3);
break;
}
}
}
}
if(s4==0)
//检测s4
{
delay(5);
if(s4==0)
{
flag1=~flag1;
while(!s4);di();
if(flag1==0)
{
//退出闹钟设置时保存数值
flag=0;
write_com(0x80+0x40);
write_data(' ');
write_data(' ');
write_com(0x0c);
write_ds(1,miao);
write_ds(3,fen);
write_ds(5,shi);
}
else
{
//进入闹钟设置
read_alarm();
//读取原始数据
miao=amiao;
//重新赋值用以按键调节
fen=afen;
shi=ashi;
write_com(0x80+0x40);
write_data('R');
//显示标志
write_data('i');
write_com(0x80+0x40+3);
write_sfm(4,ashi);
//送液晶显示闹钟时间
write_sfm(7,afen);
write_sfm(10,amiao);
}
}
} } void write_ds(uchar add,uchar
data){
//写12C887函数
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P0=add;
//先写地址
dsas=0;
dsrw=0;
P0=data;
//再写数据
dsrw=1;
dsas=1;
dscs=1;} uchar
read_ds(uchar add){
//读12C887函数
uchar
ds_data;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
//先写地址
dsas=0;
dsds=0;
P0=0xff;
ds_data=P0;
//再读数据
dsds=1;
dsas=1;
dscs=1;
return ds_data;} /*---首次操作12C887时给予寄存器初始化-----void set_time(){
//首次上电初始化时间函数
write_ds(0,0);
write_ds(1,0);
write_ds(2,0);
write_ds(3,0);
write_ds(4,0);
write_ds(5,0);
write_ds(6,0);
write_ds(7,0);
write_ds(8,0);
write_ds(9,0);}----------------------*/
void
read-alarm(){
//读取12C887闹钟值
amiao=read_ds(1);
afen=read_ds(3);
ashi=read_ds(5);} void main()
//主函数 {
init();
//调用初始化函数
while(1)
{
keyscan();
//按键扫描
if(flag_ri==1)
//当闹钟中断时进入这里
{
di();
delay(100);
di();
delay(500);
}
if(flag==0&&flag1==0)
//正常工作时进入这里
{
keyscan();
//按键扫描
year=read_ds(9);
//读取12C887数据
month=read_ds(8);
day=read_ds(7);
week=read_ds(6);
shi=read_ds(4);
fen=read_ds(2);
miao=read_ds(0);
write_sfm(10,miao);
//送液晶显示
write_sfm(7,fen);
write_sfm(4,shi);
write_week(week);
write_nyr(3,year);
write_nyr(6,month);
write_nyr(9,day);
}
} } void
exter()interrupt 2
//外部中断1服务程序 {
uchar
c;
//进入中断表示闹钟时间到
flag_ri=1;
//设置标志位,用于大程序中报警提示
c=read_ds(0x0c);
//读取12C887的C寄存器表示响应了中断 }
_______________________________________________________________________________ 以下为define.h源代码:
_______________________________________________________________________________ #define uchar unsigned char #define uint unsigned int sbit dula=P2^6;sbit wela=P2^7;sbit rs=P3^5;sbit lcden=P3^4;sbit s1=P3^0;
//功能键 sbit s2=P3^1;
//增大键 sbit s3=P3^2;
//减小键 sbit s4=P3^6;
//闹钟查看键 sbit rd=P3^7;sbit beep=P2^3;
//蜂鸣器 sbit dscs=P1^4;sbit dsas=P1^5;sbit dsrw=P1^6;sbit dsds=P1^7;sbit dsirq=P3^3;bit flag1,flag_ri;
//定义两个位变量
uchar count,s1num,flag,t0_num;
//其他变量定义 char miao,shi,fen,year,month,day,week,amiao,afen,ashi;uchar code
table[]=“201-
”;
//液晶固定显示内容 uchar code
table1[]=“
:
:
”;
void write_ds(uchar,uchar);
//函数申明 void set_alarm(uchar,uchar,uchar);void read_alarm();uchar read_ds(uchar);void set_time();
四、心
得
体
会
在本次电子时钟设计中对单片机的内部结构有了一定的了解,熟悉了各个引脚的功能,同时熟知了1602LCD液晶、DS12C887时钟芯片的使用,以及各种电路的功能。
通过此次课程设计,无论是从软件方面还是硬件方面,都进一步学习和巩固了程序的总体设计和单片机的应用。在软件方面,进一步熟悉了各条指令的功能及用法,定时、中断的用法,更深一步学习了用C语言编写实现电子时钟的功能。在硬件方面,进一步熟悉并使用了keil软件,在keil中编程,调试,运行;对电路的一些基本结构和设计有了更深一步的了解。在整个设计过程中,虽然出现了很多问题,有时确实叫人很心烦,但在发现问题后努力去解决,并获得成功,这时会感到无比的快乐和具有成就感。只有自己动手去做,去应用,才能将学到的知识变成自己的。
程序不要光看不写,一定要自己写一次。最开始的时候,可能自己啥都不懂,这时可以抄人家的程序过来。但在抄的时候一定要看看每一句是干什么用的,来达到什么目的,运行后有什么后果,看明白了之后,就要自己写一次。此时会发现,原来看明白别人的程序很容易,但到自己写的时候却一句也写不出来,这就是差距。
单片机提高重在实践,想要学好单片机,软件编程必不可少。但是熟悉硬件对于学好单片机也是非常重要的。如何学习好硬件,动手实践是必不可少的。我们可以通过自己动手做一个自己的电子制作,通过完成它,以提高对一些芯片的了解和熟练运用。这样我们就可以多了解一些芯片的结构。
我学习的目标是希望在若干年以后能够独立设计一个复杂的系统,包括硬件电路和软件部分。总之,通过这次电子技术设计我学到了许多,似乎离自己的目标又近了一步。
参
考
文
献
[1]郭天祥.51单片机C语言教程.电子工业出版社.2009 [2]谭浩强.C程序设计.清华大学出版社.1991 [3]孙育才 王荣兴
孙华芳.ATMEL新型AT89S52系列单片机及其应用.清华大学出版社.2006 [4]谢维成.单片机原理及应用与51程序设计.清华大学出版社.2006
[5]鲍宏亚.MCS—51系列单片机应用系统设计及实用技术.中国宇航出版社.2005 [6]赵文博
刘文涛.单片机语言C51程序设计.人民邮电出版社.2006 [7]求是科技.8051系列单片机C程序设计.人民邮电出版社.2006