51单片机闹钟时分显示输出子程序求解
shuchu:mov r7,#8 ;输出子程序
lop3:rrc a
clr p3.4
mov p3.5,c
setb p3.4
djnz r7,lop3
ret
dis:mov dptr,#tab
movc a,@a+dptr
ret
以上得;p3.4循环,p3.5输出进位状态,那种显示器是这种信号控制的呢? 看你这貌似164的驱动 要看看硬件的吧,况且看汇编比较头大 网上下载的程序,在学习中,没有电路图,所以理解不了这个程序. org 0000h //程序从0000H从始(伪指令)
jmp main //无条件转移到main
org 000bh //程序从000bh从始
jmp ts //无条件转移到子程序ts (定时器0中断服务)
org 0030h //程序从0030h从始
main:mov 70h,#2 //传送立即数2到直接地址70h
mov tmod,#11h //传送立即数11h到(tmod 定时器方式选择寄存器)
mov tl0,#0b0h //传送立即数0b0h到TL0 定时器 0低8位
mov th0,#3ch //传送立即数3ch到TH0 定时器 0高8位
setb ea //置位中断总控制
setb tr0 //置位定时器0
setb et0 //置位定时器0中断
setb p1.0 //置位P1.0
mov r0,#0 //传送立即数0到R0
mov 59h,#0 //传送立即数0到直接地址59H
clr p2.0 //清除P2.0
clr p2.1 //清除P2.1
clr p2.2 //清除P2.2
clr p3.6 //清除P3.6
mov 65h,#0 //传送立即数0到直接地址65H
mov 66h,#0 //传送立即数0到直接地址66H
mov 60h,#0 //传送立即数0到直接地址60H
lcall displaymin //长调用时分显示子程序
mov 61h,#0 //传送立即数0到直接地址61H
lcall displaymin //长调用时分显示子程序
setkey:setb p1.7 //置位P1.7
jb p1.2,shizhong //如果p1.2为1则转移到shizhong
lcall keydelay1 //长调用延时子程序
jb p1.2,shizhong //如果p1.2为1则转移到shizhong
jnb p1.2,$ //如果p1.2为0则转移到本条指令的起始位置
setb p2.0 ;设置灯亮(置位)
setb p2.1;设置分钟灯亮(置位)
clr tr0 //定时器0清零
lcall keydelay1 ;长调用延时 1
;设置分钟
minset:jb p1.3,lop1 ;如果P1.3为1则转移到LOP1
lcall keydelay1 ;长调用延时子程序
jb p1.3,lop1 ;如果p1.3为1则转移到lop1
jnb p1.3,$ ;如果p1.3为0则转移到本条指令的起始位置
inc 60h ;直接地址加1
lcall displaymin ;长调用时分显示子程序
mov a,60h
cjne a,#60,minset ;比较两数不相等则转移到设置分钟
mov 60h,#0
lcall displaymin ;长调用时分显示子程序
lop1:jb p1.2,minset ;如果p1.2为1则转移到设置分钟
lcall keydelay1 ;长调用延时子程序1
jb p1.2,minset ;如果p1.2为1则转移到设置分钟
jnb p1.2,$ ;如果p1.2为0则转移到本条指令的起始位置
clr p2.1 ;p2.1清零
setb p2.2 ;设置小时灯亮 (p2.2置位)
;设置小时
hourset:jb p1.3,lop2 ;如果p1.3为1则转移到lop2
lcall keydelay1 ;长调用延时子程序
jb p1.3,lop2 ;如果p1.3为1则转移到lop2
jnb p1.3,$ ;如果p1.3为0则转移到本条指令起始位置
inc 61h ;直接地址加1
lcall displaymin ;长调用时分显示子程序
mov a,61h
cjne a,#24,hourset ;比较两个数不相等则转移到设置小时子程序
mov 61h,#0
lcall displaymin ;长调用时分显示子程序
lop2:jb p1.2,hourset ;如果p1.2为1则转移到设置小时子程序
lcall keydelay1 ;长调用延时子程序
jb p1.2,hourset ;如果p1.2为1则转移到设置小时子程序
jnb p1.2,$ ;如果p1.2为0则转移到本条指令起始位置
mov th0,#3ch ;传送立即数3cH到定时器0高8位
mov tl0,#0b0h ;传送立即数0B0H到定时器0低8位
mov r0,#0 ;传送立即数0到通用寄存器R0
shizhong:setb tr0;置位定时器0
clr p2.0 ;p2.0清零
clr p2.1 ;p2.1清零
clr p2.2 ;p2.2清零
lcall displaymin ;长调用时分显示子程序
;闹铃设置模块
naolingset:
jb p2.6,naoling ;闹铃设置开关按下,进行闹铃时间设置 (如果p2.6为1则转移到naoling)
lcall keydelay1 ;长调用延时子程序
jb p2.6,naoling ;如果p2.6为1则转移到naoling
jnb p2.6,$ ;如果p2.6为0则转移到本条指令起始位置
setb p3.6 ;闹铃设置灯亮(置位)
mov 70h,#1 ;传送立即数1到直接地址
setb p2.1 ;设置分钟灯亮 (置位)
mov a,65h
lcall ndisplaymin ;显示上次闹铃设置时间(长调用闹钟设置时间显示子程序)
mov a,66h
lcall ndisplaymin ;长调用闹钟设置时间显示子程序
nminset: jb p1.1,nlop1 ;如果p1.1为1则转移到nlop1
lcall keydelay1 ;长调用延时子程序
jb p1.1,nlop1 ;如果p1.1为1则转移到nlop1
jnb p1.1,$ ;如果p1.1为0则转移到本指令起始位置
inc 65h ;直接地址加1
lcall ndisplaymin ;显示设置分钟后的时间
mov a,65h
cjne a,#60,nminset ;比较两数不相等则转移到nminset
mov 65h,#0
lcall ndisplaymin
nlop1: jb p2.6,nminset ;再次按下闹铃设置开关时进行闹铃小时设置
lcall keydelay1
jb p2.6,nminset
jnb p2.6,$
clr p2.1 ;设置分钟灯灭
setb p2.2 ;设置小时灯亮
nhourset: jb p1.1,nlop2
lcall keydelay1
jb p1.1,nlop2
jnb p1.1,$
inc 66h
lcall ndisplaymin ;显示设置小时之后的时间
mov a,66h
cjne a,#24,nhourset
mov 66h,#0
lcall ndisplaymin
nlop2: jb p2.6,nhourset ;再次按下闹铃设置开关时跳回正常显示时间
lcall keydelay1
jb p2.6,nhourset
jnb p2.6,$
clr p3.6 ;闹铃设置灯灭
clr p2.1 ;分钟设置灯灭
clr p2.2 ;小时设置灯灭
mov 70h,#2
lcall displaymin ;显示正常时间
naoling:clr p3.6
jb p2.7,nlop6 ;闹铃开关按下时进入闹铃模块
lcall keydelay1
jb p2.7,nlop6
jmp setkey
;闹铃模块
mov a,61h
cjne a,66h,nlop6 ;比较小时是否与设定时间相同
nlop3: mov a,60h
cjne a,65h,nlop6 ;比较分钟是否与设定时间相同
sound:
jb p2.7,nlop6
lcall delay2
jnb p2.7,nlop4
jmp setkey
nlop4: clr p1.7 ;闹铃时间到时闹铃灯会闪烁
lcall keydelay1
jmp nlop3
setb p1.7
jmp setkey
nlop6: setbp1.7
jmp setkey
;各子程序模块
;时分进位子程序
min:inc 60h
mov r1,70h
cjne r1,#2,loop10
lcall displaymin
jnb p3.2,loop10
loop10: mov r4,60h
cjne r4,#60,looop1
mov 60h,#0
mov r1,70h
cjne r1,#2,hour
lcall displaymin
hour:inc 61h
mov r5,61h
mov r1,70h
cjne r1,#2,loop11
lcall displaymin
loop11: cjne r5,#24,looop1
mov 61h,#0
mov r1,70h
cjne r1,#2,looop1
lcall displaymin
looop1:
ret
;时分显示子程序
displaymin:mov a,60h
lcall hexbcd ; 长调用子程序hexbcd
mov 62h,a
anl a,#0fh ;与操作
lcall dis ;长调用查表子程序
lcall shuchu ;长调用输出子程序
mov a,62h
anl a,#0f0h ;与操作
swap a ;高低4位互换
lcall dis ;长调用查表子程序
lcall shuchu ;长调用输出子程序
displayhour:mov a,61h
lcall hexbcd ; 长调用子程序hexbcd
mov 63h,a
anl a,#0fh ;与操作
lcall dis ;长调用查表子程序
lcall shuchu ;长调用输出子程序
mov a,63h
anl a,#0f0h ;与操作
swap a ;高低4位互换
lcall dis ;长调用查表子程序
lcall shuchu ;长调用输出子程序
ret
;输出子程序
shuchu:mov r7,#8
lop3:rrc a ;带进位循环右移一位
clr p3.4 ;p3.4清零
mov p3.5,c
setb p3.4 ;置位
djnz r7,lop3 ;寄存器减1不为0则转移到lop3
ret ;返回
;查表
dis:mov dptr,#tab ;指定查表启始地址
movc a,@a+dptr ;变址寻址 查表
ret ;返回
;延时
keydelay1:mov r1,#2 ;延时子程序1
keydelay: ;延时子程序
lop6:mov r2,#50
lop5:mov r3,#250
lop4:nop
nop
djnz r3,lop4
djnz r2,lop5
djnz r1,lop6
ret ;从子程序返回
hexbcd:mov b,#10
div ab ;除法指令a/b =商A...余B
swap a ;累加器高低半字节互换(循环左移4次)
orl a,b ;逻辑或运算a+b
ret ;子程序返回
;闹铃设置时间显示子程序
ndisplaymin:mov a,65h
lcall hexbcd
mov 67h,a
anl a,#0fh
lcall dis
lcall shuchu
mov a,67h
anl a,#0f0h
swap a
lcall dis
lcall shuchu
ndisplayhour:mov a,66h
lcall hexbcd
mov 68h,a
anl a,#0fh
lcall dis
lcall shuchu
mov a,68h
anl a,#0f0h
swap a
lcall dis
lcall shuchu
ret ;从子程序返回
delay2:mov r1,#70 ;传送立即数70到寄存器 R1
llop:mov r2,#250 ;传送立即数250到寄存器 R2
llop1:nop ;空操作
nop ;空操作
djnz r2,llop1 ;寄存器R2减1,不为0,则转移到llop1
djnz r1,llop ;寄存器R1减1,不为0,则转移到llop
ret ;从子程序返回
;定时器0中断服务
ts:cjne r0,#10,loop1 ;比较#10,R0两数,不相等转移到loop1(定时器0中断服务)
cpl p1.0 ;P1.0取反
mov r0,#0 ;传送立即数0到寄存器R0
mov tl0,#0b0h ;传送立即数0b0H到定时器0低8位
mov th0,#3ch ;传送立即数3CH到定时器0高8位
inc 59h ;直接地址59H加1
mov r6,59h ;传送59H的内容到R6
cjne r6,#120,loop ;比较#120,R6两数,不相等转移到中断返回
mov 59h,#0 ;传送#0到59H
lcall min ;长转移到时分进位子程序
jmp loop ;转移到中断返回
loop1:inc r0 ;寄存器加1
mov tl0,#0b0h ;传送立即数到定时器0低8位
mov th0,#3ch ;传送立即数到定时器0高8位
loop:reti ;从中断返回
;数据表
tab:db 0fch,60h,0dah,0f2h,66h,0b6h,0beh,0e0h,0feh,0f6h,0eeh,03eh,09ch,7ah,9eh,8eh ;数据表
end {:sweat:}额,真心不太会汇编 tony_sgt 发表于 2014-3-9 13:11
看你这貌似164的驱动
查了下164驱动的电路图,应该是类似的硬件,本人菜鸟,之前没看过164这样的驱动. 没办法,英语不好,感觉学c51鸭梨很大.汇编的指令好记点,所以在用力的学汇编了! 表示不用汇编,感觉太晦涩了 表示汇编一看就头大,还是C语言好看。。。本人彻底不懂汇编。。。。。。。。。
页:
[1]