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

📄 clock.asm

📁 Low-Power Real-Time Clock
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	LIST    P = 16C74, n = 66
        ERRORLEVEL  -302
;
;******************************************************************************
;
; This program implements a real time clock using the TMR1 module of the 
; PIC16Cxx family. A LCD display module is used to display (update) the time 
; every second. Three keys are used to set the time.
;
;       Program = CLOCK.ASM
;       Revision Date:   5-15-94
;                        1-15-97    Compatibility with MPASMWIN 1.40
;
;******************************************************************************
; 
;
; HARDWARE SETUP
;   LCD Control Lines
;       RA0 = E     (Enable)
;       RA1 = RW    (Read/Write)
;       RA2 = RS    (Register Select)
;   LCD Data Lines
;       RB<3:0>
;   Switch Inputs
;       RB7 = Select Hour / Minute / Off
;       RB6 = Increment Hour / Minute
;       RB5 = Reset Minutes to 00
;
            INCLUDE <p16c74.inc>

FALSE			EQU		0
TRUE			EQU		1

            INCLUDE <CLOCK.h>
;
LCD_DATA        EQU     PORTB           ; The LCD data is on the lower 4-bits
LCD_DATA_TRIS   EQU     TRISB           ; The TRIS register for the LCD data
LCD_CNTL        EQU     PORTA           ; Three control lines
;
PICMaster       EQU     FALSE           ; A Debugging Flag
Debug           EQU     FALSE           ; A Debugging Flag
Debug_PU        EQU     TRUE            ; A Debugging Flag
;
;
; Reset address. Determine type of RESET
;
        org     RESET_V                 ; RESET vector location
RESET       BSF     STATUS, RP0         ; Bank 1
            BTFSC   PCON, NOT_POR           ; Power-up reset?
            GOTO    START               ; YES
            GOTO    OTHER_RESET         ; NO, a WDT or MCLR reset
;
; This is the Periperal Interrupt routine. Need to determine the type
; of interrupt that occurred. The following interrupts are enabled:
;   1.  PORTB Change (RBIF)
;   2.  TMR1 Overflow Interrupt (T1IF)
;
    page
        org     ISR_V              ; Interrupt vector location
PER_INT_V	
        if ( Debug )
            bsf     PORTD, 0            ; Set high, use to measure total
        endif                           ;     time in Int Service Routine
;
            BCF         STATUS, RP0	; Bank 0
            BTFSC	PIR1, TMR1IF	; Timer 1 overflowed?
            GOTO	T1_OVRFL	; YES, Service the Timer1 Overflow Interrupt
            BTFSS	INTCON, RBIF	; NO, Did PORTB change?
            GOTO	ERROR1		; NO, Error Condition - Unknown Interrupt
;
PORTB_FLAG				; Are any of PORTB's inputs active?
            MOVF	PORTB, W	;
            ANDLW	0xE0		; Keep only the 3 switch values
DEBOUNCE    MOVWF	TEMP		;
            MOVLW	DB_HI_BYTE	; This is the debounce delay 
            MOVF	MSD, F		;
            CLRF	LSD		;
KB_D_LP1    DECFSZ	LSD, F		;
            GOTO	KB_D_LP1	;
            DECFSZ	MSD, F		;
            GOTO	KB_D_LP1	;
END_DELAY   MOVF	PORTB, W	;
            ANDLW	0xE0		; Keep only the 3 switch values
            SUBWF	TEMP, F		;
            BTFSS	STATUS, Z	; Is the Zero bit set?
                                        ;    (switches were the same on 2 reads)
            GOTO	DEBOUNCE	; NO, Try another read
KEY_MATCH   MOVWF	TEMP		; YES, need to see which is depressed.
;
            MOVLW	0x80		; Since doing key inputs, clear TMR1
            MOVWF	TMR1H		;   for 1 sec overflow.
            CLRF	TMR1L		;
            BCF		PIR1, TMR1IF	; Clear Timer 1 Interrupt Flag

            BTFSS	TEMP, HR_MIN_SW		; Is the hour-min-off switch depressed?
            GOTO	SELECT_UNITS		; YES, specify the units selected
            BTFSS	TEMP, INC_SW		; Is the inc switch depressed?
            GOTO	INC_UNIT		; YES, Increment the selected Units
            BTFSS	TEMP, CLR_MIN_SW	; Is the clear minute switch depressed?
            GOTO	CLR_MIN			; YES, clear the minutes.
;
; No key match occured, or finished with PortB interrupt and need to clear interrupt condition.
;
CLR_RB					; No RB<7:5> keys are depressed (rising edge Int.)
            MOVF	PORTB, F	; Clear the PORTB mismatch condition
            BCF		INTCON, RBIF	; Clear the PORTB Int Flag
        if ( Debug )
            bcf		PORTD, 0	; Set low, use to measure total
                                        ;     time in Int Service Routine
        endif
            RETFIE			; Return / Enable Global Interrupts
;
    page
SELECT_UNITS
            MOVLW	0xFF		;
            MOVWF	WAIT_CNTR	; WAIT_CNTR has LSb set after each SELECT UNIT key press.
            INCF	FLAG_REG, F		; Increment the pointer to the MIN_UNIT:HR_UNIT
            BSF		FLAG_REG, KEY_INPUT	;
            GOTO	DISPLAY			; Flash the Display of the selected unit
;
INC_UNIT
            CLRF	WAIT_CNTR		; WAIT_CNTR is cleared to zero after each key press.
            BTFSC	FLAG_REG, HR_UNIT	; Are the hour units selected?
            GOTO	INC_HRS			; YES, Increment the hour units
            BTFSS	FLAG_REG, MIN_UNIT	; Are the minute units selected?
            GOTO	CLR_RB			; NO, Not a valid key. Clear flags
;
            INCF	MIN, F			; YES, Increment the minute units
            MOVLW	0x3C			; This is Decimal 60
            SUBWF	MIN, W			; MIN - 60 = ?
            BTFSS	STATUS, Z		; MIN = 60?
            GOTO	DISPLAY			; NO, display time
                                            	; YES, MIN = 0 (use code from CLR_MIN)
CLR_MIN     CLRF	MIN			; MIN = 0
            MOVLW	0x04			; Clear the seconds 
            MOVWF	SECS			; Initial Second count = 4
            MOVLW	0x80			; Clear Timer 1, for 1 sec overflow
            MOVWF	TMR1H			;
            CLRF	TMR1L			;
            BCF		PIR1, TMR1IF		; Clear the TMR1 overflow interrupt.
            CLRF	WAIT_CNTR		; WAIT_CNTR is cleared to zero after each key press.
            BTFSC	TEMP, CLR_MIN_SW	; Is the clear minute switch depressed?
            GOTO	DISPLAY			; NO. Rollover from increment key
            BCF		FLAG_REG, MIN_UNIT	; YES, Clear ALL relevant flags
            BCF		FLAG_REG, HR_UNIT	;
            BCF		FLAG_REG, KEY_INPUT	;
            GOTO	DISPLAY			;
;
    page
;
T1_OVRFL
            BCF		PIR1, TMR1IF		; Clear Timer 1 Interrupt Flag
            BTFSS	FLAG_REG, KEY_INPUT	; Are we using the key inputs?
            GOTO	INC_TIME		; NO, Need to Increment the time
            INCF	WAIT_CNTR, F		; YES, 
            MOVLW	0x0A			; 10 counts x 1 seconds
            SUBWF	WAIT_CNTR, W		; Has the 10 Sec wait for key expired?
            BTFSS	STATUS, Z		; Is the result 0?
            GOTO	DISPLAY			; NO, Display value
            CLRF	WAIT_CNTR		; YES, Clear WAIT_CNTR
            BCF		FLAG_REG, KEY_INPUT	;
            BCF		FLAG_REG, HR_UNIT	;
            BCF		FLAG_REG, MIN_UNIT	;
;
;
INC_TIME	MOVLW	0x80			;
		MOVWF	TMR1H		; 1 Second Overflow
		INCF	SECS, F		;
		BTFSS	SECS, 6		; 
		GOTO	DISPLAY		;
		MOVLW	0x04		;
		MOVWF	SECS		;
		INCF	MIN, F		;
		MOVLW	0x3C		; W = 60d
		SUBWF	MIN, W		;
		BTFSS	STATUS, Z	;
		GOTO	DISPLAY		;
		CLRF	MIN		;
INC_HRS		INCF	HRS, F		;

		MOVLW	0x0C		; It is now 12:00, Toggle AM / PM
		SUBWF	HRS, W		;
		BTFSS	STATUS, Z	;
		GOTO	CK_13		; Need to check if HRS = 13
		BTFSS	FLAG_REG, AM	; Was it AM or PM
		GOTO	SET_AM		; Was PM, Needs to be AM
		BCF	FLAG_REG, AM	; It is PM
		GOTO	DISPLAY		;
SET_AM		BSF	FLAG_REG, AM	; It is AM
		GOTO	DISPLAY		;

CK_13		MOVLW	0x0D			; Check if HRS = 13
		SUBWF	HRS, W			;
		BTFSS	STATUS, Z		;
		GOTO	DISPLAY			;
		CLRF	HRS			;
		INCF	HRS, F			;
		GOTO	DISPLAY			;
;
	page
INIT_DISPLAY
		MOVLW	DISP_ON			; Display On, Cursor On
		CALL	SEND_CMD		; Send This command to the Display Module
		MOVLW	CLR_DISP		; Clear the Display
		CALL	SEND_CMD		; Send This command to the Display Module
		MOVLW	ENTRY_INC		; Set Entry Mode Inc., No shift
		CALL	SEND_CMD		; Send This command to the Display Module
		RETURN
;
DISPLAY
		MOVLW	DD_RAM_ADDR		;
		CALL	SEND_CMD		;
;
		BTFSC	FLAG_REG, KEY_INPUT	; Do we need to flash the selectected units?
		GOTO	FLASH_UNITS		; YES, we need to flash selected units
		CALL	LOAD_HRS		; NO, do a normal display
		CALL	LOAD_COLON		;
		CALL	LOAD_MIN		;
		GOTO	LOAD_AM			;
;
FLASH_UNITS
		CLRF	PCLATH			; This clears PCLATH, This table in 1st
		MOVF	FLAG_REG, W		;    256 bytes of program memory
		ANDLW	0x03			; only HR_UNIT and MIN_UNIT bit can be non-zero
UNIT_TBL
		ADDWF	PCL, F			; HR_UNIT:MIN_UNIT
		GOTO	NO_UNITS		;       0 0        - Display everything.
		GOTO	HR_UNITS		;       0 1        - Flash the hour units
		GOTO	MIN_UNITS		;       1 0        - Flash the minute units
UNIT_TBL_END
		MOVLW	0xFC			;       1 1        - Need to clear FLAG_REG<HR_UNIT:MIN_UNIT>
		ANDWF	FLAG_REG, F		;
		GOTO	NO_UNITS		;       0 0        - Display everything.
;
	if ( (UNIT_TBL & 0x0FF) >= (UNIT_TBL_END & 0x0FF) )
       MESSG   "Warning: Table UNIT_TBL crosses page boundry in computed jump"
    endif
;
;
HR_UNITS
		BTFSS	WAIT_CNTR, 0		; If WAIT_CNTR is odd,
                                        	;    hour digits are displayed as blank
		GOTO	SKIP_BLK_HRS		;
		MOVLW	' '			;
		CALL	SEND_CHAR		;
		MOVLW	' '			;
		CALL	SEND_CHAR		;
SKIP_BLK_HRS
		BTFSS	WAIT_CNTR, 0		; WAIT_CNTR was even, display hour digits
		CALL	LOAD_HRS		;
;
		MOVLW	':'			; : always on, display all other character
		CALL	SEND_CHAR		;
		CALL	LOAD_MIN		;
		GOTO	LOAD_AM			;
;
	page
MIN_UNITS
		CALL	LOAD_HRS		; Display hours
		MOVLW	':'			; : always on
		CALL	SEND_CHAR		;
		BTFSS	WAIT_CNTR, 0		; If WAIT_CNTR is odd,
                                        	;    minute digits are displayed as blank
		GOTO	SKIP_BLK_MIN		;
		MOVLW	' '			;
		CALL	SEND_CHAR		;
		MOVLW	' '			;
		CALL	SEND_CHAR		;
SKIP_BLK_MIN
		BTFSS	WAIT_CNTR, 0		; WAIT_CNTR was even, display minute digits
		CALL	LOAD_MIN		;
		GOTO	LOAD_AM			;
;			
NO_UNITS
		CALL	LOAD_HRS		; Display all character
		MOVLW	':'			;
		CALL	SEND_CHAR		;
		CALL	LOAD_MIN		;
		GOTO	LOAD_AM			;
;
LOAD_HRS
		MOVF	HRS, W			; Load the Wreg with the value 
		CALL	BIN_2_BCD		;   to convert to BCD
		MOVF	MSD, W			; Load the MSD value into the Wreg
		CALL	NUM_TABLE		; Get the ASCII code
		CALL	SEND_CHAR		; Send this Character to the Display
;
		MOVF	LSD, W			; Load the LSD value into the Wreg
		CALL	NUM_TABLE		; Get the ASCII code
		CALL	SEND_CHAR		; Send this Character to the Display
		RETURN
;
LOAD_COLON	MOVLW	' '			; ASCII value for a Blank space
		BTFSC	SECS, 0			; Is it an EVEN or ODD second
		ADDLW	':' - ' '		; Is ODD, Second colon is ON.
						;   Add delta offset of ASCII Characters
		CALL	SEND_CHAR		; Send this Character to the Display
		RETURN
;
LOAD_MIN
		MOVF	MIN, W			; Load the Wreg with the value 
		CALL	BIN_2_BCD		;   to convert to BCD
		MOVF	MSD, W			; Load the MSD value into the Wreg
		CALL	NUM_TABLE		; Get the ASCII code
		CALL	SEND_CHAR		; Send this Character to the Display
;
		MOVF	LSD, W			; Load the LSD value into the Wreg
		CALL	NUM_TABLE		; Get the ASCII code
		CALL	SEND_CHAR		; Send this Character to the Display
		RETURN
;
	page
LOAD_AM		MOVLW	' '			; ASCII value for a Blank space
		CALL	SEND_CHAR		; Send this Character to the Display
		MOVLW	'A'			; ASCII value for a Blank space

⌨️ 快捷键说明

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