📄 clock.asm
字号:
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 + -