⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.asm

📁 单片机实现的时钟程序
💻 ASM
字号:
;*********************************************************
;           带有时间设置和秒显示的数字闹钟(1个闹钟功能)
;  Date :  2008.3.15     11。0592MHZ晶振                                  
;  Create by :lus2008		email: yrg200510@126.com
; P3.0 分钟调整键  P3.3小时 调整键  P3.2 设置键(闹钟设置) P3.4 p3.5 闹钟时间到输出
;**************************************************************

;*********************************************************
;                 变量地址分配
;********************************************************* 
DisplayBuffer       equ  30h	;设置显示缓冲区的地址为30h-35h共6个字节 
OneSecondCounter    equ  39h	;设置1秒计数器的地址,1秒计数器是用来计数1秒内计时器的中断次数
Hour                equ  3ah	;设置小时计数器的地址
Minute              equ  3bh	;设置分钟计数器的地址
Second              equ  3ch	;设置秒计数器的地址
ClockMode           equ  20h.0	;模式(正常走时/闹时)设置寄存器地址,值为0时正常走时,为1时闹时设定
AlarmOnOff          equ  20h.1	;闹钟开启/关闭标志,为0关闭,为1开启
AlarmTimeOn         equ  20h.2	;此位为1时表示闹时时间到
DispHour            equ  21h	;设置小时显示寄存器的地址
DispMinute          equ  22h	;设置分钟显示寄存器的地址
DispSecond          equ  23h	;设置秒显示寄存器的地址
AlarmHour           equ  2eh	;设置闹时小时计数器的地址
AlarmMinute         equ  2fh	;设置闹时分钟计数器的地址
AlarmSetKey         bit  P3.2	;闹钟设置键
MinuteKey           bit  P3.4	;定义分设置键
HourKey             bit  P3.3	;定义小时设置键
RelayOut            equ  P3.0	;定义输出引脚,扬声器控制
RelayOut1           equ  P3.5	;定义输出引脚,继电器1控制
;**********************************************************************
;                     程序开始,初始化
;**********************************************************************
	org 	00h
	ajmp   	Start		;程序开始
	org	0bh     	;Timer0中断向量地址
	ajmp 	TimeInt		;跳到中断处理程序
	org 	0020h
Start:               		;以下为初始化程序,为各个变量赋初值
	mov 	sp,#70h
	setb 	RelayOut 	;输出高电平,闹钟服务程序驱动口
	setb 	RelayOut1 	;输出高电平,闹钟服务程序驱动口
	mov 	OneSecondCounter,#125	;1秒钟中断次数
	;
        mov 	Hour,#12		;开机时间
        mov 	Minute,#00		
        mov 	Second,#00		;设置上电时时钟显示的初值
         ;
        mov 	AlarmHour,#06	;开机时闹钟默认时间
        mov 	AlarmMinute,#00	;设置上电时闹时时间的初值
         ;
        clr 	AlarmOnOff	;上点复位后闹时功能处于关闭状态
        clr 	ClockMode	;正常走时模式
        clr 	AlarmTimeOn	;闹钟时间还没有到
        setb 	RelayOut;          清闹时输出
        setb 	RelayOut1;          清闹时输出
         
;************************************
;   定时器初始化,定时器0方式1,8ms
	;th0=0e3  tl0=33	
;   
;************************************
         mov 	tmod,#00000001b	;
         mov 	th0,#0E3h		;                  
         mov 	tl0,#33h		;
         mov 	ie,#82h		;开全局中断
         setb  	tr0		;开定时中断,启动定时器
;*****************************************
;         以下为主程序,按键扫描
;*****************************************
MainLoop:
	jb 	AlarmSetKey,CheckMinuteKey;闹时设置键按下了吗?没有则转去检测秒设置键篇p3.2
	lcall 	Delay2
        jb 	AlarmSetKey,CheckMinuteKey	;按下的时间超过15ms吗?
	setb 	ClockMode		       ;置为闹时设置模式
        call 	AlarmSet
CheckMinuteKey:
        jb 	MinuteKey,CheckHourKey	;分设置键按下了吗?没有则转去检测小时设置键
        call 	Delay2
        jb 	MinuteKey,CheckHourKey	;按下的时间超过15ms吗? 				;如按下调用蜂鸣器发音程序
        mov 	a,Minute
        add 	a,#1;                       如果按下则将分钟加一                          十进制调整
        mov 	Minute,a;
        cjne 	a,#3ch,NotOver1;           到60分钟了吗?
        mov 	Minute,#0;                  到60分钟则将分钟清0
NotOver1:                                ;以下等待按键释放及防抖动
        jnb  	MinuteKey,$
CheckHourKey:
        jb 	HourKey,CheckAlarm		;小时设置键按下了吗?没有则转去闹时状态检测
        call 	Delay2
        jb 	HourKey,CheckAlarm	;按下的时间超过15ms吗?  				;如按下调用蜂鸣器发音程序
        mov 	a,Hour
        add 	a,#1			;如果按下则将小时加1
        mov 	Hour,a
        cjne 	a,#18h,NotOver2
        mov 	Hour,#0			;到24小时则将小时清0
NotOver2:                                ;以下等待按键释放及防抖动
        jnb  	HourKey,$
CheckAlarm:          ;
        jnb 	AlarmTimeOn,ToReturn	;闹钟时间到没有
        call 	AlarmProcess		;闹钟子程序
ToReturn:
        ajmp 	MainLoop

;**********************************************
;  定时器Timer0中断服务程序(此程序每8ms执行一次)
;**********************************************
TimeInt:
          mov 	th0,#0E3h;                      重新加载定时参数
          mov 	tl0,#33h;
          push 	acc
          push 	psw;                           保护累加器及程序状态字的内容
          setb 	rs0;                           选择工作寄存器组1,
          clr  	rs1;                           这样可保护原工作寄存器组(0组)的内容
          djnz 	OneSecondCounter,NotoneSecond; 中断了125次了吗?即够1秒了吗?
          mov 	OneSecondCounter,#125;          如够1秒则重新设置"OneSecondCounter"计数器
          call 	Clock               ;          调用将时钟内容加1秒的子程序
          call 	ConvertoBuffer      ;          调用将时钟内容转换到显示缓冲区子程序
NotoneSecond:
          call 	ScanDisplay         ;          调用扫描显示子程序
          pop  	psw
          pop  	acc                 ;          恢复累加器及程序状态字的内容
          reti                     ;          中断返回
;*********************************************
;           扫描显示子程序,将缓冲区的数值显示在对应的数码管上
;*********************************************
ScanDisplay:
	MOV   	R1,#DisplayBuffer       ;指向显示数据首址,利用c语言指针原理读取缓冲区的数值
					;子程序ConvertoBuffer已经将相应的值存放在displaybuffer的缓冲区中
      	MOV   	R4,#11011111b           ;扫描控制字初值,显示右边第一个数码管
PLAY: 	MOV   	A,R4                    ;扫描字放入A
   	MOV   	P2,A                    ;从P2口输出,p2口的低六位分别控制对应的六个数码管的显示
        MOV   	A,@R1         		;取显示数据到A
        MOV   	DPTR,#TAB     ;取段码表地址
        MOVC  	A,@A+DPTR     ;查显示数据对应段码
	MOV   	P0,A          ;段码放入P0口,具体显示位
	
	INC   	R1            ;指向下一地址
       	MOV   	A,R4            ;扫描控制字放入A
	;显示时分秒分隔位

	JB	ACC.1,LPP1	;显示时分位
	CLR	P0.7
	;CALL	Delay
	;SETB	P0.7
LPP1:	JB	ACC.3,LPP2	;显示秒分位
	CLR	P0.7
	;CALL	Delay
;	SETB	P0.7
LPP2:   
 	JNB   	ACC.7,ENDOUT    ;扫到第六位时结束
       	RR   	A               ;A中数据循环左移
       	MOV   	R4,A            ;放回R4内
	LCALL 	Delay		;每位数码管显示间隔时间为2ms
	SETB	P0.7		;关闭分位显示点
 	AJMP  	PLAY            ;跳回PLAY循环
;ENDOUT:	SETB  	P2.0           ;一次显示结束,P2口复位
 ;      	MOV    	P0,#0FFH       ;P0口复位
ENDOUT:	MOV    	P0,#0FFH       ;P0口复位
	RET                      ;子程序返回
TAB: 	DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,7FH,0B7H,0FFH
;共阳段码表 "0""1""2" "3""4""5""6""7" "8""9"".""=""不亮"

;****************************************************
;            时钟内容加1秒的子程序(1秒时间到)
;****************************************************
Clock:
	mov a,Second	;将原秒值送入a
        add a,#1	;加1秒
          
        mov Second,a
        cjne a,#3cH,NotOverFlow	;够60秒了吗?
        mov Second,#0;                    够了则将秒值清0
          ;
        mov a,Minute
        add a,#1
        mov Minute,a;                     分钟加1
        cjne a,#3cH,NotOverFlow;          够60分了吗?
        mov Minute,#0;                    够了则将分值清0
        ;
        mov a,Hour
        add a,#1
        mov Hour,a;                       小时加1
        cjne a,#18H,NotOverFlow;          够24小时吗?
        mov Hour,#0;                      够了则将小时值清0
NotOverFlow:
        jnb AlarmOnOff,NotAlarm;          闹钟开启了吗?如没有开启则无需理会是否到闹时时间
        mov a,Second
        jnz NotAlarm;                     秒为零吗?
        mov a,Minute
        cjne a,AlarmMinute,NotAlarm;      时间分钟值和闹时设置分钟值相等吗?
        mov a,Hour
        cjne a,AlarmHour,NotAlarm;        时间小时值和闹时设置小时值相等吗?
        setb AlarmTimeOn;                 到了闹时时间则将“闹时时间到”标志设为1*******
NotAlarm:
        ret
          ;
;**************************************************************************
;            将时钟内容或闹时设置值转换到显示缓冲区子程序
;**************************************************************************
ConvertoBuffer:
        mov r1,#DisplayBuffer
        jb ClockMode,DispAlarmSet;        判断时钟模式,以决定是显示实时时间还是闹时时间,ClockMode,0为正常走时,1为闹钟设定
        ;
	mov a,Second;
        mov DispSecond,a
	;
        mov a,Minute;
        mov Dispminute,a
	;
        mov a,Hour;
        mov DispHour,a;                   显示实时时间,显示寄存器地址
        ;
        ajmp Convert			;在数码管显示缓冲区的数值
DispAlarmSet:				;闹钟设定
        jb AlarmOnOff,AlarmOn		;闹钟开关,0为关,1为开
        mov DispSecond,#00h
        ajmp Next
AlarmOn:
        mov DispSecond,#11;             显示闹时时间及显示闹钟状态:显示“00”表示关闭闹钟,
Next:                                    ;“11”表示开启闹钟
        mov a,AlarmMinute;
        mov Dispminute,a;
        mov a,AlarmHour;
        mov DispHour,a;
                         ;			将数值显示到数码管
Convert:
         
	mov a,DispSecond;                取秒值,将待显示的数值存储到缓冲区
	mov b,#10
        div ab                              
	mov @r1,b               
        inc r1;                          缓冲寄存器的地址加1
	mov @r1,a                          
        inc r1
        mov a,DispMinute
        mov b,#10
        div ab                            
        mov @r1,b;                       
        inc r1;                          缓冲寄存器的地址加1
        mov @r1,a;                       将秒值的十位值存入缓冲区
          ;                                
        inc r1
        mov a,DispHour
        mov b,#10
        div ab                             
        mov @r1,b;                       
        inc r1;                          缓冲寄存器的地址加1
        mov @r1,a;                       将秒值的十位值存入缓冲区          
        ret;                        

;**************************************************
;                   闹钟时间设置子程序
;**************************************************
AlarmSet:
	jnb  AlarmSetKey,$
        call Delay2;                     等待“AlarmSetKey”键释放
CheckArmMinuteKey:          ;
        jb MinuteKey,CheckArmHourKey	;分设置键按下了吗?没有则转去检测小时设置键 p3.5
	call 	Delay2
        jb 	MinuteKey,CheckArmHourKey	;按下的时间超过500ms吗?
        setb AlarmOnOff			;闹钟开
        mov a,AlarmMinute
        add a,#1			;如果按下则将分钟加1,十进制调整
        mov AlarmMinute,a
        cjne a,#3ch,ArmNotOver1	;到60分钟了吗?
        mov AlarmMinute,#0			;到60分钟则将分钟清0
ArmNotOver1:                             ;以下等待按键释放及防抖动
        jnb  MinuteKey,$		;等待对应设置时间的按键释放
CheckArmHourKey:
	jb HourKey,AlarmSetEnd;         小时设置键按下了吗?没有则返回反复检测
	call 	Delay2
        jb 	HourKey,AlarmSetEnd	;按下的时间超过500ms吗?
	setb AlarmOnOff
	mov a,AlarmHour
	add a,#1;                       如果按下则将小时加1
	mov AlarmHour,a
	cjne a,#18h,ArmNotOver2
	mov AlarmHour,#0;               到24小时则将小时清0
ArmNotOver2:                             ;以下等待按键释放及防抖动
	jnb  HourKey,$
AlarmSetEnd:
	jb AlarmSetKey,AlarmSet;        闹钟设置 完毕了吗?
	call 	Delay2
        jb 	AlarmSetKey,AlarmSet	;按下的时间超过500ms吗?
	jnb AlarmSetKey,$
	clr ClockMode;                  从设置模式转为走时模式
	ret

;**************************************************
;             闹时服务子程序
;**************************************************
AlarmProcess:
	mov	r2,#10
loop2:	
	cpl  	RelayOut
	cpl  	RelayOut1
	call	Delay1
	jb 	AlarmSetKey,AlarmReturn;   停止闹时键(即闹时设置键)按下了吗?
	call	Delay2
	jb 	AlarmSetKey,AlarmReturn
	clr 	AlarmOnOff		;关闭闹钟
	jnb 	AlarmSetKey,$		
	setb  	RelayOut		;如停止闹时键按下则停止闹时
	setb  	RelayOut1
	clr 	AlarmTimeOn;
	ajmp	loop6
AlarmReturn:
	dec	r2
	mov	a,r2
	cjne	a,#00h,loop2
	setb  	RelayOut		;如停止闹时键按下则停止闹时
	setb  	RelayOut1
	clr 	AlarmOnOff		;关闭闹钟
	clr 	AlarmTimeOn
loop6:	ret
;**************************************************
;          延时子程序
;**************************************************
Delay:
	mov r6,#2		;延时产生1ms,数码管 动态 显示间隔时间
del:	mov r7,#249
	djnz r7,$
	djnz r6,del
	ret
	;
Delay1:	
	mov r5,#2	;延时间产生1s,扬声器的震动间隔时间
de3:	mov r6,#200
de2:	mov r7,#250
	djnz r7,$
	djnz r6,de2
	djnz r5,de3
	ret

Delay2:
	mov r6,#10		;延时产生15ms,按键防止抖动时间
de4:	mov r7,#245
	djnz r7,$
	djnz r6,de4
	ret
	end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -