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

📄 clock.asm

📁 Low-Power Real-Time Clock
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		BTFSS	FLAG_REG, AM		; Is it AM or PM
		ADDLW	'P' - 'A'		; Is PM, Add delta offset of ASCII Characters
		CALL	SEND_CHAR		; Send this Character to the Display
		MOVLW	'M'
		CALL	SEND_CHAR		; Send this Character to the Display
;
		BSF     STATUS, RP0		; Bank 1
		BCF	OPTION_REG, NOT_RBPU		; Turn on PORTB Pull-up
		BCF     STATUS, RP0		; Bank 0
		GOTO	CLR_RB			; You've displayed the time, Clear RBIF 
;
;
;******************************************************************************
; The BIN_2_BCD routine converts the binary number, in the W register, to a 
; binary coded decimal (BCD) munber. This BCD number is stored MSD:LSD. This
; routine is used by the DISPLAY subroutine, to convert the time values.
;******************************************************************************
;
BIN_2_BCD   CLRF    MSD                 ; This value contain the 10's digit value
            MOVWF   LSD                 ; This value contain the 1's digit value
TENS_SUB    MOVLW   .10                 ; A decimal 10
            SUBWF   LSD, W              ;
            BTFSS   STATUS, C           ; Did this subtract cause a Negative Result?
            RETLW   0                   ; YES, Return from this Routine
            MOVWF   LSD                 ; No, move the result into LSD
            INCF    MSD, F              ; Increment the most significat digit
            GOTO    TENS_SUB            ;
;			
;
; Should NEVER get here
;
ERROR1      BCF     STATUS, RP0         ; Bank 0
;
        if ( Debug )
            BSF     PORTD, 1
            BCF     PORTD, 1
        else
            BSF     PORTC, 0
            BCF     PORTC, 0
        endif
            GOTO    ERROR1
;
	page
;
;*******************************************************************
;* SendChar - Sends character to LCD                               *
;* This routine splits the character into the upper and lower      * 
;* nibbles and sends them to the LCD, upper nibble first.          *
;* The data is transmitted on the PORT<3:0> pins                   *
;*******************************************************************

SEND_CHAR
            MOVWF   CHAR                ; Character to be sent is in W
            CALL    BUSY_CHECK          ; Wait for LCD to be ready
            SWAPF   CHAR, W
            ANDLW   0x0F                ; Get upper nibble
            MOVWF   LCD_DATA            ; Send data to LCD
            BCF     LCD_CNTL, RW       ; Set LCD to read
            BSF     LCD_CNTL, RS        ; Set LCD to data mode
            BSF     LCD_CNTL, E         ; toggle E for LCD
            BCF     LCD_CNTL, E
            MOVF    CHAR, W
            ANDLW   0x0F                ; Get lower nibble
            MOVWF   LCD_DATA            ; Send data to LCD
            BSF     LCD_CNTL, E         ; toggle E for LCD
            BCF     LCD_CNTL, E
            RETURN

;*******************************************************************
;* SendCmd - Sends command to LCD                                  *
;* This routine splits the command into the upper and lower        * 
;* nibbles and sends them to the LCD, upper nibble first.          *
;* The data is transmitted on the PORT<3:0> pins                   *
;*******************************************************************

SEND_CMD
            MOVWF   CHAR                ; Character to be sent is in W
            CALL    BUSY_CHECK          ; Wait for LCD to be ready
            SWAPF   CHAR, W
            ANDLW   0x0F                ; Get upper nibble
            MOVWF   LCD_DATA            ; Send data to LCD
            BCF     LCD_CNTL, RW       ; Set LCD to read
            BCF     LCD_CNTL, RS        ; Set LCD to command mode
            BSF     LCD_CNTL, E         ; toggle E for LCD
            BCF     LCD_CNTL, E
            MOVF    CHAR, W
            ANDLW   0x0F                ; Get lower nibble
            MOVWF   LCD_DATA            ; Send data to LCD
            BSF     LCD_CNTL, E         ; toggle E for LCD
            BCF     LCD_CNTL, E
            RETURN
    page
;*******************************************************************
;* This routine checks the busy flag, returns when not busy        *
;*  Affects:                                                       *
;*      TEMP - Returned with busy/address                          *
;*******************************************************************

BUSY_CHECK
;
        if ( Debug )
            BSF     PORTD, 3
            BCF     PORTD, 3
        endif
            CLRF    LCD_DATA            ;** Have PORTB<3:0> output low
            BSF     STATUS, RP0         ; Bank 1
            BSF     OPTION_REG, NOT_RBPU      ; Turn off PORTB Pull-up 
            MOVLW   0xFF                ; Set PortB for input
            MOVWF   LCD_DATA_TRIS
            BCF     STATUS, RP0         ; Bank 0
            BCF     LCD_CNTL, RS        ; Set LCD for Command mode
            BSF     LCD_CNTL, RW       ; Setup to read busy flag
            BSF     LCD_CNTL, E         ; Set E high
            BCF     LCD_CNTL, E         ; Set E low
            SWAPF   LCD_DATA, W         ; Read upper nibble busy flag, DDRam address
            ANDLW   0xF0                ; Mask out lower nibble
            MOVWF   TEMP                ;
            BSF     LCD_CNTL, E         ; Toggle E to get lower nibble
            BCF     LCD_CNTL, E
            MOVF    LCD_DATA, W         ; Read lower nibble busy flag, DDRam address
            ANDLW   0x0F                ; Mask out upper nibble
            IORWF   TEMP, F             ; Combine nibbles
            BTFSC   TEMP, 7             ; Check busy flag, high = busy
            GOTO    BUSY_CHECK          ; If busy, check again
            BCF     LCD_CNTL, RW
            BSF     STATUS, RP0         ; Bank 1
            MOVLW   0xF0                ;
            MOVWF   LCD_DATA_TRIS       ; RB7 - 4 = inputs, RB3 - 0 = output
            BCF     STATUS, RP0         ; Bank 0
            RETURN
;
    page
;
;******************************************************************************
;*****      Start program here, Power-On Reset occurred.
;******************************************************************************
;
START                               ; POWER_ON Reset (Beginning of program)
            BCF     STATUS, RP0     ; Bank 0
            MOVLW   0x0C            ; Decimal 12
            MOVWF   HRS             ; HOURS = 12
            CLRF    MIN             ; MIN   = 00
            MOVLW   0x00            ;
            MOVWF   FLAG_REG        ; PM light is on
            MOVLW   0x04            ; Initial value of seconds (64d - 60d)
            MOVWF   SECS            ; This allows a simple bit test to see if 60
                                    ;   secs has elapsed.
            MOVLW   0x80            ; TIM1H:TMR1L = 0x8000 gives 1 second
            MOVWF   TMR1H           ;   overflow, at 32 KHz.
            CLRF    TMR1L           ;
;
MCLR_RESET                          ; A Master Clear Reset
            CLRF    STATUS          ; Do initialization (Bank 0)
            CLRF    INTCON
            CLRF    PIR1
            BSF     STATUS, RP0     ; Bank 1
            MOVLW   0x00            ; The LCD module does not like to work w/ weak pull-ups
            MOVWF   OPTION_REG        ;
            CLRF    PIE1            ; Disable all peripheral interrupts
            MOVLW   0xFF            ;
            MOVWF   ADCON1          ; Port A is Digital (for 16C7x devices).
;
;
            BCF     STATUS, RP0     ; Bank 0
            CLRF    PORTA           ; ALL PORT output should output Low.
            CLRF    PORTB
            CLRF    PORTC
            CLRF    PORTD
            CLRF    PORTE
            BCF     T1CON, TMR1ON   ; Timer 1 is NOT incrementing
;
            BSF     STATUS, RP0     ; Select Bank 1
            CLRF    TRISA           ; RA5 -  0 outputs
            MOVLW   0xF0            ;
            MOVWF   TRISB           ; RB7 - 4 inputs, RB3 - 0 outputs 
            CLRF    TRISC           ; RC Port are outputs
            BSF     TRISC, T1OSO    ; RC0 needs to be input for the oscillator to function
            CLRF    TRISD           ; RD Port are outputs
            CLRF    TRISE           ; RE Port are outputs
            BSF     PIE1, TMR1IE    ; Enable TMR1 Interrupt
            BCF     OPTION_REG, NOT_RBPU  ; Enable PORTB pull-ups
            BCF     STATUS, RP0     ; Select Bank 0
            MOVF    PORTB, F        ; Need to clear 1st RBIF, due to
            BCF     INTCON, RBIF    ;    set up of PORTB
;
    page
;
; Initilize the LCD Display Module
;
            CLRF    LCD_CNTL        ; ALL PORT output should output Low.

DISPLAY_INIT
            MOVLW   0x02            ; Command for 4-bit interface
            MOVWF   LCD_DATA        ;
            BSF     LCD_CNTL, E     ; 
            BCF     LCD_CNTL, E     ;
;
; This routine takes the calculated times that the delay loop needs to
; be executed, based on the LCD_INIT_DELAY EQUate that includes the
; frequency of operation. These uses registers before they are needed to 
; store the time.
;
LCD_DELAY   MOVLW   LCD_INIT_DELAY  ;
            MOVWF   MSD             ; Use MSD and LSD Registers to Initilize LCD
            CLRF    LSD             ;
LOOP2       DECFSZ  LSD, F          ; Delay time = MSD * ((3 * 256) + 3) * Tcy
            GOTO    LOOP2           ;
            DECFSZ  MSD, F          ;
END_LCD_DELAY
            GOTO    LOOP2           ;
;
; Command sequence for 2 lines of 5x7 characters
;
CMD_SEQ     MOVLW   0X02
            MOVWF   LCD_DATA
            BSF     LCD_CNTL, E     ; 
            BCF     LCD_CNTL, E     ;
            MOVLW   0x08            ; 
            MOVWF   LCD_DATA        ;
            BSF     LCD_CNTL, E     ; 
            BCF     LCD_CNTL, E     ;
;
; Busy Flag should be valid after this point
;
            MOVLW   DISP_ON         ;
            CALL    SEND_CMD        ;
            MOVLW   CLR_DISP        ;
            CALL    SEND_CMD        ;
            MOVLW   ENTRY_INC       ;
            CALL    SEND_CMD        ;
            MOVLW   DD_RAM_ADDR     ;
            CALL    SEND_CMD        ;
;
    page
;
; Initialize the Special Function Registers (SFR) interrupts
;
            CLRF    PIR1            ;
            MOVLW   0x0E
            MOVWF   T1CON           ; RC1 is overridden by TCKO
            BSF     INTCON, PEIE    ; Enable Peripheral Interrupts
            BSF     INTCON, RBIE    ; Disable PORTB<7:4> Change Interrupts
            BSF     INTCON, GIE     ; Enable all Interrupts
;
            CALL    INIT_DISPLAY    ;
            CALL    DISPLAY         ;
;
            MOVLW   0x0E
            MOVWF   T1CON           ; Enable T1 Oscillator, Ext Clock, Async, prescaler = 1
            BSF     T1CON, TMR1ON   ; Turn Timer 1 ON
;
        if ( PICMaster )
lzz         goto    lzz             ; Loop waiting for interrupts (for use with PICMASTER)
        else
;
SLEEP_LP    SLEEP                   ; Wait for Change on PORTB interrupt. or TMR1 timeout
            NOP                     ;
            GOTO    SLEEP_LP        ; 
;
        endif
;
; Here is where you do things depending on the type of RESET (Not a Power-On Reset).
;
OTHER_RESET   BTFSS  STATUS,NOT_TO     ; WDT Time-out?
WDT_TIMEOUT   GOTO   ERROR1         ; YES, This is error condition
        if ( Debug_PU )
            goto   START            ; MCLR reset, Goto START
        else
            GOTO   MCLR_RESET       ; MCLR reset, Goto MCLR_RESET
        endif
;
        if (Debug )
END_START     NOP                   ; END lable for debug
        endif
;
    page
;
    org     TABLE_ADDR
;
NUM_TABLE       MOVWF   TEMP                ; Store value to TEMP register
                MOVLW   HIGH (TABLE_ADDR)   ; Ensure that the PCLATH high has the 
                MOVWF   PCLATH              ;   correct value
                MOVF    TEMP, W             ; Value into table
                ANDLW   0x0F                ; Mask to 4-bits (00 - 0Fh) 
NUM_TBL         ADDWF   PCL, F              ; Determine Offset into table
                RETLW   '0'                 ; ASCII value of "0" in W register
                RETLW   '1'                 ; ASCII value of "1" in W register
                RETLW   '2'                 ; ASCII value of "2" in W register
                RETLW   '3'                 ; ASCII value of "3" in W register
                RETLW   '4'                 ; ASCII value of "4" in W register
                RETLW   '5'                 ; ASCII value of "5" in W register
                RETLW   '6'                 ; ASCII value of "6" in W register
                RETLW   '7'                 ; ASCII value of "7" in W register
                RETLW   '8'                 ; ASCII value of "8" in W register
                RETLW   '9'                 ; ASCII value of "9" in W register
                                            ; Any enter after is in error (Display an E)
                RETLW   'E'                 ; ASCII value of "E" in W register
                RETLW   'E'                 ; ASCII value of "E" in W register
                RETLW   'E'                 ; ASCII value of "E" in W register
                RETLW   'E'                 ; ASCII value of "E" in W register
                RETLW   'E'                 ; ASCII value of "E" in W register
NUM_TBL_END     RETLW   'E'                 ; ASCII value of "E" in W register
;
    if ( (NUM_TBL & 0xFF00) != (NUM_TBL_END & 0xFF00) )
       MESSG   "Warning: Table NUM_TBL crosses page boundry in computed jump"
    endif
;
;
    org     PMEM_END            ; End of Program Memory
            GOTO    ERROR1          ; If you get here your program was lost

    end

⌨️ 快捷键说明

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