liyute 发表于 2014-3-9 04:32:51

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输出进位状态,那种显示器是这种信号控制的呢?

tony_sgt 发表于 2014-3-9 13:11:12

看你这貌似164的驱动

dlmaowf 发表于 2014-3-9 23:51:21

要看看硬件的吧,况且看汇编比较头大

liyute 发表于 2014-3-10 10:14:35

网上下载的程序,在学习中,没有电路图,所以理解不了这个程序.

liyute 发表于 2014-3-10 10:15:46

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

zjk 发表于 2014-3-10 10:20:58

{:sweat:}额,真心不太会汇编

liyute 发表于 2014-3-10 10:23:29

tony_sgt 发表于 2014-3-9 13:11
看你这貌似164的驱动

查了下164驱动的电路图,应该是类似的硬件,本人菜鸟,之前没看过164这样的驱动.

liyute 发表于 2014-3-10 10:26:20

没办法,英语不好,感觉学c51鸭梨很大.汇编的指令好记点,所以在用力的学汇编了!

Smartist 发表于 2014-3-11 13:20:45

表示不用汇编,感觉太晦涩了

lswhome 发表于 2014-3-11 23:50:34

表示汇编一看就头大,还是C语言好看。。。本人彻底不懂汇编。。。。。。。。。
页: [1]
查看完整版本: 51单片机闹钟时分显示输出子程序求解