;----------------------------------------------------------------------;
; BINCLK4M.ASM A clock that displays in bcd numbers ;
;----------------------------------------------------------------------;
; .-----------.
; -|RA2 RA1|- V+ = 4.5 or 5 Volts
; -|RA3 RA0|- X = 4.096 MHz xtal
; -|RA4 OSC1|--|X|-||--- gnd 20 pf caps
; -{r}- = 470 ohm V+ ---|MCLR OSC2|--|X|-||--- gnd
; -|<- = LED gnd ---|Vss Vdd|--- V+
; gnd ---|<--{r}--|RB0 RB7|-
; gnd ---|<--{r}--|RB1 RB6|-
; gnd ---|<--{r}--|RB2 RB5|---[PB]--- gnd <- SET PB
; gnd ---|<--{r}--|RB3 RB4|---[PB]--- gnd <- SHOW PB
; '-----------'
; PIC16F84 -[PB]- pushbutton
LIST P=16F84 ; tells which processor is used
INCLUDE "p16f84.inc" ; defines various registers etc. Look
ERRORLEVEL -224 ; supress annoying message from tris
__CONFIG _PWRTE_ON & _XT_OSC & _WDT_OFF ; config. switches
CBLOCK 0CH
sec ; seconds digit
sec10 ; 10's of second digit
mins ; minutes digit
min10 ; 10's of minutes digit
hr ; hours digit
hr10 ; 10's of hours digit
w_temp ; holds W during interrupt
status_temp ; holds STATUS during interrupt
fsr_temp ; holds FSR during interrupt
digit ; holds digit position
cntmsec ; used to count milliseconds
counter ; used to stretch isr out to 1 sec
flashcnt ; counter for flashing LED
ENDC
;----------------------------------------------------------------------;
; Here are some DEFINEs which give 'names' to pushbutton port bits ;
;----------------------------------------------------------------------;
#DEFINE SHOWPB PORTB, 4
#DEFINE SETPB PORTB, 5
ORG 0 ; start at location 0
goto main ; jump over to main routine
ORG 4
goto isr ; jump to interrupt routine
;----------------------------------------------------------------------;
; High limit + 1 of digits at position W ;
;----------------------------------------------------------------------;
sethi:
addwf PCL, f
dt H'A',H'6',H'A',H'6',H'A',H'3'
;----------------------------------------------------------------------;
; time delay routines ;
;----------------------------------------------------------------------;
micro4 addlw H'FF' ; subtract 1 from 'W'
btfss STATUS,Z ; skip when you reach zero
goto micro4 ; more loops
return
msec250: movlw D'250' ; delay for 250 milliseconds
;*** N millisecond delay routine ***
nmsec: movwf cntmsec ; delay for N (in W) millisec
msecloop: movlw D'248' ; 1 usec for load
call micro4 ; this instruction is 995 usec
nop ; 1 usec
decfsz cntmsec,f ; 1 usec, (2 if skip taken)
goto msecloop ; 2 usec, loop = 995+5 = 1 msec
return
;----------------------------------------------------------------------;
; Delay for one second ;
;----------------------------------------------------------------------;
onesecond: ; a subroutine that delays for 1 seconds
call msec250
call msec250
call msec250
call msec250
return
;----------------------------------------------------------------------;
; Put value in W on LEDs for 1 second ;
;----------------------------------------------------------------------;
sendnbr:
btfsc STATUS, Z ; skip if not zero
movlw H'0F' ; else all on for a zero
movwf PORTB ; light LEDs
call onesecond ; wait 1 second
clrf PORTB ; clear the LEDs
movlw D'100' ; pause for 0.1 sec
call nmsec
return
;----------------------------------------------------------------------;
; Send the current time out LEDs ;
;----------------------------------------------------------------------;
disptime:
movf hr10, W
call sendnbr
movf hr, W
call sendnbr
movf min10, W
call sendnbr
movf mins, W
call sendnbr
return
;----------------------------------------------------------------------;
; Wait until set button is released ;
;----------------------------------------------------------------------;
waitsetup: ; wait for set pushbutton up
btfss SETPB ; skip if set button released
goto waitsetup
movlw D'10'
call nmsec ; wait 10 msec for debounce
btfss SETPB ; check again for release
goto waitsetup ; false alarm, start over
return ; yes, finished
;----------------------------------------------------------------------;
; Initialization Subroutine ;
;----------------------------------------------------------------------;
init:
movlw B'0000000' ; all outputs port A
tris PORTA
movlw B'00110000' ; RB4, RB5 inputs, others outputs
tris PORTB ; on port B
movlw H'0' ; all low (off)
movwf PORTB
movlw B'00000100' ; pull-ups enabled
; prescaler assigned to TMR0
; prescaler set to 1:16
; rolls over each 1/125 th second
option
movlw 0
movwf hr10
movlw H'9' ; initialize hrs, mins and secs
movwf hr ; Do this before interrupts are
movlw H'5' ; turned on because isr also acts
movwf min10 ; on these registers
movlw H'0'
movwf mins
movwf sec10
movwf sec
movlw D'125' ; initialize isr counter
movwf counter
movlw B'10100000' ; GIE & T0IE set, T0IF cleared
movwf INTCON
return
;----------------------------------------------------------------------;
; Interrupt routine, increments time by one second (BCD) ;
;----------------------------------------------------------------------;
isr:
movwf w_temp ; save W
swapf STATUS,W ; save status
movwf status_temp ; without changing flags
swapf FSR,W ; save FSR
movwf fsr_temp ; without changing flags
decfsz counter, f ; skip on 125th time thru
goto restore ; else exit
movlw D'125' ; reset interrupt counter
movwf counter
movlw sec ; point at sec register
movwf FSR
newdigit: incf INDF, f ; current digit up one
movlw sec ; get difference sec and FSR
subwf FSR, W
call sethi ; use to get high limit + 1
subwf INDF, W ; reached that number yet?
btfss STATUS, Z ; skip over if yes
goto restore ; else exit isr
clrf INDF ; set current digit to 0
incf FSR, f ; point at next digit
btfss hr10, 1 ; has hr10 reached 2?
goto newdigit ; no, increment the next digit
btfss hr, 2 ; has hr reached 4?
goto newdigit ; no
clrf hr ; yes, set hour to 00
clrf hr10 ; and hour 10
restore:
swapf status_temp,W ; get original status back
movwf STATUS ; into status register
swapf fsr_temp,W ; get original fsr back
movwf FSR ; into status register
swapf w_temp,f ; old no flags trick again
swapf w_temp,W ; to restore W
bcf INTCON,T0IF ; clear the TMR0 interrupt flag
retfie ; finished reset GIE
;----------------------------------------------------------------------;
; Increment and display digit pointed to by FSR ;
;----------------------------------------------------------------------;
updigit:
incf INDF, f ; selected digit up one
movlw mins ; set up to subtract mins address
subwf FSR, W ; from address of current digit
call sethi ; get maximum of digit + 1 into W
subwf INDF, W ; is it = to current digit value?
btfsc STATUS, Z ; gives zero if yes, skip if no
clrf INDF ; reset value of digit to zero
movf INDF, W ; get current value and ..
movwf PORTB ; display it
call onesecond ; pause for 1 second
return
;----------------------------------------------------------------------;
; flash LED representing digit position ;
;----------------------------------------------------------------------;
setnext:
movwf digit ; save digit position
flashloop:
clrf PORTB ; all LEDs off
movf digit, W ; restore digit position
btfss flashcnt, 0 ; leave off on odd #'s of counter
movwf PORTB ; flash digit on even #'s
movlw 50 ; delay for 50 msec
call nmsec
incf flashcnt, f ; flip LSB of flashcnt
btfss SHOWPB ; skip over if SHOW not pressed
call updigit ; else increment current digit
btfsc SETPB ; skip over if set pressed
goto flashloop ; continue until pressed again
incf FSR, f ; set up for next digit
call waitsetup ; wait for release
return
;----------------------------------------------------------------------;
; Increment and set digits ;
;----------------------------------------------------------------------;
setdigits:
bcf INTCON, GIE ; no interrupts while setting time
movlw mins ; point at minutes register
movwf FSR
call waitsetup ; wait on set pushbutton up
movlw B'00000001' ; light right LED (mins)
call setnext
movlw B'00000010' ; light min10 LED
call setnext
movlw B'00000100' ; light hr LED
call setnext
movlw B'00001000' ; hr10 LED on
call setnext
clrf PORTB ; clear LEDs
bsf INTCON, GIE ; enable interrupts again
return
;----------------------------------------------------------------------;
; The main routine ;
;----------------------------------------------------------------------;
main:
call init ; set up initial conditions
loop:
btfss SHOWPB ; check for show pushbutton
call disptime ; display the time
btfss SETPB ; check for setting of time
call setdigits
goto loop ; do forever
end
; Note: A 4.096 MHz xtal is needed for accurate timing over long
; periods. You press the SHOW pushbutton to show the time, digit by
; digit. Zeros are shown as all lights on. To set the time you press
; SET. The right most digit will blink indicating minutes are to
; be set. Pressing SET again chooses tens of minutes etc. After tens
; of hours, the LEDs blank and the clock is timing again. While any
; LED is blinking, pressing SHOW will display that digit value and
; increment it every second. Release SHOW when the digit value is what
; you want.
file: /Techref/piclist/cheapic/binclk4m.asm, 13KB, , updated: 2000/12/8 11:59, local time: 2024/11/17 14:01,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/piclist/cheapic/binclk4m.asm"> piclist cheapic binclk4m</A> |
Did you find what you needed?
|