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

📄 picclock.asm

📁 着是一个很好的编译程序,他可以控制 时钟的运行状况,可以显示时间.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
              LIST    p=16F84 ; PIC16F844 is the target processor

              #include "P16F84.INC" ; Include header file

              CBLOCK 0x10   ; Temporary storage
                 state
                 secs
                 mins
                 hours
                 ticks
                 idc
                 bcd
              ENDC

; Constants for bit allocation. The BIT_x constants are actual bit numbers and
; the MASK_x are bit masks for the same bit.
BIT_HSEL      EQU H'0000'
BIT_TSET      EQU H'0001'
BIT_HSET      EQU H'0002'
BIT_MSET      EQU H'0003'

BIT_H24       EQU H'0000'
BIT_PM        EQU H'0001'
BIT_SET       EQU H'0002'
BIT_HSB       EQU H'0003'

MASK_H24      EQU H'0001'
MASK_PM       EQU H'0002'
MASK_SET      EQU H'0004'
MASK_HSB      EQU H'0008'


; Macro to generate a MOVLW instruction that also causes a model break:
break         MACRO arg
              DW    0x3100 | (arg & H'FF')
              ENDM

              ORG   0
entrypoint    goto  initialise

              ORG   4
intvector     goto    clock

initialise    ; Register set up:
              clrw                    ; Zero.
              movwf   PORTA           ; Ensure PORTA is zero before we enable it.
              movwf   PORTB           ; Ensure PORTB is zero before we enable it.
              bsf     STATUS,RP0      ; Select Bank 1
              movlw   H'1F'           ; Mask for PORTA inputs/outputs.
              movwf   TRISA           ; Set TRISA register.
              movlw   H'01'           ; Mask for PORTA inputs/outputs.
              movwf   TRISB           ; Set TRISB register.
              bcf     STATUS,RP0      ; Reselect Bank 0.

              ; Initialise clock:
              clrf    state
              bsf     state,BIT_HSB
              movlw   D'0'
              movwf   hours
              movlw   D'0'
              movwf   mins
              movlw   D'0'
              movwf   secs

              ; Clear 50Hz tick count:
              clrf    ticks

              ; Clear interrupt disable count (idc) semaphore:
              clrf    idc

              ; Initialise display:
              call    wr_hours
              call    wr_mins
              call    wr_secs
              call    wr_state

              ; Finally initialise interrupts for clock on RB0/INT pin:
              movlw   H'90'
              movwf   INTCON

start         ; When not processing an interrupt we sit and check input pins:
              call    chk_tset        ; Time set select active?
              call    chk_hsel        ; H12/H24 display format select active?
              goto    start


;------------------------------------------------------------------------------
; Interrupt handler. We come here for every tick of the time base.

clock         ; Toggle half-second flag and set state outputs:
              incf    ticks,F         ; Increment clock ticks.
              movf    ticks,W         ; Get ticks value.
              sublw   D'25'           ; Is it 25 (W=25-W)?
              btfss   STATUS,Z        ; Test zero flag.
              goto    endclock        ; Return.

toggle_hs     ; Half second - toggle HS flag, write it and return:
              clrf    ticks           ; Reset timebase,
              movf    state,W         ; Get state.
              xorlw   MASK_HSB        ; Toggle half-second bit.
              movwf   state           ; Save it back to register.
              call    wr_state        ; Display it.
              movf    state,W         ; Get state.
              btfss   state,BIT_HSB   ; Is bit now clear?
              goto    endclock        ; Return.

inc_secs      ; Incrmement seconds...
              incf    secs,F          ; Increment seconds count.
              movf    secs,W          ; Get it into W.
              sublw   D'60'           ; Is it 60 (W=60-W)?
              btfsc   STATUS,Z        ; Test zero flag, skip clear if no set.
              goto    reset_secs      ; Clear seconds, increment minutes.
              call    wr_secs         ; Write seconds it to display.
              goto    endclock        ; Done.

reset_secs    clrf    secs
              call    wr_secs         ; Write seconds to display.

              incf    mins,F          ; Increment minute count.
              movf    mins,W          ; Get it into W.
              sublw   D'60'           ; Is it 60 (W=60-W)?
              btfsc   STATUS,Z        ; Test zero flag, skip clear if no set.
              goto    reset_mins      ; Clear minutes, increment hours.
              call    wr_mins         ; Write minutes it to display.
              goto    endclock        ; Done.

reset_mins    clrf    mins            ; Reset minute count to zero.
              call    wr_mins         ; Write minutes to display.

              call    inc_hours       ; Increment hours, display it with PM flag.
              
endclock      movlw   H'90'
              movwf   INTCON
              retfie                  ; Return

;------------------------------------------------------------------------------
; Subroutine. Check the state of the HSEL input and set h12/h24 format as
; required.

chk_hsel      btfsc   PORTA,BIT_HSEL  ; Test 12/24 select.
              goto    set_h12         ; H12 set so switch to 12 hour format.
              ; fall through          ; H12 not set so switch to 24 hour format.

set_h24       btfsc   state,BIT_H24   ; Are we on 12 hour format?
              retlw   0               ; No, so no need to do anything...

              bcf     INTCON,GIE      ; Disable interrupts.
              incf    idc,F           ; Increment count of number of disables.
              bsf     state,BIT_H24   ; Clear h12 flag.

              movf    hours,W         ; Get hours value.
              sublw   D'12'           ; Is it 12:xx?
              btfsc   STATUS,Z        ; Test zero flag.
              clrf    hours           ; Reset to zero.
              movf    hours,W         ; Get hours value.
              btfsc   state,BIT_PM    ; Is the PM indicator set?
              addlw   D'12'           ; Add 12 to get 24 hour value.
              movwf   hours           ; Save result (does nothing for AM).
              bcf     state,BIT_PM    ; Clear PM flag.
              call    wr_hours        ; Write hours.
              call    wr_state        ; Write H12 state and PM state.
              goto    chk_hsel_iec    ; Done.

set_h12       btfss   state,BIT_H24   ; Are we on 12 hour format?
              retlw   0               ; Yes, so no need to do anything...

              bcf     INTCON,GIE      ; Disable interrupts.
              incf    idc,F           ; Increment count of number of disables.
              bcf     state,BIT_H24   ; Set h12 flag.

              movf    hours,W         ; Get hour value.
              sublw   D'11'           ; W=11-W. C is clear for a borrow (W>=12).
              btfss   STATUS,C        ; Test carry flag.
              goto    set_h12_pm      ; Set PM.

set_h12_am    bcf     state,BIT_PM    ; Clear PM bit.
              movf    hours,W         ; Get hours.
              btfsc   STATUS,Z        ; Is it zero?
              addlw   D'12'           ; Yes, add 12 to get 00:xx to 12:xx.
              movwf   hours           ; Save any result.
              call    wr_hours        ; Display hours.
              call    wr_state        ; Display H12 and PM states.
              goto    chk_hsel_iec    ; Done.

set_h12_pm    bsf     state,BIT_PM    ; Set PM bit.
              movlw   D'12'           ; Constant.
              subwf   hours,F         ; hours=hours-12 (23..12 -> 11..0).
              btfsc   STATUS,Z        ; Zero set?
              movwf   hours           ; Yes, so reset to '12'.
              call    wr_hours        ; No, so leave hours alone and display it.
              call    wr_state        ; Display H12 and PM states.
              goto    chk_hsel_iec    ; Done.

chk_hsel_iec  decfsz  idc,F           ; Decrement idc. If zero we can reenable interrupts.
              retlw   1               ; Return without enabling interrupts.

chk_hsel_done movlw   H'90'           ; Constant for GIE and T0IE.
              movwf   INTCON          ; Set interrupt register.
              retlw   1               ; Return.

;------------------------------------------------------------------------------
chk_tset      btfsc   PORTA,BIT_TSET  ; Set mode?
              retlw   0

              bcf     INTCON,GIE      ; Disable interrupts.
              incf    idc,F           ; Increment count of number of disables.
              bsf     state,BIT_SET   ; Set the 'set mode' bit.
              clrf    secs            ; Setting time resets seconds count.
              call    wr_secs         ; Display it.
              bcf     state,BIT_HSB   ; Clear seconds toggle.
              call    wr_state        ; Update the state output latch.

⌨️ 快捷键说明

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