PIC16F628 Timer Reloj Digital
Este temporizador de reloj utiliza un microcontrolador PIC16F628 para mostrar 3 y el tiempo de 1/2 dígitos y controlar una carga externa. Puede ser programado para tiempo de 1 a 59 minutos. El reloj incluye un calendario con año bisiesto y ajustes opcionales de verano. La salida del temporizador se puede ajustar de 1 a 59 minutos y de forma manual encendido y apagado. El reloj también tiene una función de corrección que permite a un segundo adicional que se añade cada tantas horas para compensar un oscilador ligeramente ejecuta lentamente. El oscilador utiliza un cristal de reloj común 32,768 KHz y la frecuencia puede ajustarse ligeramente con el condensador de 24pF en el lado derecho del cristal.
;------------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
————————-Compiled HEX code ————————–
:0200000059287D :08000800B700030EB9008312DA :10001000A80A3C302806031D5328A801A20A122171 :100020003C302206031D5328A201A10A2E212621BD :100030000D302106031D1E28A101A10A0C30210646 :10004000031D5328AB0AAB102B185328A60A25080A :1000500097202606031D3C28A601A60AA50A0D30F6 :100060002506031D3C28A501A50AAD0A05302D066D :10007000031D3C28AD01AD0AA70A08302706031D61 :100080004328A701A70A02302506031D53281D3067 :100090002606031D532804302D0603195328033068 :1000A000A500A601A60A0B11390E8300B70E370E64 :1000B0000900831603130030860070308500811616 :1000C0008111011083120310031183108B160B1181 :1000D0008B1707309F000230A1003830A200063095 :1000E000A3001E30A4000330A5000730A600013095 :1000F000A700A801AB012D30AA00A901AC01023074 :10010000AD001230AE00BB01BF01BD01C001213006 :1001100084000F30B800A528820740347934243495 :1001200030341934123402347834003410348207F5 :10013000003420341E3420341F3420341F34203443 :1001400020341F3420341F3420344E21FA200E3046 :100150003806031DAD28213084002E303806031DDB :10016000B328213084000D303806031DB9287E21C4 :1001700089212D303806031DBF287E2189212B308F :100180003806031DC9287E21800A0D300006031998 :10019000800127303806031DD9287E21840A800A71 :1001A0003C30000603198001283004060319A80119 :1001B0008403073038060319BB130B303806031DC0 :1001C000A528BB17BF01A5288C203B04860008008A :1001D0001930BA00A000A00BEB28BA0BEA280800DF :1001E000B6010A30B60AB502031CF728F228B60396 :1001F000B50708007F3085003B04860083167F30FA :1002000085003F308500831205130A30E920050878 :10021000B80083167F3085007030850083122F3040 :10022000B8050800BF0A2A083F060319BB132108B6 :100230002306031D080022082406031D08002B08BE :100240002906031D0800BB17BF010800BD0A2E08C0 :100250003D06031D0800A80ABD0108002C1C08006B :1002600001302706031D080003302106031D080086 :100270002B18080003302506031D4529A61D08007C :10028000AC180800A10AAC1408000B302506031DA9 :100290000800AC1C0800A103AC100800C00121300C :1002A0000406031D55292B18C01723300406031D0F :1002B0005B292918C0170008B500F020361C6629F4 :1002C0003608E4200E3040048500E8203508E4209C :1002D0000D3040048500E820840A0008B500F020B5 :1002E0003608E4200B3040048500E8203508E4207F :1002F000073040048500E820840308004E21FA20DE :100300000F303806031908002F303806031908008B :100310007E29840A840A2F300406031D0800213038 :04032000840008004D :02400E00103F61 :00000001FF
Fuente: http://electronics-diy.com/
|
|
![]() | 19 noviembre 2012 en Electronica | tags: Circuitos electrónicos, Electronica |





















