原创 HELIOS(H6164)DSP+DS1302的汇编代码

2008-8-13 14:25 2080 11 11 分类: 处理器与DSP

;*******************************************************************************
;*  USER WORKING MEMORY (VARIABLE DEFINITION)              *
;*******************************************************************************
DATA RAM 


DEBOUNCE2   BYTE
INPUT_MASK2    BYTE
LAST_KEY_STATE2   BYTE
KEY_FS2     BYTE
KEY_RS2     BYTE


 


UCADDR  BYTE    ;写入DS1302的地址
UCDATA          BYTE  ;写入DS1302的内容


SECOND  BYTE  
MINUTE  BYTE
HOUR  BYTE
DAY    BYTE
MONTH           BYTE
WEEK   BYTE
YEAR            BYTE


PCLOCK      EQU SECOND 


MiniValue BYTE  ;设定秒,分。。。的最小值
MaxValue BYTE  ;设定秒,分。。。的最大值


TimeSetupFlag BYTE  ;设置时间的标志
SETUPSECOND_FLAG  EQU 00000001B   ;设定秒标志
SETUPMINUTE_FLAG  EQU 00000010B   ;设定分标志
SETUPHOUR_FLAG   EQU 00000100B   ;设定时标志
SETUPDAY_FLAG   EQU 00001000B   ;设定日标志
SETUPMONTH_FLAG   EQU 00010000B   ;设定月标志
SETUPWEEK_FLAG   EQU 00100000B   ;设定星期标志
SETUPYEAR_FLAG   EQU 01000000B   ;设定年标志


FlashCount    WORD     ;闪烁计时,半秒改变一次,以T1 1000HZ计算,FlashCount=500时改变一次显示状态,
            ; 由亮变为灭,或由灭变为亮
FlashFlag    BYTE     ; 闪烁状态,第0位,1表示亮,0表示灭            


CODE 


;************************************************************
;FUNCTION   初始化变量
;************************************************************       
InitialDS1302Value FUNCTION
 MOVE [INPUT_MASK2], 00111000B
 MOVE    [TimeSetupFlag], 00H
 MOVE [FlashFlag], 00H
 MOVEW [FlashCount], 0000H
 
 RET
InitialDS1302Value ENDF



;************************************************************
;FUNCTION   开始写, 控制命令,WP=0,写操作
;************************************************************       
InitialDS1302 FUNCTION


 CALL InitialDS1302Value


 MOVE [UCADDR],90H
 MOVE [UCDATA],A0H
 
 CALL WRITE1302  ; FUNCTION 写操作
   
 ;CALL InitialTime
            
 ;*************************************************************
 ;FUNCTION   控制命令,WP=1,写保护功能
 ;*************************************************************           
 MOVE [UCADDR],8EH
 MOVE [UCDATA],80H
 CALL WRITE1302   ;FUNCTION 写保护
  
  
 RET
InitialDS1302 ENDF


;=================================================================
;FUNCTION InitialTime() 设置初始时间
;=================================================================
InitialTime FUNCTION
 MOVE X,00H


 MOVE PTR,TAB1
@L1 MOVE A,[PTR]
 MOVE [PCLOCK+X], A
 INC PTR
 INC X
 CMP X, 07H
 JNZ @L1
 
 CALL SET1302
         
 RET
InitialTime ENDF
 
;**************************************************************
;FUNCTION   调整功能   1个按键是功能选择,另外一个是数值加,
;                      另外一个是数值减  
;************************************************************** 
                      
;**************************************************************         
;FUNCTION   调整功能
;**************************************************************     
DS1302_SCAN_KEY   FUNCTION
      CMP  [DEBOUNCE2], 20
      JNC  @F
      RET
@      MOVE [DEBOUNCE2], 0
      MOVE A, [PORT1_DATA]
      MOVE X, A
      XOR  A, [LAST_KEY_STATE2]    ; GET CHANGE KEY STATE
      AND  A, [INPUT_MASK2]
      PUSH A
      AND  A, [LAST_KEY_STATE2]    ; GET FALLING EDGE KEY
      MOVE [KEY_FS2], A
      POP  A
      AND  A, X       ; GET RISING EDGE KEY
      MOVE [KEY_RS2], A
      MOVE [LAST_KEY_STATE2], X
      OR  A, [KEY_FS2]
      JNZ  @HAS_KEY_EVENT2
      RET
@HAS_KEY_EVENT2   


      ;有按键,打开LCD背光
      CALL    SetBacklight
;=============================================================================================================
; 向上键处理      
@KEYF_P13    JBZ  [KEY_FS2], 00001000B, @KEYF_P14  ;第P1.3脚, 上键
      CALL    Key_Increase
      JUMP @QUIT_SCAN2


;=============================================================================================================
; 中键,主要是功能切换处理, 秒结束后,就停止设置会到正常时钟显示
; 设置顺序:年4位,前面都加20,如2008
;   月+日 四位,中间点不显示
;   时+分 四位,中间点显示
;   秒    二位,单独设置     
@KEYF_P14    JBZ  [KEY_FS2], 00010000B, @KEYF_P15  ;第P1.4脚, 功能键
      MOVE    A, [TimeSetupFlag]
      JNZ  A, @f
      OR  A, 10000000B      
@      
      CLC  ; 清楚PSR 零标志位
      RCR  A                             
      
      ; 星期自动计算,所以跳过设定
      JBZ  A, SETUPWEEK_FLAG, @F
      CLC
      RCR  A
      
@      
      MOVE [TimeSetupFlag], A            
      ; 判断是否已经一个设定循环结束,即TimeSetupFlag == 0, 如果等于0则保存以前设定的值
      JNZ  [TimeSetupFlag], @SETUP
      CALL SaveSetup
      JUMP @QUIT_SCAN2
@SETUP      
      MOVEW [FlashCount], 500
      OR  [FlashFlag], 00000001B
      
      JUMP @QUIT_SCAN2


;=============================================================================================================
; 向下键处理      
@KEYF_P15    JBZ  [KEY_FS2], 00100000B, @QUIT_SCAN2 ;第P1.5脚, 下键
      CALL    Key_Decrease
      
      JUMP @QUIT_SCAN2



@QUIT_SCAN2    MOVE [KEY_FS2], 00H     ; CLEAR FALLING KEY STATUS
      MOVE [KEY_RS2], 00H     ; CLEAR RISING KEY STATUS
      RET
DS1302_SCAN_KEY ENDF



;***************************************************************
;FUNCTION DS1302_ShowTime()
; 根据TimeSetupFlag决定是要正常显示,还是闪烁设置的状态, 设置时的
; 闪烁参见@KEYF_P14
;***************************************************************
DS1302_ShowTime FUNCTION
 ; 首先比对FlashCount 是否为 500 = 1f4H, 不是表示还没有到要刷新的时间,则加1后返回,需要刷新则进入下面判断
 CMP [FlashCount], F4H
 JNZ @NOTEQUAL
 CMP [FlashCount+1],01H
 JZ @F
@NOTEQUAL
 ADDW [FlashCount], 1
 RET
  
@
 MOVEW [FlashCount], 0000H  ;FlashCount == 500, 开始切换闪烁状态,并且重置FlashCount=0
 MOVE A, [TimeSetupFlag]   ;TimeSetupFlag == 0 表示不是设置状态,则正常显示时间
 JNZ A, @@F      ;SetupTime


 ;ShowNormalTime
 ;====================================================
 ;正常显示时间
 CALL GET1302
 MOVE A, [HOUR]
 MOVE X, [MINUTE]
 ; 将时间显示出来
 MOVE [ShowFlag], 00001111B  ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 CALL ShowTime  ;Show
 
 ; 显示闪烁的两点
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00010000B ;显示两点
 CALL ShowDots
 AND [FlashFlag], 11111110B
 JUMP @RETURN 

 MOVE [ShowFlag], 00010000B ;隐藏两点
 CALL ClearDots
 OR  [FlashFlag], 00000001B


@RETURN  
 RET  


@@ ;=====================================================
 ; 有设置标志,则进行闪烁
 ;=====================================================
 ; 正在设置年
 JBZ [TimeSetupFlag], SETUPYEAR_FLAG, @@F
 CALL ClearDots
 MOVE A, 0
 MOVE X, [YEAR]
 ADD AX, 2000
 
 MOVE [NumberShow], AX
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00001111B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 AND [FlashFlag], 11111110B
 CALL ShowNumbers  ;Show
 RET
@
 ; 此处FlashFlag.0 == 0, 不显示内容
 MOVE [ShowFlag], 00000000B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部不显示
 OR  [FlashFlag], 00000001B


 CALL ShowNumbers  ;Show
 RET
 
 
@@  ;=====================================================
 ; 正在设置月
 JBZ [TimeSetupFlag], SETUPMONTH_FLAG, @@F
 CALL ClearDots
 MOVE A, [MONTH]
 MOVE X, [DAY]
 
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00001111B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 AND [FlashFlag], 11111110B
 CALL ShowTime  ;Show
 RET
@
 ; 此处FlashFlag.0 == 0, 不显示内容
 MOVE [ShowFlag], 00000011B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部不显示
 OR  [FlashFlag], 00000001B


 CALL ShowTime  ;Show
  
 RET
 
 
@@  ;=====================================================
 ; 正在设置日
 JBZ [TimeSetupFlag], SETUPDAY_FLAG, @@F
 CALL ClearDots
 MOVE A, [MONTH]
 MOVE X, [DAY]
 
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00001111B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 AND [FlashFlag], 11111110B
 CALL ShowTime  ;Show
 RET
@  ;=====================================================
 ; 此处FlashFlag.0 == 0, 不显示内容
 MOVE [ShowFlag], 00001100B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部不显示
 OR  [FlashFlag], 00000001B


 CALL ShowTime  ;Show  
 RET
 
 
@@ ;=====================================================
 ; 正在设置时
 JBZ [TimeSetupFlag], SETUPHOUR_FLAG, @@F
 CALL ShowDots
 MOVE A, [HOUR]
 MOVE X, [MINUTE]
 
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00001111B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 AND [FlashFlag], 11111110B
 CALL ShowTime  ;Show
 RET
@  ;=====================================================
 ; 此处FlashFlag.0 == 0, 不显示内容
 MOVE [ShowFlag], 00000011B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部不显示
 OR  [FlashFlag], 00000001B


 CALL ShowTime  ;Show    
 RET
 
 
@@  ;=====================================================
 ; 正在设置分
 JBZ [TimeSetupFlag], SETUPMINUTE_FLAG, @@F
 CALL ShowDots
 MOVE A, [HOUR]
 MOVE X, [MINUTE]
 
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00001111B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 AND [FlashFlag], 11111110B
 CALL ShowTime  ;Show
 RET
@  ;=====================================================
 ; 此处FlashFlag.0 == 0, 不显示内容
 MOVE [ShowFlag], 00001100B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部不显示
 OR  [FlashFlag], 00000001B


 CALL ShowTime  ;Show    
 RET
 
 
@@  ;=====================================================
 ; 正在设置秒
 JBZ [TimeSetupFlag], SETUPSECOND_FLAG, @@F
 CALL ClearDots
 MOVE A, FFH
 MOVE X, [SECOND]
 
 JBZ [FlashFlag], 00000001B, @F ;FlashFlag.0 == 1 表示显示, == 0 表示不显示
 ; 此处FlashFlag.0 == 1, 显示内容
 MOVE [ShowFlag], 00000011B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部显示
 AND [FlashFlag], 11111110B
 CALL ShowTime  ;Show
 RET
@  ;=====================================================
 ; 此处FlashFlag.0 == 0, 不显示内容
 MOVE [ShowFlag], 00000000B ;ShowFlag 在LCD 中定义的,此处表示四位数字全部不显示
 OR  [FlashFlag], 00000001B


 CALL ShowTime  ;Show
@@ RET



DS1302_ShowTime  ENDF



;**************************************************************
;FUNCTION 数值增函数
;**************************************************************
Key_Increase   FUNCTION
 PUSH A
 PUSH X
 
 MOVE X,00H
 MOVE A, [TimeSetupFlag]
 JZ A, @NOT_SETUP_MODE
 
@ RCR A
 JC @SETUP_TIME  ; 有设定时间
 
 INC X
 CMP X, 07H
 JNZ @B
  
@SETUP_TIME
 PUSH X
 MOVE PTR, TAB2
 ROL X    ;X = X*2
 
 ADD PTR, X   ;取设定时的最小值
 MOVE A, [PTR]
 MOVE [MiniValue], A
 
 INC PTR    ;取设定时的最大值
 MOVE A, [PTR]
 MOVE [MaxValue], A
 
 POP X
 MOVE A, [PCLOCK+X]
 
 CMP A, [MaxValue]
 JZ @F
 INC A
 JUMP @@F

 MOVE A, [MiniValue] 


@@
 ;此时A内的值为新的设定值,将新的设定值写入DS1302
 MOVE [PCLOCK+X], A
  
 JUMP @EXIT_KEY_INCREASE
 
@NOT_SETUP_MODE
 ; TimeSetupFlag == 0, 表示不在设定时间状态
 
@EXIT_KEY_INCREASE
 POP X
 POP A           
 RET
Key_Increase   ENDF



;***************************************************************
;FUNCTION 数值减函数 
;***************************************************************
Key_Decrease   FUNCTION
 PUSH A
 PUSH X
 
 MOVE X,00H
 MOVE A, [TimeSetupFlag]
 JZ A, @NOT_SETUP_MODE
 
@ RCR A
 JC @SETUP_TIME  ; 有设定时间
 
 INC X
 CMP X, 07H
 JNZ @B
  
@SETUP_TIME
 PUSH X
 MOVE PTR, TAB2
 ROL X    ;X = X*2
 
 ADD PTR, X   ;取设定时的最小值
 MOVE A, [PTR]
 MOVE [MiniValue], A
 
 INC PTR    ;取设定时的最大值
 MOVE A, [PTR]
 MOVE [MaxValue], A
 
 POP X
 MOVE A, [PCLOCK+X]
 
 CMP A, [MiniValue]
 JZ @F
 DEC A
 JUMP @@F

 MOVE A, [MaxValue] 


@@
 ;此时A内的值为新的设定值,将新的设定值写入DS1302
 MOVE [PCLOCK+X], A
  
 JUMP @EXIT_KEY_DECREASE
 
@NOT_SETUP_MODE
 ; TimeSetupFlag == 0, 表示不在设定时间状态
 
@EXIT_KEY_DECREASE
 POP X
 POP A           
 RET


Key_Decrease   ENDF  


;***************************************************************
;FUNCTION SaveSetup()
; 保存时钟设置的结果
; 有两种状况会调用到此函数,一按【功能切换】键切到SetupTimeFlag == 0时调用
; 或者在设定时,较长时间没有按键,自动切会到时钟显示时,会调用
SaveSetup FUNCTION
 ; 先计算出 星期值
 CALL CalculateWeek
 
 CALL SET1302
 RET
SaveSetup ENDF
     
;***************************************************************
;FUNCTION Write1302()
; 功    能:往DS1302写入数据
; 说    明:先写地址,后写命令/数据 (内部函数)
; 调    用:RTInputByte() , RTOutputByte()
; 入口参数:ucAddr: DS1302地址, ucData: 要写的数据
; 返 回 值:无
;***************************************************************   
WRITE1302 FUNCTION
 PUSH X


    CALL ClearDS1302ChipSelect
    CALL ClearDS1302Clock
    CALL SetDS1302ChipSelect
   
    MOVE A, [UCADDR]
    CALL RTINPUTBYTE ;A 为参数 
    MOVE A, [UCDATA]
    CALL RTINPUTBYTE
   
    CALL SetDS1302Clock
    CALL ClearDS1302ChipSelect


 POP X
    RET
WRITE1302 ENDF
      
;*******************************************************************
;函 数 名:Read1302()
; 功    能:读取DS1302某地址的数据
; 说    明:先写地址,后读命令/数据 (内部函数)
; 调    用:RTInputByte() , RTOutputByte()
; 入口参数:ucAddr: DS1302地址
; 返 回 值:ucData :读取的数据
;*******************************************************************
Read1302 FUNCTION
 PUSH X 
 
 CALL ClearDS1302ChipSelect
 CALL ClearDS1302Clock
 CALL SetDS1302ChipSelect
 MOVE A,[UCADDR]
 CALL RTINPUTBYTE
 CALL RTOUTPUTBYTE
 MOVE [UCDATA],A
 CALL SetDS1302Clock
 CALL ClearDS1302ChipSelect
 
 POP X
 RET
Read1302 ENDF
       
;********************************************************************
;FUNCTION 设置初始时间,先写地址,后读命令/数据(寄存器多字节方式)
;- 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年
;-7Byte (BCD码)1B 1B 1B 1B 1B  1B  1B
;********************************************************************
SET1302 FUNCTION
 MOVE [UCADDR],8EH
 MOVE [UCDATA],00H
 CALL WRITE1302  ;FUNCTION 将控制寄存器的值设置为零,最高位WP=0允许写


 MOVE [UCADDR], 80H
 MOVE X,00H
@L 
 PUSH X
 MOVE A, [PCLOCK+X]
 ; 将 要写入的值,转为BCD码, 如08年,需要转成08H, 12月需要转成12H 而非0CH
 MOVEW [Dividend],0000H
 MOVE [Dividend], A 
 MOVEW [Divisor], 0AH
 CALL DIV16
 
 MOVE A, 10H
 IMUL [Quotient], A   ; 商*16
 ADD [Quotient], X   ; 此时 X 内为除后的余数,加Quotient后,[Quotient]为写入值的BCD码
 
 MOVE A, [Quotient]
 
 MOVE [UCDATA], A
 CALL WRITE1302    ;FUNCTION 将7个时间初值写入对应的控制寄存器
 
 ADD [UCADDR], 2    ;UCADDR += 2
 POP X      ; 由于除法中X值会被改变,所以需要先PUSH, 在需要使用指出POP出来
 INC X
 CMP X, 07H     ;IF X == 7 结束循环
 JNZ @L
 
 MOVE [UCADDR],8EH
 MOVE [UCDATA],80H
 CALL WRITE1302    ;FUNCTION 写保护
 RET  
SET1302 ENDF


;*********************************************************
;FUNCTION 读取当前时间值
;*********************************************************
GET1302 FUNCTION
  PUSH A
  MOVE [UCADDR],81H
  MOVE X,00H


@
  PUSH X
  CALL Read1302  ;Read1302将读出的值放在A中
  MOVEW [Dividend],0000H
  MOVE [Dividend], A ;读出数据为BCD码,即56秒的值为56H,所以需要通过除以16*10+余数方法,得到正式16进制数
       ;如56秒,读出值为56H,通过56/16+56%16 = 38H
  MOVEW [Divisor], 10H
  CALL DIV16
  
  MOVE A, 0AH   
  IMUL [Quotient], A ; 商*10
  ADD [Quotient], X ; 此时 X 内为除后的余数,加Quotient后,[Quotient]为BCD码转出来的值,如原来32H,变为十进制的32
  
  MOVE A, [Quotient]
  POP X    ; 由于除法中X值会被改变,所以需要先PUSH, 在需要使用指出POP出来
  MOVE [PCLOCK+X], A
  ADD [UCADDR], 2
  
  INC X    
  
  CMP X, 07H
  JNZ @B
  
  POP A
  RET            
GET1302  ENDF


;*************************************************************
;FUNCTION RtOutputByte
; 函 数 名:RTOutputByte()
; 功    能:实时时钟读取一字节
; 说    明:从DS1302读取1Byte数据 (内部函数)
; 入口参数:无 
; 返 回 值:A
;unsigned char RTOutputByte(void)
;{
;    unsigned char i;
;    for(i=8; i>0; i--)
;    {
;        ACC = ACC >>1;         //相当于汇编中的 RRC
;        ACC7 = T_IO;
;        T_CLK = 1;
;        T_CLK = 0;
;    }
;    return(ACC);
;}
;*************************************************************     
RTOutputByte FUNCTION
 MOVE A, 00H
 AND PSR,11111110B
 OR [PORT1_IO_MODE], 00000010B ;设定P1.1为输入状态
 
 MOVE X, 08H
@@ 
 RCR A
 JBZ [PORT1_DATA], 00000010B, @F
 OR A, 10000000B
 
@ CALL SetDS1302Clock
 CALL ClearDS1302Clock 
 
 LOOP X, @@B
 RET
RTOutputByte ENDF 


;*************************************************************
;FUNCTION RTInputByte
; 函 数 名:RTInputByte()
; 功    能:实时时钟写入一字节
; 说    明:往DS1302写入1Byte数据 (内部函数)
; 入口参数:A 写入的数据
; 返 回 值:无 
;void RTInputByte(unsigned char d)
;{
;    unsigned char i;
;    ACC = d;
;    for(i=8; i>0; i--)
;    {
;        T_IO = ACC0;           //相当于汇编中的 RRC
;        T_CLK = 1;
;        T_CLK = 0;
;        ACC = ACC >> 1;
;    }
;}
;*************************************************************        
RTInputByte FUNCTION


 AND [PORT1_IO_MODE], 11111101B ;设定P1.1为输出状态
 MOVE X, 08H
@@ 
 RCR  A
 CALL ClearDS1302Data
 JNC   @F
 CALL SetDS1302Data

 CALL SetDS1302Clock
 CALL ClearDS1302Clock
 
 LOOP X, @@B
 RET
RTInputByte ENDF


 


;********************************
;FUNCTION  SetDS1302Clock() 
;Clock 接 P12
;********************************
SetDS1302Clock FUNCTION
 OR [PORT1_DATA],00000100b
 RET
SetDS1302Clock ENDF



;********************************
;FUNCTION ClearDS1302Clock()
;********************************
ClearDS1302Clock FUNCTION
 AND [PORT1_DATA],11111011b      
 RET
ClearDS1302Clock ENDF



;********************************
;FUNCTION SetDS1302Data()
;Data 接 P11
;********************************
SetDS1302Data  FUNCTION
 OR [PORT1_DATA],00000010b 
 RET
SetDS1302Data  ENDF



;*********************************
;FUNCTION ClearDS1302Data()
;*********************************
ClearDS1302Data FUNCTION
 AND [PORT1_DATA],11111101b
 RET
ClearDS1302Data ENDF


;********************************
;FUNCTION SetDS1302ChipSelect()
;ChipSelect 接 P10
;********************************
SetDS1302ChipSelect  FUNCTION
 OR [PORT1_DATA],00000001b 
 RET
SetDS1302ChipSelect  ENDF



;*********************************
;FUNCTION ClearDS1302ChipSelect()
;*********************************
ClearDS1302ChipSelect FUNCTION
 AND [PORT1_DATA],11111110b
 RET
ClearDS1302ChipSelect ENDF



; 计算星期几
; 已知D=第"N"年"m"月"d"日
; WD≡d+[ (13n-1)/5 ] + y +[y/4] +[c/4] -2c (mod 7),
; 这里 n = m-2若果 m="2"、3、....、12;
; 否则n=12若m=2, 及n=11若m=1。
; 注:其实这里想将月份倒推二个月。
; 此外c、y由以下公式确定:N=100 c + y,而y是0至99(包括0和99)的整数,即最后的两个位数字。c代表删去最后两个位所得到的数字,所谓c世纪。
; 在以上的方括号代表括号内数字的整数部份。
; 如[1.2]=1、[13.9]=13、[99/4]=[24.75]=24。
; 在此 mod 7 代表 将计算的答案用7除后,只取余数。这亦即常用的所谓"同余"。
; 最后的数值应该在0至6之间。
; "0"代表星期日;
; "1"代表星期一;
; "2"代表星期二;
; 如此类推
; 举个例子:
; 今天是 1999年 3月 20日,它应是星期六。
; 由此得N=1999,所以c=19、y=99、m=3、n=1、d=20。
;    d+[ (13*n-1)/5 ] + y +[y/4] +[c/4] -2*c
; =20 +[ (13x1 -1)/5] +99+[99/4]+[19/4] -2x19
; ≡20+[12/5]+99+[99/4] +[19/4] -38
; ≡6+2 +1+24+4 - 3
; ≡6    (即星期六) 。
CalculateWeek FUNCTION
 PUSH A
 PUSH X
 MOVEW [Dividend], 13  ;将Dividend 当临时变量用于乘除
 ;由于我们日期都是从2000-2099, 所以C为固定值20,C/4 固定为5, 2*C 固定为40,40%7 = 5,与C/4正好抵消
 
 ;先根据月计算出n 来,值放在A 里
 MOVE A, [MONTH]
 CMP A, 1
 JZ @F
 SUB A, 2
 JUMP @@F
@ MOVE A, 11 
@@ IMUL [Dividend], A  ;此时Dividend = 13*N
 
 DEC [Dividend]   ;13N-1
 MOVE A, 5
 IDIV [Dividend], A  ;Dividend = [13*N-1]/5
 ;忽略IDIV 除后的余数
 MOVE A, [Dividend]  ;将结果先保存到WEEK
 MOVE [WEEK], A
 
 ;再计算y/4,
 MOVE A, [YEAR]
 MOVEW [Dividend], 0
 MOVE [Dividend], A  ;Dividend = YEAR
 
 MOVE A, 4   
 IDIV [Dividend], A  ;此时Dividend = Y/4 


 MOVE A,[Dividend]  ;A = Y/4 X = y%4
 ADD A, [DAY]  ;A = D + Y/4
 ADD A, [WEEK]  ;A = D+ Y/4 + 此时WEEK值为[13*N-1]/5
 ADD A, [YEAR]  ;A = D + Y/4 + [13*N-1]/5 + Y
; ADD A, 5   ;A = D + Y/4 + [13*N-1]/5 + Y + C/4
; SUB A, 5   ;A = D + Y/4 + [13*N-1]/5 + Y + C/4 - 2C
 
 MOVEW [Dividend], 0
 MOVE [Dividend], A ;A当被除数
 MOVEW [Divisor], 7 ;7为除数
 CALL DIV16   ;此时X为余数,
 
 ;0代表星期天,这里把它修正为7,表示星期天
 JNZ X, @F
 MOVE X, 7
@
 MOVE [WEEK], X
 
 POP X
 POP A
 
 RET
CalculateWeek ENDF


;        秒  分  时  日  月 星期 年     
TAB1 DB 00H,59H,23H,28H,04H,01H, 08H 
;      Min  Max  
;         秒      分    时     日      月    星期     年
;       ====== ====== ====== ======  ======  ====== ======
TAB2 DB 0, 59, 0, 59, 00, 23, 1, 31, 01, 12, 1, 7,  00, 99



 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
11
关闭 站长推荐上一条 /3 下一条