Buscar

Relógio com PIC16F628A

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

;------------Program Listing, Clock.asm - REV 1 - 11/08/06 ---------
 LIST P=16F628 ; Device number (PIC16F628)
 ERRORLEVEL -224 ; suppress annoying message because of tris
 ERRORLEVEL -302 ; suppress message because of page change
;--------------------- Configuration ---------------------------------
_BODEN_OFF equ H'3FBF' ; Brown out detection off
_CP_OFF equ H'3FFF' ; Code protection off
_PWRTE_ON equ H'3FF7' ; Power-on reset enabled
_WDT_OFF equ H'3FFB' ; Watch dog timer off
_LVP_OFF equ H'3F7F' ; Low Voltage programming off
_INTRC_OSC_NOCLKOUT equ H'3FFC' ; Use Internal RC Oscillator
_MCLRE_OFF equ H'3FDF' ; Use RA5 as functional input
 __CONFIG _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _PWRTE_ON & _LVP_OFF & _BODEN_OFF & _MCLRE_OFF
;--------------------- Define Variables -------------------------------
INDF equ 00h
FSR equ 04h
CMCON equ 1Fh ; Comparator Control Address
INTCON equ 0Bh ; Interrupt control register
OPTION_REG equ 81h ; Option register
STATUS equ 03h ; Status register
TRISA equ 85h ; I/O control for port A
TRISB equ 86h ; I/O control for port B
PORTB equ 06h ; Address of port B
PORTA equ 05h ; Address of port A
PC equ 02h ; Program counter
COUNTER equ 20h ; Addresses 20H-7FH = general RAM
HOURS equ 21h ; These 20 addresses for display
MINUTES equ 22h
HOURS_A equ 23h
MINUTES_A equ 24h
MONTH equ 25h
DAYS equ 26h
WEEKDAY equ 27h
SECONDS equ 28h
AMPM_A equ 29h
TIMER_LIMIT equ 2ah
AMPM equ 2bh
DAYLIGHT equ 2ch
YEAR equ 2dh
CORRECTION equ 2eh
TEMP equ 35h ; Value passed to Digits routine
TENS equ 36h ; Value returned from Digits routine
TEMPW equ 37h ; Used in interrupt to save w
SWITCH equ 38h ; Value returned from switches
STATUS_SAVE equ 39h ; Interrupt (save status)
TEMP1 equ 3ah ; Part of delay routine
ALARM equ 3bh ; Alarm on/off (bit 7 set =on)
; BLANK equ 3ch ; Not used
LIMIT equ 3dh ; Increments every hour to (correction)
TEMP_SAVE equ 3eh ; Saves a copy of TEMP
TIMER equ 3fh
AMPM_LED equ 40h
;--------------------- Program Starts here --------------------------
 goto INIT
;--------------------- Interrupt routine to update time -------------
 org 0x04
 movwf TEMPW ; Save w
 swapf STATUS,0 ; Get status register into w
 movwf STATUS_SAVE ; Save status register
 bcf STATUS,5 ; Go to bank 0 (00)
 incf SECONDS,f ; Advance seconds
 movlw d'60'
 xorwf SECONDS,0
 btfss STATUS,2 ; Check for 60 seconds
 goto Done ; Jump out if not 60
 clrf SECONDS
 incf MINUTES,f
 call Alarm
 movlw d'60'
 xorwf MINUTES,0
 btfss STATUS,2 ; Check for 60 minutes
 goto Done ; Jump out if not 60
 clrf MINUTES
 incf HOURS,f
 call Daylight
 call Add_Second ; Compensate for slow oscillator
 movlw d'13'
 xorwf HOURS,0
 btfss STATUS,2 ; Check for 13 hours
 goto Noon ; Jump out if not 13
 clrf HOURS
 incf HOURS,f ; Set hours to 1:00
Noon
 movlw d'12'
 xorwf HOURS,0
 btfss STATUS,2 ; Check for 12 hours
 goto Done ; Jump out if not 12
 incf AMPM,f
 bcf AMPM,1 ; Clear Bit 1 to stop overflow
 btfsc AMPM,0 ; AM = Bit 0 clear
 Goto Done
 incf DAYS,f
 movfw MONTH
 call Table
 xorwf DAYS,0 ; Check for Days = Limit
 btfss STATUS,2
 goto WeekDay
 clrf DAYS
 incf DAYS,f
 incf MONTH,f
 movlw d'13'
 xorwf MONTH,0
 btfss STATUS,2 ; Check for new year
 goto WeekDay
 clrf MONTH
 incf MONTH,f
 incf YEAR,f
 movlw d'5'
 xorwf YEAR,0
 btfss STATUS,2
 goto WeekDay
 clrf YEAR
 incf YEAR,f
WeekDay
 incf WEEKDAY,f
 movlw d'8'
 xorwf WEEKDAY,0
 btfss STATUS,2 ; Check for new week
 goto Leap
 clrf WEEKDAY
 incf WEEKDAY,f ; Set weekday to 1 = Sunday
Leap
 movlw d'2'
 xorwf MONTH,0
 btfss STATUS,2
 goto Done
 movlw d'29'
 xorwf DAYS,0
 btfss STATUS,2
 goto Done
 movlw d'4'
 xorwf YEAR,0
 btfsc STATUS,2
 goto Done
 movlw d'3'
 movwf MONTH
 clrf DAYS
 incf DAYS,f
Done
 bcf INTCON,2
 swapf STATUS_SAVE,0
 movwf STATUS
 swapf TEMPW,f
 swapf TEMPW,0
 retfie
;--------------------- End Interrupt Procedure ----------------------
INIT ; Initialize variables
 bsf STATUS,5 ; Select memory bank 1 (01)
 bcf STATUS,6 ; Select memory bank 1 (01)
 movlw b'00000000'
 movwf TRISB ; Set port B as output
 movlw b'01110000' ;
 movwf TRISA ; Set port A as output, RA4,5,6=Input
 bsf OPTION_REG,5 ; Select Timer0 (TOCS=1)
 bcf OPTION_REG,3 ; Assign prescaler to timer0
 bcf OPTION_REG,0 ; Set prescaler to 128
 bcf STATUS,5 ; Reset to bank 0
 bcf STATUS,0 ; Clear carry bit
 bcf STATUS,2 ; Clear zero flag
 bcf STATUS,1 ;
 bsf INTCON,5 ; Enable timer0 interrupt
 bcf INTCON,2 ; Clear interrupt flag
 bsf INTCON,7 ; Enable global interrupt
 movlw 07h
 movwf CMCON ; Comparators off
 movlw d'2'
 movwf HOURS ; Initialize hours to 2
 movlw d'56'
 movwf MINUTES ; Inititlize minutes to 56
 movlw d'6'
 movwf HOURS_A ; Initialize alarm hours to 6
 movlw d'30'
 movwf MINUTES_A
 movlw
d'3'
 movwf MONTH ; Initialize Month to March, 7
 movlw d'7'
 movwf DAYS
 movlw d'1'
 movwf WEEKDAY ; Initialize weekday to Sunday (1)
 clrf SECONDS
 clrf AMPM ; Initialize AMPM to AM
 movlw d'45'
 movwf TIMER_LIMIT ; Initialize alarm timer to 45
 clrf AMPM_A
 clrf DAYLIGHT ; Turn off daylight savings time
 movlw d'2'
 movwf YEAR ; Set year to 2 (Leap year=4)
 movlw d'18'
 movwf CORRECTION ; Add 1 second every 18 hours
 clrf ALARM ; Turn off alarm
 clrf TIMER
 clrf LIMIT
 clrf AMPM_LED
 movlw h'21'
 movwf FSR ; Address pointer points to Hours
 movlw d'15'
 movwf SWITCH
 
 goto Main
Array ; Data for 7 segment digits
 addwf PC,1
 retlw b'01000000' ; "0" 
 retlw b'01111001' ; "1"
 retlw b'00100100' ; "2"
 retlw b'00110000' ; "3" 
 retlw b'00011001' ; "4"
 retlw b'00010010' ; "5"
 retlw b'00000010' ; "6"
 retlw b'01111000' ; "7"
 retlw b'00000000' ; "8"
 retlw b'00010000' ; "9"
Table ; Days per month plus 1
 addwf PC,1
 retlw d'00' ; Unused line
 retlw d'32' ; Jan
 retlw d'30' 
 retlw d'32'
 retlw d'31' 
 retlw d'32' ; May
 retlw d'31'
 retlw d'32' 
 retlw d'32'
 retlw d'31'
 retlw d'32'
 retlw d'31'
 retlw d'32' ; December
Main ; ------------ Main Loop ----------------------
 call Display ; Display data
 call Read_Port ; Check for switch closed
 movlw d'14' ; Check for time switch closed
 xorwf SWITCH,0
 btfss STATUS,2
 goto Set_Time
 movlw h'21'
 movwf FSR
Set_Time
 movlw d'46' ; Check for time switch and RA5 closed
 xorwf SWITCH,0
 btfss STATUS,2
 goto Increment_Display
 movlw h'21'
 movwf FSR
Increment_Display
 movlw d'13'
 xorwf SWITCH,0
 btfss STATUS,2
 goto Function ; Function key not hit (13)
 call Wait ; Wait for switch to open
 call Increment_Pointer
Function
 movlw d'45'
 xorwf SWITCH,0
 btfss STATUS,2
 goto Increment_100s ; Function key not hit (13)
 call Wait ; Wait for switch to open
 call Increment_Pointer
Increment_100s ; On plus RA5 = 32 + 11 = 43
 movlw d'43'
 xorwf SWITCH,0
 btfss STATUS,2
 goto Increment_10s
 call Wait
 incf INDF,f
 movlw d'13' ; Rollover at 12
 xorwf INDF,0
 btfsc STATUS,2
 clrf INDF
Increment_10s ; RA5 + alarm off = 39
 movlw d'39'
 xorwf SWITCH,0
 btfss STATUS,2
 goto Alarm_Toggle
 call Wait
 incf FSR,f
 incf INDF,f
 movlw d'60' ; Rollover at 60
 xorwf INDF,0
 btfsc STATUS,2
 clrf INDF
 movlw h'28' ; Check for Seconds display
 xorwf FSR,0
 btfsc STATUS,2
 clrf SECONDS ; Zero seconds
 decf FSR,f
Alarm_Toggle
 movlw d'7' ; Alarm Off
 xorwf SWITCH,0
 btfsc STATUS,2
 bcf ALARM,7
 movlw d'11' ; Alarm On
 xorwf SWITCH,0
 btfss STATUS,2
 goto Main
 bsf ALARM,7
 clrf TIMER
 goto Main
;--------------------- End of Main Loop ------------------------------
Output ; Write data to port B
 call Array
 iorwf ALARM,0
 movwf PORTB
 return
Delay ;------------------------ Delay ---- about 600 uS ------------
 movlw d'25'
Delay_0
 movwf TEMP1
Delay_1 movwf COUNTER
Delay_2 decfsz COUNTER,f
 goto Delay_2
 decfsz TEMP1,f
 goto Delay_1
 return
Digits ; Converts value in TEMP to 2 single digits - TENS and TEMP
 clrf TENS
 movlw d'10'
Loop
 incf TENS,f
 subwf TEMP,f
 btfss STATUS,0
 goto Ones
 goto Loop
Ones
 decf TENS,f
 addwf TEMP,f
 return
Read_Port ; Look to see if switch is closed
 movlw d'127'
 movwf PORTA
 iorwf ALARM,0 ; add alarm bit
 movwf PORTB ; Set port B to high level
 bsf STATUS,5 ; Select bank 1 (01)
 movlw b'01111111'
 movwf TRISA ; Set port A as input, RA7=output
 movlw b'00111111'
 movwf TRISA ; Set RA6 to output
 bcf STATUS,5 ; Return to bank 0 (00)
 bcf PORTA,6 ; Low level on RA6
 movlw d'10'
 call Delay_0 ; Wait
 movfw PORTA ; Read the pins
 movwf SWITCH
 bsf STATUS,5 ; Select Bank 1
 movlw b'01111111'
 movwf TRISA ; Set port A to input
 movlw b'01110000'
 movwf TRISA ; Set porta,0,1,2,3 to output
 bcf STATUS,5 ; Return to Bank 0
 movlw b'00101111' ; RA5 is normally 0
 andwf SWITCH,f ; Switch returns value 0 to 47
 return
Alarm
 incf TIMER,f
 movfw TIMER_LIMIT ; Default is 45 minutes
 xorwf TIMER,0
 btfsc STATUS,2
 bcf ALARM,7
 movfw HOURS
 xorwf HOURS_A,0
 btfss STATUS,2
 return
 movfw MINUTES
 xorwf MINUTES_A,0
 btfss STATUS,2
 return
 movfw AMPM
 xorwf AMPM_A,0
 btfss STATUS,2
 return
 bsf ALARM,7
 clrf TIMER
 return
Add_Second
 incf LIMIT,f
 movfw CORRECTION
 xorwf LIMIT,0
 btfss STATUS,2
 return
 incf SECONDS,f
 clrf LIMIT
 return
Daylight ;----------------------- Daylight savings adjustment
 btfss DAYLIGHT,0
; Bit 0 set = Daylight enabled
 return
 movlw d'1' ; Check for Sunday
 xorwf WEEKDAY,0
 btfss STATUS,2
 return
 movlw d'3' ; Adjust daylight at 3AM
 xorwf HOURS,0
 btfss STATUS,2
 return
 btfsc AMPM,0 ; Adjust daylight if AM
 return
 movlw d'3'
 xorwf MONTH,0
 btfss STATUS,2
 goto MinusHour
 btfss DAYS,3 ; Bit 3 must be set for 2nd Sunday
 return
 btfsc DAYLIGHT,1 ; Bit 1 set = Correction done (March)
 return
 incf HOURS,f
 bsf DAYLIGHT,1 ; Correction done
 return
MinusHour ;---------- Subtract 1 hour on 1st Sunday in November
 movlw d'11'
 xorwf MONTH,0
 btfss STATUS,2
 return
 btfss DAYLIGHT,1 ; Bit 1 set = Do Correction
 return
 decf HOURS,f
 bcf DAYLIGHT,1 ; Bit 1 clear = Correction done
 return
Display ; -------------------- Display Data -----------------------
 clrf AMPM_LED ; AMPM off
 movlw h'21'
 xorwf FSR,0
 btfss STATUS,2
 goto $ +3
 btfsc AMPM,0
 bsf AMPM_LED,7 ; Add AMPM light (time)
 movlw h'23'
 xorwf FSR,0
 btfss STATUS,2
 goto $ +3
 btfsc AMPM_A,0
 bsf AMPM_LED,7 ; Add AMPM light (alarm)
 movfw INDF ; Get 100s data
 movwf TEMP
 call Digits
 btfss TENS,0
 goto Ones_Hours
 movfw TENS ; Light 10s Hours LED
 call Output
 movlw d'14'
 iorwf AMPM_LED,0 ; Add AMPM light if time or alarm
 movwf PORTA
 call Delay
Ones_Hours
 movfw TEMP
 call Output
 movlw d'13'
 iorwf AMPM_LED,0 ; Add AMPM light if time or alarm
 movwf PORTA
 call Delay
 incf FSR,f
 movfw INDF
 movwf TEMP
 call Digits
 movfw TENS
 call Output
 movlw d'11'
 iorwf AMPM_LED,0 ; Add AMPM light if time or alarm
 movwf PORTA
 call Delay
 movfw TEMP
 call Output
 movlw d'7'
 iorwf AMPM_LED,0 ; Add AMPM light if time or alarm
 movwf PORTA
 call Delay
 decf FSR,f
 return
Wait ; Wait until switches are open
 call Display
 call Read_Port
 movlw d'15' ; Switches open in run mode
 xorwf SWITCH,0
 btfsc STATUS,2
 return
 movlw d'47' ; Switches open in program mode
 xorwf SWITCH,0
 btfsc STATUS,2
 return
 goto Wait
Increment_Pointer
 incf FSR,f ; Increment Pointer 2 steps
 incf FSR,f
 movlw h'2f'
 xorwf FSR,0
 btfss STATUS,2
 return
 movlw h'21'
 movwf FSR ; Set Pointer to Time display
 return
 end

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Outros materiais