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

📄 time1.asm

📁 电子钟的程序
💻 ASM
字号:
;***********************************
 ;博圆单片机培训[博圆单片机初学之路]
 ;2005年10月10日
 ;Email: bypxmcu@126.com
 ;本程序采用的是六位数[最好采用八位码数,在时钟分钟秒钟之间用短横线隔开,如23时45分02秒,写为23-45-02]
  ;使用P1.7[选择键]、P1.6[时钟增1]、P1.5[分钟增1]、P1.4[秒钟增1]
 ;*******************************************
 SEC  DATA  51H   ;定义秒钟计数器使用51H内存区
 MIN  DATA  53H   ;定义分钟计数器使用53H内存区
 HOU  DATA  55H   ;定义时钟计数器使用55H内存区
 ;*********************************************
        ORG  0000H
        AJMP MAIN     ;跳过中断地址
        ORG  000BH
        LJMP TIME     ;调用计时中断子程序
        ORG  0100H 
   
  MAIN: MOV  SP,#60H    ;初始化堆栈
        ;给定时器0赋初值
        MOV  TMOD,#001H  ;使用16位无分频模式[方式1 M1=0 M0=1]
        MOV  TH0,#04CH   ;初始化定时器0的溢出间隔时间为50ms 
        MOV  TL0,#000H   ;TH为位 TL为低位
        SETB EA         ;启用全局中断
        SETB ET0        ;启用定时器0中断
        SETB TR0        ;启用定时器0
        MOV  R0,#014H   ;初始化定时计数为20[014H]次,014H为十六进制码,请查阅[附录12]
        MOV  R1,#00H    
        MOV  R6,#0AH    ;
        MOV  R7,#0AH
        MOV  SEC,#00H   ;初始化秒钟计数器
        MOV  MIN,#00H   ;初始化分钟计数器
        MOV  HOU,#00H   ;初始化时钟计数器
        
  ;***********************************************      
  ;主程序区的主循环体
  ;数字显示程序主体
  ;入口参数:SEC[秒],MIN[分],HOU[时]
  ;时间传送参数SEC[秒],MIN[分],HOU[时]
  ;*************************************************
  DSUP: ;扫描并显示秒钟的个位         
        MOV  DPTR,#TAB1   ;获得第一字形码表的启始地址[主要是个数字]
        MOV  A,SEC        ;从字形码表取出秒钟的个位显示字模
        MOVC A,@A+DPTR    ;查表
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11111110B;关闭其它位,点亮秒钟个位
        LCALL YSH2S       ;短时间延时 这个时间的长短是关键如果显示有抖动的感觉请时间继续短
       ;扫描并显示秒钟的十位
        MOV  DPTR,#TAB2   ;获得第二字形码表的启始地址[主要是个数字]
        MOV  A,SEC        ;从字形码表取出秒钟的十位显示字模
        MOVC A,@A+DPTR    ;查表
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11111101B;关闭其它位,点亮秒钟十位
        LCALL YSH2S  
       ;显示'——'
        MOV  A,#0BFH
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11111011B;关闭其它位,点亮秒钟十位
        LCALL YSH2S  
       
        ;扫描并显示分钟的个位
        MOV  DPTR,#TAB1
        MOV  A,MIN       ;从字形码表取出个位分钟显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A        ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11110111B;关闭其它位,点亮分钟个位 
        LCALL YSH2S     ;短时间延时 这个时间的长短是关键如果显示有抖动的感觉请时间继续短
        ;扫描并显示分钟的十位
        MOV  DPTR,#TAB2 
        MOV  A,MIN       ;从字形码表取出十位显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A       ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11101111B
        LCALL YSH2S  
        ;显示'——'
        MOV  A,#0BFH
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11011111B;关闭其它位,点亮秒钟十位
        LCALL YSH2S
       ;扫描并显示时钟的个位
        MOV  DPTR,#TAB1
        MOV  A,HOU       ;从字形码表取出个位显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A       ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#10111111B
        LCALL YSH2S     ;短时间延时 这个时间的长短是关键如果显示有抖动的感觉请时间继续短
        ;扫描并显示时钟的十位
        MOV  DPTR,#TAB2 
        MOV  A,HOU       ;从字形码表取出十位显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A       ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#01111111B
        LCALL YSH2S    
        
        JNB P1.7,KEY17 
        JNB P1.6,KEY16 
        JNB P1.5,KEY15 
        JNB P1.4,KEY14
        
        AJMP DSUP        ;转到主程序区的主循环体开始处
  
  ;******************************************************
  ;使用P1.7[选择键]、P1.6[时钟增1]、P1.5[分钟增1]
  ;按下连在P1.7引脚上的按键进入时钟和分钟调整
  ;******************************************************
  KEY17: JNB  ET0,KEY17_
         CLR  ET0       ;停止定时器0中断
         CLR  EA        ;关闭全局中断
         MOV  R6,#0BH   ;给用来控制KEY16,KEY15赋初值,允许KEY16,KEY15两按下产生动作
         LJMP DSUP 
         RET
         
  KEY17_:MOV  R6,#0AH   ;禁用KEY16,KEY15两键工作
         SETB ET0       ;启用定时器0
         SETB EA        ;开启全局中断 
         LJMP DSUP 
         RET
  ;*****************************************************
  ;使用P1.7[选择键]、P1.6[时钟增1]、P1.5[分钟增1]
  ;按下连在P1.6引脚上的按键调整时钟       
  ;*****************************************************       
  KEY16: 
         CJNE R6,#0BH,KEY16_
         INC  HOU    ;时钟加1
         ACALL DISP  ;调用显示程序
         MOV  R1,HOU
         CJNE R1,#018H,KEY16_ 
         MOV  HOU,#00H  
 KEY16_: LJMP DSUP 
         RET
;*******************************************************
  ;使用P1.7[选择键]、P1.6[时钟增1]、P1.5[分钟增1]
  ;按下连在P1.5引脚上的按键调整分钟       
;********************************************************         
  KEY15:
         CJNE  R6,#0BH,KEY15_
         INC   MIN
         ACALL DISP
         MOV   R1,MIN
         CJNE  R1,#03CH,KEY15_
         MOV   MIN,#00H
  KEY15_:LJMP  DSUP 
         RET   
         
 ;*******************************************************
  ;使用P1.7[选择键]、P1.6[时钟增1]、P1.5[分钟增1]、P1.4[秒钟增1]
  ;按下连在P1.4引脚上的按键调整分钟       
;********************************************************         
  KEY14:
         CJNE  R6,#0BH,KEY14_
         INC   SEC
         ACALL DISP
         MOV   R1,SEC
         CJNE  R1,#03CH,KEY14_
         MOV   SEC,#00H
  KEY14_:LJMP  DSUP 
         RET           
  ;*************************************************************
  ;延时子程序  
  ;用于控制显示器的扫描速度
  ;**************************************************************    
  YSH2S:  MOV R3,#01H
  LOOP2:  MOV R4,#014H   ;修改这里的参数可以改显示扫描速的快和慢
  LOOP21: MOV R5,#05AH
  XHD3:   DJNZ R5,XHD3
          DJNZ R4,LOOP21
          DJNZ R3,LOOP2
          RET
  
  ;*************************************************************
  ;计时子程序
  ;入口参数:SEC[秒],MIN[分],HOU[时]
  ;出口参数:SEC[秒],MIN[分],HOU[时]
  ;以上三个参传递给字符显示程序
  ;***************************************************************
  TIME4:  ;计时[每秒计时一次]
        CPL  P1.0    ;指示灯一秒显一次[熄一秒亮一秒]
        INC  SEC      ;秒钟增1  
        MOV  R1,SEC
        CJNE R1,#03CH,TIME5 ;R1与立即数60秒比较,满60秒了吗?如果没到跳到TIME5处执行
        MOV  SEC,#00H       ;满60秒给秒钟变量清0
        INC  MIN            ;分钟加1 
        MOV  R1,MIN
        CJNE R1,#03CH,TIME5 ;满60分了吗?如果没满跳到TIME5处执行
        MOV  MIN,#00H       ;满60分给分钟变量清0
        INC  HOU            ;时钟加1
        MOV  R1,HOU
        CJNE R1,#18H,TIME5  ;满24小时了吗?如果没满跳到TIME5处执行
        MOV  HOU,#00H       ;满24小时给时钟变清0
        ;在此如你做的是日期你可以加入日变量、月变量和年变量  
      
  TIME5:RET
 ;**********************************************************
 ;调时时调用的显示子程序
 ;入口参数:SEC[秒],MIN[分],HOU[时]
 ;*********************************************************
 DISP:
        MOV  DPTR,#TAB1   ;获得第一字形码表的启始地址[主要是个数字]
        MOV  A,SEC        ;从字形码表取出秒钟的个位显示字模
        MOVC A,@A+DPTR    ;查表
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11111110B;关闭其它位,点亮秒钟个位
        LCALL YSH2S       ;短时间延时 这个时间的长短是关键如果显示有抖动的感觉请时间继续短
       ;扫描并显示秒钟的十位
        MOV  DPTR,#TAB2   ;获得第二字形码表的启始地址[主要是个数字]
        MOV  A,SEC        ;从字形码表取出秒钟的十位显示字模
        MOVC A,@A+DPTR    ;查表
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11111101B;关闭其它位,点亮秒钟十位
        LCALL YSH2S  
        ;显示'——'
        MOV  A,#0BFH
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11111011B;关闭其它位,点亮秒钟十位
        LCALL YSH2S  
        
        ;扫描并显示分钟的个位
        MOV  DPTR,#TAB1
        MOV  A,MIN       ;从字形码表取出个位分钟显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A        ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11110111B;关闭其它位,点亮分钟个位 
        LCALL YSH2S     ;短时间延时 这个时间的长短是关键如果显示有抖动的感觉请时间继续短
        ;扫描并显示分钟的十位
        MOV  DPTR,#TAB2 
        MOV  A,MIN       ;从字形码表取出十位显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A       ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11101111B
        LCALL YSH2S  
        
        ;显示'——'
        MOV  A,#0BFH
        MOV  P0,A         ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#11011111B
        LCALL YSH2S  
        
        ;扫描并显示时钟的个位
        MOV  DPTR,#TAB1
        MOV  A,HOU       ;从字形码表取出个位显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A       ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#10111111B
        LCALL YSH2S     ;短时间延时 这个时间的长短是关键如果显示有抖动的感觉请时间继续短
        ;扫描并显示时钟的十位
        MOV  DPTR,#TAB2 
        MOV  A,HOU       ;从字形码表取出十位显示字模
        MOVC A,@A+DPTR  
        MOV  P0,A       ;将个位段码值送给P0口线用于显示数字
        MOV  P2,#01111111B
        LCALL YSH2S
        DJNZ R7,DISP
        MOV R7,#0AH       
        RET                 
 ;********************************************************** 
  ;以下为中断服务子程序 [s为秒单位]
  ;采定时器0计时每50ms中断一次,中断20次为1s,即  50X20=1000ms[1秒]
  ;有关定时器初值的计算请查阅理论部分
  ;;*********************************************************
  TIME: CLR ET0         ;关闭定时器0中断
        CLR TR0         ;关闭定时器0
        MOV TH0,#04CH   ;初始化定时器0的溢出间隔时间[50ms] 
        MOV TL0,#00H    ;TH为位 TL为低位
        DJNZ R0,TIME2   ;20次计数到了吗?没到跳到程序[TIME2]处执行
        
        LCALL TIME4     ;20次计数已到调用计时子程序计时一次[一秒]
        MOV R0,#014H    ;给R0赋20[014H]次的初值,以便下一秒钟的计数
        
  TIME2:SETB TR0        ;开启定时器0
        SETB ET0        ;允许定时器0中断
        RETI            ;中断返回
        
;****************************************************  
;为了简化程序中复杂的计算法,本人在实际设计中构思了一个复杂点的字形码表,这对于现
;在的mcu[单片机来说不是困难的事],却在程序中简去复杂的计算过程。
;采用个位和十位分开建表,个位为TAB1,十位为TAB2。
;****************************************************
 TAB1: ;个位60个字模码表
      DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H  ; 0~9
      DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H  ; 10~19
      DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H  ; 20~29
      DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H  ; 30~39
      DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H  ; 40~49
      DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H  ; 50~59
      ;   0    1    2    3    4    5    6    7    8    9
 TAB2: ;十位10个字模码表
      DB 0C0H,0C0H,0C0H,0C0H,0C0H,0C0H,0C0H,0C0H,0C0H,0C0H  ;十位 0   
      DB 0F9H,0F9H,0F9H,0F9H,0F9H,0F9H,0F9H,0F9H,0F9H,0F9H  ;十位 1
      DB 0A4H,0A4H,0A4H,0A4H,0A4H,0A4H,0A4H,0A4H,0A4H,0A4H  ;十位 2
      DB 0B0H,0B0H,0B0H,0B0H,0B0H,0B0H,0B0H,0B0H,0B0H,0B0H  ;十位 3
      DB 099H,099H,099H,099H,099H,099H,099H,099H,099H,099H  ;十位 4
      DB 092H,092H,092H,092H,092H,092H,092H,092H,092H,092H  ;十位 5
      
      END

⌨️ 快捷键说明

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